The following contrived examples demonstrate the various aspects of the parameter passing mechanism. With the following program file, DOUBLE.PRG:

parameters arg

arg *= 2 // Double passed parameter

from the Command window, typing the following statements results in the values shown in the comments:

x = 7

double( x ) // Call as variable

? x // Displays 14, pass by reference

double( x + 0 ) // Call as an expression

? x // Displays 14, pass by value

double( (x) ) // Call with parentheses around variable name

? x // Displays 14, pass by value

o = new Object( )

o.x = 5

double( o.x ) // Call as property

? o.x // Displays 10, pass by reference

double( (o.x) ) // Call with parentheses around property name

? o.x // Displays 10, pass by value

With the following program DOUBLEX.PRG, designed specifically to modify the property x of the passed object:

parameters oArg

oArg.x *= 2

typing the following statements in the Command window results in the values shown in the comments:

doublex( o ) // Pass by reference

? o.x // Displays 10, property modified

doublex( (o) ) // Pass by value

? o.x // Displays 20, property still modified

With the following program ILIKEAPP.PRG:

parameter oArg

oArg := _app

passing by value will prevent the object reference itself from being changed:

f = new Form( )

ilikeapp( (f) ) // Pass by value

? f.className // Displays FORM

ilikeapp( f ) // Pass by reference

? f.className // Displays APPLICATION, object reference changed

g = "test" // Another variable, this one with a string

ilikeapp( g ) // Pass by reference

? g.className // Displays APPLICATION, variable changed to an object reference

Note that you when assigning to a variable that was passed by reference, you are free to change the type of the variable.

This example demonstrates what happens if you don’t enclose the special object reference this in parentheses when it is passed to the method of another object. (Codeblocks are used for the methods; codeblocks declare their parameters in-between pipe characters instead of using a PARAMETERS statement.)

f = new Form( "F" ) // text property is "F"

g = new Form( "G" ) // text property is "G"

f.test1 = {; g.meth( this )} // Pass-by-reference

f.test2 = {; g.meth( (this) )} // Pass-by-value

g.meth = {|o|; ? o.text} // Display text property of passed object

f.test1( ) // Pass-by-reference displays "G"

f.test2( ) // Pass-by-value displays "F"

Whenever an object’s method is called, the value of this is automatically updated to point to that object. If the parameter this is passed by reference from the caller, the value of this changes to the called object before it is assigned to the parameter variable. By enclosing the parameter this in parentheses to make it pass-by-value, this does not change, and the parameter value is passed as expected.