In the new English Html help additional information is provided for Function and Sub. Since this is new information a copy of the text has a place in a blogpost.
The return value of a Function can be assigned to a local variable with the same name as the Function. When the return type is a numeric data type a local variable of that type is automatically added to the function’s local variables. With String, Type (UDT) and Variant a by reference variable is passed as the last argument on the stack. The string, UDT or variant becomes the variable that can be used to pass the function’s return value. Therefor, the following is equal:
Dim h$ h$ = testf(8) ' assign result to h$ testp(8, h$) ' put result in h$
Function testf(a%) As String testf = "3" & a%
Procedure testp(a%, ByRef p$) p$ = "3" & a%
In the function testf the variable h$ is silently passed on the stack. Inside the function this by reference variable is known as testf. Assigning a new string to testf actually assigns the string to h$ directly.
When a Function is used for a Windows API callback make sure the return data type is a primary numeric type (Byte, Word, Long, Int64, Single, Double), otherwise the stack will be overwritten.
To provide compatibility with VB’s Sub, which - for instance - allows to pass literal values by reference(!), GB offers a special type of calling convention for the Sub. This GB implementation for Sub differs from the usual way of passing parameters by reference. The default state for passing arguments to a Sub is an implicit by reference; by omitting the ByVal or ByRef keywords the arguments are passed by reference. However, there is a difference between the default ByRef and an explicit ByRef.
When in a Sub declaration ByRef is omitted the argument is first copied to a hidden local variable whose address is then passed by reference. The data type of the hidden local copy depends on the data type of the implicit ByRef parameter. So, a Sub parameter without explicit ByRef does not modify the variable (actual or hidden) that is passed to the Sub. This way it is possible to pass incompatible data types by reference. It also allows for passing literal values because they are first copied to a hidden local variable that is then passed by reference. For the sub these implicit by reference variables are a kind-of ‘read-only’ since using them doesn’t influence the value that was passed to the sub.
This adds an additional feature to the GB-language. In contrast with by value parameters, that require a copy of an argument on the stack, implicit ByRef makes a copy first and then puts the address of that copy on the stack. To prevent the creation and passing of hidden local copies, ByRef must be included explicitly in the Sub declaration. Doing so ensures that only actual variables of the correct type are passed to the Sub.
Example of implicit by reference:
Dim vnt test(7) ' 7 is assigned to a local Variant first test(vnt) ' vnt is copied to a local Variant first Sub test(vnt As Variant) ' implicit ByRef, read-only vnt = "new Value" ' not returned to caller
Example of explicit by reference calling convention:
testbyref(7) ' syntax error: variable expected testbyref(vnt) ' vnt itself is passed Sub testbyref(ByRef vnt As Variant) vnt = "new value"