-> Passing by value makes a copy of the parameter. If you change the copy
-> the original doesn't change. With pass by reference, the address of
the
-> variable is passed. If you change the parameter variable in the SUB,
it
-> will be changed in the main program.
-> Here's an example. If the following program p***** by value it will
print
-> 5 since the SUB can't change the value of its parameter.. If it p*****
by
-> reference, it will print 2.
-> a=5
-> CALL test(a)
-> PRINT a
-> SUB test(b)
-> b=2
-> END SUB
-> Tom Lake
Thanks Tom, and others. Now I get it.
But, in programs I write, I frequently and deliberately change the
values of parameters within SUBs, and expect the changed values to be
passed back to the calling routines. Sometimes, I have variables that
are used only to *output* numbers from SUBs (or FUNCTIONs) to the
calling routines. For example, I might write something like this:
FUNCTION TrueMod! (Divisor!, Dividend!, Quotient%)
Quotient% = INT(Dividend! / Divisor!)
TrueMod = Dividend! - Quotient% * Divisor!
END FUNCTION
If the calling routine says:
A = 7
B = -53.5
PRINT TrueMod(A, B, C%);
PRINT C%
The output will be:
2.5 -8
Note that the variable C% is used to pass the quotient out from the
FUNCTION to the calling routine. On the way in, C% has no specified
value, and is there just to specify the name of the variable in which
the quotient output will appear.
I guess I'm making use of BASIC's usage of passing by reference,
rather than by value. I wouldn't like to be deprived of this way of
doing things.
Sure, it is possible to make mistakes. This is always true. A language
that protects the programmer from all mistakes would be no language at
all.
dow
P.S. Here is a real program that makes extensive use of this kind of
thing. Look at the SUBs D2P and P2D, and how they are used.
---------------------------------------------------------
' SunAlign.BAS (Version for QBasic and similar dialects)
' Calculates position of sun in sky, as azimuth (compass bearing
' measured clockwise from True North) and angle of elevation, as
' seen from any place on earth, on any date and any time.
' Also calculates alignment of a heliostat mirror.
' David Williams
' P.O. Box 48512
' 3605 Lakeshore Blvd. West
' Toronto, Ontario. M8W 4Y6
' Canada
' Initially dated 2007 Jul 07
' This version 2007 Oct 07
DECLARE FUNCTION ET.Dec (D, F%)
DECLARE FUNCTION ROff$ (X)
DECLARE SUB D2P (X, Y, Z, AZ, EL)
DECLARE SUB P2D (AZ, EL, X, Y, Z)
DECLARE FUNCTION Ang (X, Y)
CONST PY = 3.1415926536# ' "PI" not assignable in some BASICs
CONST DR = 180 / PY ' degree / radian factor
' Note: For brevity, no error checks on user inputs
CLS
PRINT "Use negative numbers for directions opposite to those shown."
INPUT "Observer's latitude (degrees North)"; LT
INPUT "Observer's longitude (degrees East)"; LG
INPUT "Date (M#,D#)"; Mth%, Day%
INPUT "Time (HH,MM) (24-hr format)"; HR, MIN
INPUT "Time Zone (+/- hours from GMT/UT)"; TZN
D = INT(30.6 * ((Mth% + 9) MOD 12) + 58.5 + Day%) MOD 365
ET = ET.Dec(D, 1) ' Equation of Time
DC = ET.Dec(D, 0) ' Declination
LD = 15 * (HR - TZN) + (MIN + ET) / 4 + LG 'longitude difference
CALL P2D(LD, DC, sX, sY, sZ)
CALL D2P(sY, sZ, sX, qAZ, qEL)
CALL P2D(qAZ + LT - 90, qEL, sY, sZ, sX)
CALL D2P(sX, sY, sZ, sAZ, sEL)
PRINT
IF sEL < 0 THEN PRINT "Sun Below Horizon": END
PRINT "Sun's azimuth: "; ROff$(sAZ); " degrees"
PRINT "Sun's elevation: "; ROff$(sEL); " degrees"
PRINT
PRINT "Calculate heliostat mirror alignment? (y/n) ";
DO
K$ = UCASE$(INKEY$)
LOOP UNTIL K$ = "Y" OR K$ = "N"
PRINT K$
IF K$ = "Y" THEN
PRINT
INPUT "Azimuth of target direction (degrees)"; tAZ
INPUT "Elevation of target direction (degrees)"; tEL
CALL P2D(tAZ, tEL, tX, tY, tZ)
CALL D2P(sX + tX, sY + tY, sZ + tZ, mAZ, mEL)
PRINT
PRINT "Mirror aim direction (perpendicular to surface):"
PRINT "Azimuth: "; ROff$(mAZ); " degrees"
PRINT "Elevation: "; ROff$(mEL); " degrees"
END IF
END
FUNCTION Ang (X, Y)
' calculates angle between positive X axis and vector to (X,Y)
IF X = 0 THEN
A = SGN(Y) * PY / 2
ELSE
A = ATN(Y / X)
IF X < 0 THEN A = A + PY
END IF
Ang = A
END FUNCTION
SUB D2P (X, Y, Z, AZ, EL)
' convert from X,Y,Z to AZ, EL
' Outputs in degrees
EL = Ang(SQR(X * X + Y * Y), Z) * DR
A = Ang(Y, X) * DR
IF A < 180 THEN AZ = A + 180 ELSE AZ = A - 180
END SUB
FUNCTION ET.Dec (D, F%) STATIC
' Calculates equation of time, in minutes, or solar declination,
' in degrees, on day number D of year. (D = 0 on January 1.)
' F% selects function: True (non-zero) for Equation of Time,
' False (zero) for Declination.
' STATIC means variables are preserved between calls of function
' This version assumes PY (PI) and DR (180/PI) are initialized
IF W = 0 THEN ' first call, initialize constants
W = 2 * PY / 365 ' earth's mean orbital angular speed in radians/day
C = -23.45 / DR ' reverse angle of earth's axial tilt in radians
ST = SIN(C) ' sine of reverse tilt
CT = COS(C) ' cosine of reverse tilt
E2 = 2 * .0167 ' twice earth's orbital eccentricity
SP = 12 * W ' 12 days from December solstice to perihelion
D1 = -1 ' holds last D. Saves time if D repeated for both functions
END IF
IF D <> D1 THEN ' new value of D
A = W * (D + 10) ' Solstice 10 days before Jan 1
B = A + E2 * SIN(A - SP)
D1 = D
END IF
IF F% THEN ' equation of time calculation
C = (A - ATN(TAN(B) / CT)) / PY
ET.Dec = 720 * (C - INT(C + .5))
' in 720 minutes, earth rotates PI radians relative to sun
ELSE ' declination calculation
C = ST * COS(B)
ET.Dec = ATN(C / SQR(1 - C * C)) * DR
' arcsine of C in degrees. ASN not directly available in QBasic
END IF
END FUNCTION
SUB P2D (AZ, EL, X, Y, Z)
' convert from AZ,EL to X,Y,Z
' Inputs in degrees
E = EL / DR
A = AZ / DR
Z = SIN(E)
C = -COS(E)
X = C * SIN(A)
Y = C * COS(A)
END SUB
FUNCTION ROff$ (X)
' neatly rounds number to one place of decimals
S$ = LTRIM$(STR$(INT(10 * ABS(X) + .5)))
IF S$ = "3600" THEN S$ = "0"
IF LEN(S$) = 1 THEN S$ = "0" + S$
IF X < 0 THEN IF VAL(S$) THEN S$ = "-" + S$
ROff$ = LEFT$(S$, LEN(S$) - 1) + "." + RIGHT$(S$, 1)
END FUNCTION
-------------------------------------------------------


|