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