Page 2 of 2
Error XS0161 not all Code paths Return a Value
Posted: Fri Oct 18, 2019 6:11 pm
by FoxProMatt
There is a setting that can control whether values passed to Functions are passed by Value or by Reference.
From VFP Help:
Code: Select all
SET UDFPARMS TO VALUE (default)
SET UDFPARMS TO REFERENCE
Code: Select all
SET UDFPARAMS
Specifies whether Visual FoxPro passes variables by Value or by Reference to parameters in procedures and user-defined functions (UDFs).
TO VALUE
--------------
Pass variables to parameters by value. When passing variables by value, the procedure or function can change the value in the variable; however, the original value of the variable in the calling program does not change. (Default)
Note
Using SET UDFPARMS TO VALUE does not affect the WITH clause in the DO command, which, by default, passes arguments to parameters by reference.
TO REFERENCE
---------------------
Pass variables to parameters by reference. When passing variables by reference, the procedure or function can change the value in the variable, which changes the original value of the variable in the calling program.
Error XS0161 not all Code paths Return a Value
Posted: Fri Oct 18, 2019 6:31 pm
by robert
Chris,
Chris Pyrgas wrote:Hi Matt,
But how can they be used interchangeably, when they have different semantics in VFP? Functions pass values by value, while Procedures pass values by reference. We do not have that difference in VO (or other xBase dialects that I know of), but this behavior will be implemented for the VFP dialect.
Well that is not entirely correct as well.
The only real difference is that procedures do not return a value.
It is the DO <proc> [WITH <params>] syntax that passes variables by reference. And in this case <proc> can also be a function.
And the Func(..) syntax passes variables by value, unless you add the @ sign in front of a variable name.
But you can also call a procedure with the <proc>(...) syntax, in which case the parameters are again by value.
Of course the normal behavior would be to:
- Call procedure with the DO Proc WITH params syntax
- Call functions with the <Func>( params ) syntax.
Robert
Error XS0161 not all Code paths Return a Value
Posted: Fri Oct 18, 2019 6:33 pm
by FoxProMatt
Chris said
Functions pass values by value, while Procedures pass values by reference.
Chris - I don't think this is true... VFP Says the same thing for FUNCTION and PROCEDURE:
"By default, parameters are passed to procedures by value."
*BOTH* receive params by value, according to the VFP Help file.
However, I just tested this and I see that (single value) variables are indeed passed by value by default, yet if I pass an OBJECT to a Function, the Object is passed by reference, even when UDFPARMS is set to VALUE, and it can be changed in the called Function.
Example:
(In example below, I go the same exact results whether I used FUNCTION or PROCEDURE"
Code: Select all
Clear
*-- 1. Pass an Object (it's passed by Reference)
loData = CreateObject("Empty")
AddProperty(loData, "Name", "Chris")
?loData.Name && Prints Chris
ChangeNameObject(loData)
? loData.Name && Now Prints Robert
? "----"
*-- 2. Pass var, it's passed by value by default...
Set Udfparms To Value && Default
lcName = "Chris"
?lcName && Prints Chris
ChangeNamevar(lcName)
?lcName && Prints Chris
? "----"
*-- 3. Pass var by reference (with change to UDFPRAM)
Set UDFParms To Reference
lcName = "Chris"
?lcName && Prints Chris
ChangeNamevar(lcName)
?lcName && Now prints Robert
? "----"
*-- 4. Pass var by Refernece with "@" prefix
Set Udfparms To Value && Default
lcName = "Chris"
?lcName && Prints Chris
ChangeNamevar(@lcName)
?lcName && Prints Robert
? "----"
*-------------------------------
Procedure ChangeNameObject(toData)
toData.Name = "Robert"
EndFunc
*-------------------------------
Procedure ChangeNameVar(tcName)
tcName = "Robert"
Endfunc
Error XS0161 not all Code paths Return a Value
Posted: Fri Oct 18, 2019 6:40 pm
by robert
Matt,
Matt Slay wrote:Chris said
yet if I pass an OBJECT to a Function, the Object is passed by reference, even when UDFPARMS is set to VALUE, and it can be changed in the called Function.
This is a common mistake: the object is a reference type. The object
reference is passed by value. But the copy of that reference has the same value as the original, so both references point to the same memory location.
However if you assign a new value to the object inside NameObject then the reference inside NameObject will point to the new object where the original loData will still point to the original object.
Robert
Error XS0161 not all Code paths Return a Value
Posted: Fri Oct 18, 2019 7:05 pm
by FoxProMatt
However if you assign a new value to the object inside NameObject then the reference inside NameObject will point to the new object where the original loData will still point to the original object.
Robert - The line:
in example 1 now prints "Robert" after the Function call. So the called function changed the local loData object.
Error XS0161 not all Code paths Return a Value
Posted: Fri Oct 18, 2019 9:36 pm
by mainhatten
Matt Slay wrote:However if you assign a new value to the object inside NameObject then the reference inside
Robert - NameObject will point to the new object where the original loData will still point to the original object.
The line:
in example 1 now prints "Robert" after the Function call. So the called function changed the local loData object.
What Robert meant is when doing a createobject() ito the parameter nside a call via reference, that new object will be "alive" after the function call returns, and might be a car instead of a person. If you call by value, the object stays a person, even if name is changed
Error XS0161 not all Code paths Return a Value
Posted: Sat Oct 19, 2019 7:12 am
by robert
Matt,
Put the following code inside ChangeNameObject()
Code: Select all
loData = CreateObject("Empty")
AddProperty(loData, "Name", "Robert")
Then you'll see that afterwards the original loData still has its original value.
So the function gets a copy of the reference to loData. If you change loData inside the called function then the original copy still has a reference to the original loData.
Robert