Using '@' to mark pass-by-reference (was Re: synonyms)
Mark Waddingham
mark at livecode.com
Fri Aug 18 11:38:15 EDT 2017
On 2017-08-18 17:18, Bob Sneidar via use-livecode wrote:
> That actually is a great explanation which solves a mystery I've often
> wondnered about, which is how a handler with a different variable name
> can contain the *actual* original variable. I thought the engine
> actually created a new variable and copied the incoming value to it,
> and then reversed this operation on return. Aliasing makes perfect
> sense.
That's what would call 'inout' parameter mode.
For most languages which exist today, the way you can specify to pass
parameters to functions distills down into 4 types (generally these are
called parameter 'modes'):
- by-ref
- by-value (also called 'in')
- copy-out (generally called 'out')
- copy-in-copy-out (generally called 'inout')
Let us imagine we supported all these modes and we had a handler with
signature:
command myHandler @yRef, in pIn, out rOut, inout xInOut
Called with
myHandler tRef, tIn, tOut, tInOut
The 'by-value'/'in' mode is what we are most familiar with. On entry to
the handler the value in pIn is copied into the receiving variable tIn.
The 'out' mode is similar to what you describe. On entry to the handler
rOut contains nothing; on exit from the handler, the value in rOut is
'copied back' into the passed variable tOut.
The 'inout' mode is a mixture of the two: on entry tInOut is copied into
xInOut, and on exit xInOut is copied back into tInOut.
In the 'by-ref' mode there is no copying at all - mutations to the
receiving variable yRef are actually mutations to the passed variable
tRef. i.e. yRef doesn't really exist at all.
The by-ref mode can emulate all of the other modes - you just have to
code with some rules:
To use a by-ref parameter as 'in' - you must not change the value of the
parameter in the handler being called.
To use a by-ref parameter as 'out' - you must not read the parameter at
all and only change the value of the parameter except just before you
exit/return.
To use a by-ref parameter as 'inout' - you can read the parameter at any
point, but only change it just before you exit/return.
In most languages, the 'copy-back' part of the 'out' and 'inout' modes
only generally happen for normal handler exit - they don't happen if you
throw an exception.
Now, having said all of that - there is actually a fifth parameter mode
'call-by-name' which at least one language had - ALGOL. Basically this
meant (IIRC) that you passed in the symbolic expression to the receiver
so it acted as some kind of macro:
foo(tArray[I]) - inside foo, any reference to that parameter would
re-evaluate tArray[I] in the context of the caller.
The reason I mention this is because the way LiveCode does by-ref
parameters for array elements is *almost* like this - but not quite as
unwieldy. When you do:
command myHandler @xVar
put 100 into xVar["baz"]
end myHandler
local tArray
myHandler tArray[tIndex1][tIndex2]
What actually happens is somewhat equivalent to the following:
local tArrayPath
put tIndex1 into tArrayPath[1]
put tIndex2 into tArrayPath[2]
myHandlerModified tArray, tArrayPath -- a second parameter has been
added here
With
command myHandlerModified @xArray, pArrayPath
put 100 into xArray[pArrayPath]["baz"]
end myHandlerModified
Basically, the 'path' is frozen before the call, but implicitly used
within the call when mutating the by-ref variable.
Warmest Regards,
Mark.
--
Mark Waddingham ~ mark at livecode.com ~ http://www.livecode.com/
LiveCode: Everyone can create apps
More information about the use-livecode
mailing list