History: ByRef was introduced in VDF 11.0. It allows parameters to be passed "by reference" to a procedure/function.
Combining with VDF's "Implicit Type Conversion", you've got some nasty bugs.
Use UI
Procedure StringByValue String sParam
Move (sParam+"A") to sParam
End_Procedure
Procedure StringByRef String ByRef sParam
Move (sParam+"A") to sParam
End_Procedure
String sString
Move "123" to sParam
Send StringByValue sParam // sParam will still be "123"
Send StringByRef (&sParam) // sParam will be "123A"
InKey FieldIndex
If a parameter is passed by value, regardless of what happens inside the subroutine, no changes will be applied to the caller's parameter.
If a parameter is passed by reference, any changes you make to the parameter within the subroutine will be applied to the caller's parameter.
So far so good.
Use UI
Procedure StringByValue String sParam
Move (sParam+"A") to sParam
Showln sParam
End_Procedure
Send StringByValue 123 // Showln will show 123A
Send StringByValue (CurrentDateTime()) // Showln will show 6/12/2020 5:58:00.000 PMA
Procedure IntegerByValue Integer iParam
Move (iParam + 2) to iParam
Showln iParam
End_Procedure
Send IntegerByValue "1" // Showln will show 3
Send IntegerByValue (CurrentDateTime()) // ERROR here, see explanation below.
InKey FieldIndex
This is good-old VDF implicit type conversion. StringByValue is expecting a string. However you can totally call StringByValue with
any data type that can be coerced (converted) into a string. The same concept applies to the procedure IntegerByValue. When you pass a
data type that can not be coerced into the target data type (In this scenario, trying to convert a DateTime type into an Integer type),
you will get the runtime error Illegal Datatype Conversion.
So far so good.
Here comes puzzle time!!
Use UI
Procedure AddCurrencySign String ByRef sVal
Move ("$"+sVal) to sVal
End_Procedure
Procedure ShowStringWithCurrencySign String sVal
Send AddCurrencySign (&sVal)
Showln sVal // What will be shown???
End_Procedure
Number nNum
Move 12.22 to nNum
Send ShowStringWithCurrencySign nNum
InKey FieldIndex
What will be shown? Is it $12.22? The answer is $. But why?
The procedures AddCurrencySign and ShowStringWithCurrencySign both look good. There
is no syntax error or runtime error. What happened?
Use UI
Procedure TestByRef String ByRef s1 String ByRef s2
Showln (s1+s2) // What will be shown???
End_Procedure
Procedure Test String s1 String s2
Showln (s1+s2) // What will be shown???
Send TestByRef (&s1) (&s2)
End_Procedure
Send Test 56 78
InKey FieldNumber
Here comes another similar puzzle - What will be shown? On Line 8, as you might have guessed - "5678". What about Line 4? You get a blank string.
Use WinShell.pkg
Procedure RemoveExt String sFile
Integer iVoid
Move (PathRemoveExtension(AddressOf(sFile))) to iVoid
End_Procedure
Procedure ByRefProc String ByRef sFile
Showln "Before " sFile // Hello.txt
Send RemoveExt sFile // I am passing sFile by value into RemoveExt
Showln "After " sFile // Hello
End_Procedure
Procedure Main
String sLocalFile
Move "Hello.txt" to sLocalFile
Send ByRefProc (&sLocalFile)
End_Procedure
Send Main
InKey FieldIndex
PathRemoveExtension
is a Windows API call that removes the file extension from a file name. Here is another puzzle -
sFile inside ByRefProc was changed by RemoveExt? But how?
Use UI
Procedure Method_C String ByRef sParam
Move 'Voodoo' to sParam
End_Procedure
Procedure Method_B String sParam
Send Method_C (&sParam)
End_Procedure
Procedure Method_A
String sTest
Send Method_B // Not passing any parameter!
Showln "sTest: " sTest
InKey FieldIndex
End_Procedure
Send Method_A
// sTest now contains the string "Voodoo"
I have no explanation for this one. That's just pure VDF voodoo.