A question about call by reference
Moderators: FourthWorld, heatherlaine, Klaus, kevinmiller
Re: A question about call by reference
That is what I was saying. The @ means that you must use a variable when calling the function/handler.
Re: A question about call by reference
Brian.
I get that. My point was "how does the command handler know it is being set up for failure"?
Stepping through the script, with no "@", everything goes swimmingly. You get a "42".
But put the "@" in, and an error is thrown at the call to the command handler back up in "mouseUp". I am just wondering how LC knows about the impending failure. The script again:
Craig
I get that. My point was "how does the command handler know it is being set up for failure"?
Stepping through the script, with no "@", everything goes swimmingly. You get a "42".
But put the "@" in, and an error is thrown at the call to the command handler back up in "mouseUp". I am just wondering how LC knows about the impending failure. The script again:
Code: Select all
on mouseUp
put 5 into a
testhandler testFunction(a)
end mouseUp
function testFunction a
return 42
end testFunction
--on testHandler a --works
on testHandler @a --fails, before it even is reached
answer a
end testHandler
Re: A question about call by reference
Probably a question for LCMark. I'll try... the type of data that you are passing is immutable and the handler requires a mutable variable. Try it with any other constant and you get the same thing. When the interpreter gets to setting up the call to testhandler, it is trying to create a pointer to a variable being passed in (instead of setting up a copy on write variable which would automatically turn a constant into a mutable variable). I'm sure my words aren't exactly correct, but I think I understand the idea.
The compiler could flag it as an error, but I don't think any parameter checking is done at compile time. Probably something that would make sense to add once (optional) type checking is added.
The compiler could flag it as an error, but I don't think any parameter checking is done at compile time. Probably something that would make sense to add once (optional) type checking is added.
-
- Posts: 43
- Joined: Fri Aug 21, 2020 7:06 pm
Re: A question about call by reference
Thanks to all who responded.
It appears that the correct answer is that any value returned by a function cannot be used as a reference parameter to a handler.
My hypothesis that the problem was that in one case, the value returned by the function was extracted from an array, while in the other case it was a simple value, turns out to be wrong.
A button with this script fails in both cases, but after removing the "@" in the myHandler formal parameter, both statements succeed.
It appears that the correct answer is that any value returned by a function cannot be used as a reference parameter to a handler.
My hypothesis that the problem was that in one case, the value returned by the function was extracted from an array, while in the other case it was a simple value, turns out to be wrong.
A button with this script fails in both cases, but after removing the "@" in the myHandler formal parameter, both statements succeed.
Code: Select all
on mouseUp
local tInstanceVariable
put newClassName() into tInstanceVariable
-- both of the following statements cause this runtime error:
-- Execution error at line 30 (Handler: error in parameter expresion) near "myHandler" char 1
myHandler getBeta(tInstanceVariable)
myHandler getBread("whole wheat")
end mouseUp
function newClassName
local tObject
put 3.14159 into tObject["mAlpha"]
put "a very long string" into tObject["mBeta"]
put true into tObject["mGamma"]
return tObject
end newClassName
function getBeta pInstanceVariable
return pInstanceVariable["mBeta"]
end getBeta
function getBread pString -- value parameter
return "pumpernickel"
end getBread
on myHandler @pString -- reference parameter -- this is line 31 in this script
put "Result is" && pString into msg
end myHandler
Re: A question about call by reference
At times @ can save surprisingly much if the value of the passed variable changes between passing.bwmilby wrote: ↑Sun Feb 07, 2021 5:31 am.........
As stated earlier, if you are not changing the value then there is probably not a huge cost since the engine does a copy on write. (In a tight loop with many calls you could achieve some speed gains by explicitly doing a pass by reference since the engine wouldn't need to set up the additional variable that supported the copy on write. I did a quick test and the difference was roughly 10ms for 50,000 calls passing a simple integer without changing the value.)
As a short experiment:
In the ScriptEditor a tab formats a handler, shiftKey-tab formats the entire script. Formatting an entire script is time intensive.
In script of stack "com.livecode.scripteditor.behavior.editorcommon" of the IDE (access it via Project Browser with "show IDE Stacks in Lists" = checked in Menu "View") make changes to record the time (line 3323)
Code: Select all
command scriptFormat pScope, pDontGroup
lock screen
local tScroll, t -- added t
put the milliseconds into t -- added
....
-- code
-- code
....
put the milliseconds -t && the milliseconds -- added
set the vScroll of field "Script" of me to tScroll
unlock screen
end scriptFormat
or
the script of stack "com.livecode.library.dropbox" 5000+ lines of code
Do "shiftKey-tab" a couple of times. Note the milliseconds it takes
Now change again in stack "com.livecode.scripteditor.behavior.editorcommon" at line 540 handler "private function textFormatLine"
from
Code: Select all
private function textFormatLine pLine, pTextLines, @xPreviousLine
Code: Select all
private function textFormatLine pLine, @pTextLines, @xPreviousLine
In my testing for 11000+ lines in unchanged version it takes 4600 milliseconds, adding @ it takes 2500 milliseconds
For 5000+ lines 1600 down to 1000+ milliseconds.
That is not bad for a simple "@" added.
These changes to the the IDE are not persistent and next time you open LC they are gone.
Kind regards
Bernd
Re: A question about call by reference
To make it easier to test passing parameters by reference or without for variables that change in between passing here is a stack to test without fiddling with the IDE as in the example above. Though that is a real world example.
In the stack below you have the option to load some IDE stacks of different length and test 10000 passing of the styledArray of those stacks with or without passing them by reference.
In both cases one char is changed in the styledText array in between passing.
Without change to the variable in between passing the difference between passing with or without reference is negligible.
Kind regards
Bernd
In the stack below you have the option to load some IDE stacks of different length and test 10000 passing of the styledArray of those stacks with or without passing them by reference.
In both cases one char is changed in the styledText array in between passing.
Without change to the variable in between passing the difference between passing with or without reference is negligible.
Kind regards
Bernd
Re: A question about call by reference
Bernd,
That is a not-so-insignificant improvement. I wonder if that would be something to suggest to the team as an improvement? I have not looked at the code in that handler though.
Thanks,
Brian
That is a not-so-insignificant improvement. I wonder if that would be something to suggest to the team as an improvement? I have not looked at the code in that handler though.
Thanks,
Brian
Re: A question about call by reference
Brian,
these are pretty extrem cases in the IDE but they show nicely what @ can do when used in the right place.
Maybe when the team has more time to look at stuff like this I will make a pull-request.
Kind regards
Bernd
-
- Posts: 683
- Joined: Wed Apr 24, 2013 4:53 pm
- Contact:
Re: A question about call by reference
The only time I've actually seen someone use this was in UDI's PMD (Play MIDI Data) LCS library that creates MIDI file data from HyperCard "ABC" style musical notation. I did some tests while modifying/dissecting his work, with and without @ symbol, and it did indeed have a significant impact on speed. Of course that was way back about a decade ago (on a mobile Core2Duo) so I'm not sure it would be all that significant now. Probably still very much worth using in certain situations and it's basically carpal-tunnel neutral at only one more character to type.At times @ can save surprisingly much if the value of the passed variable changes between passing.