xsharp.eu • Error XS0161 not all Code paths Return a Value - Page 2
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:

Code: Select all

?loData.Name
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.

Code: Select all

?loData.Name
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