Error XS0161 not all Code paths Return a Value

This forum is meant for questions about the Visual FoxPro Language support in X#.

FoxProMatt

Error XS0161 not all Code paths Return a Value

Post 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.


User avatar
robert
Posts: 4540
Joined: Fri Aug 21, 2015 10:57 am
Location: Netherlands

Error XS0161 not all Code paths Return a Value

Post 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
XSharp Development Team
The Netherlands
robert@xsharp.eu
FoxProMatt

Error XS0161 not all Code paths Return a Value

Post 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




User avatar
robert
Posts: 4540
Joined: Fri Aug 21, 2015 10:57 am
Location: Netherlands

Error XS0161 not all Code paths Return a Value

Post 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
XSharp Development Team
The Netherlands
robert@xsharp.eu
FoxProMatt

Error XS0161 not all Code paths Return a Value

Post 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.
mainhatten
Posts: 200
Joined: Wed Oct 09, 2019 6:51 pm

Error XS0161 not all Code paths Return a Value

Post 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
User avatar
robert
Posts: 4540
Joined: Fri Aug 21, 2015 10:57 am
Location: Netherlands

Error XS0161 not all Code paths Return a Value

Post 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
XSharp Development Team
The Netherlands
robert@xsharp.eu
Post Reply