Hi reader,
The following AppleScript does not work. When run in “Script Debugger”, it fails at the call to “addtwonumbers(x,y)” claiming that this entity is not understood - i.e., it can’t be located/accessed.
Commenting out the line “property parent : AppleScript” allows it to work as expected.
The question is -
if I use “property parent : AppleScript”
how can I get the encapsulated handlers get to external handlers
The reason I want to use the the “property parent : AppleScript” is that if I do not - “LNS Script Debugger” states that there is an “internal table overflow”, throws an error and will not allow me to debug the script in debug mode (the internal table overflow message does not occur when debug mode is switched off). The script itself is not that big - a hundred lines or so. The problem causing the internal table overflow error appears to be the result of several objects being defined and initialized.
Anyway - any suggestions how one might solve this problem would be much appreciated.
use AppleScript version "2.4" -- Yosemite (10.10) or later
use scripting additions
on addtwonumbers(a as integer, b as integer)
return (a + b)
end addtwonumbers
on encapsScript()
script abc
property parent : AppleScript
property c : 0 as integer
on testThis(x as integer, y as integer)
set c to addtwonumbers(x, y)
return (c)
end testThis
end script -- abc
end encapsScript
local d
set es to encapsScript()
tell es
set d to testThis(1, 2)
end tell
d
Two suggestions:
-
Don’t try to solve the problem by using a parent property like that. It’s not the answer (as you have already found out).
-
Don’t try to treat AS handlers as objects; they’re not, and even though they sometimes appear to behave as such, it is at best undefined bahavior. If you want an object, use a script object:
use AppleScript version "2.4" -- Yosemite (10.10) or later
use scripting additions
on addtwonumbers(a as integer, b as integer)
return (a + b)
end addtwonumbers
script abc
property c : 0 as integer
on testThis(x as integer, y as integer)
set c to addtwonumbers(x, y)
return (c)
end testThis
end script -- abc
local d
tell abc
set d to testThis(1, 2)
end tell
d
Hi Shane and other interested readers,
Thanks for the suggestions - intriguing! When I read AppleScript language references several suggested that by wrapping a “script” in a AS handler I could use the construct to create instances of a scrip object. This became useful because I could then do something like in the code snippet below (which is using the construct like it was an object).
The result is effectively two objects that have different local storage states.
As you point out - this construct and usage creates problems that can be masked by using a parent property - but that has side effects as well. So better to avoid this method.
Is there a syntax that allows me to do what I want a script object (creating separate instances) without using an AS handler?
If not I will have to rethink how I use AppleScript.
use AppleScript version "2.4" -- Yosemite (10.10) or later
use scripting additions
on addtwonumbers(a as integer, b as integer)
return (a + b)
end addtwonumbers
on encapsScript()
script abc
property parent : AppleScript
property c : 0 as integer
on testThis(x as integer, y as integer)
set c to addtwonumbers(x, y)
return (c)
end testThis
end script -- abc
end encapsScript
local d
set es1 to encapsScript()
tell es1
set d to testThis(1, 2)
end tell
set es2 to encapsScript()
tell es2
set e to testThis(4, 5)
end tell
Hi. Perhaps I don’t understand the question or goal, as I’m not really sure why an object is needed to have something be local. Things defined within a handler are local instances, unless explicitly made global; my example violates the handler’s stated purpose of simply adding two numbers, but it demonstrates this point.
set c to 20
display dialog addTwoNumbers(1, 2) -->10, since local c was added to last handler operation
display dialog c -->20, since global c
#global c --if enabled, c will be set by the handler; in this case -->7
on addTwoNumbers(a, b)
set c to 7
(a + b) + c
end addTwoNumbers
Your original code without the parent property is doing what you want. The handler is returning its last result, which is a script object. If you’re getting internal table overflows, you need to try to work out why that’s happening.
Having said that, my personal opinion is that although AppleScript is in theory an OOP language in this sense, using it as such is often unnecessary, and sometimes problematic.
There is another method like this:
script anClass
property anValue : missing value
on setValue(val)
set my anValue to val
end setValue
on getValue()
return my anValue
end getValue
end script
copy anClass to instance1
copy anClass to instance2
instance1's setValue(1)
instance2's setValue(2)
return {instance1's getValue(), instance2's getValue()}
Basically the handler method and using copy are doing the same, they create an instance by copying an script object. There is however one major difference and that that the handler method is dynamic while the copy method is static. For example with the handler method you can send an parent property while that is not possible using copy.
on createInstance(_parent)
script -- anonymous
property parent : _parent
end script
end createInstance
on add(a, b)
return a + b
end add
set o to createInstance(me)
o's add(4, 5) -- Result: 9
set o to createInstance(AppleScript)
o's add(4, 5) -- Result: error
Last time I gave not entirely correct information, so I deleted the post. Although my main point was correct: setting the parent property of the abc script to AppleScript or to me is not possible at compile time (explicitly). Because the compiler is smart and sees a violation of the OOP concept in this.
The fact is that in this case the abc script inherits all properties and all handlers of the head script, including the handler in which it is encapsulated. It is like a snake swallowing its tail.
But setting the parent property of the abc script to AppleScript or to me is possible at runtime.
The exact answer to the OP’s question is in the following script. I specially added additional handlers of 2 levels to it: 1) belonging to the head script and 2) belonging to scripts b and c. Tested:
use AppleScript version "2.4" -- Yosemite (10.10) or later
use scripting additions
property parent : AppleScript -- or, me -- I made it explicit to understand better
on addtwonumbers(a as integer, b as integer)
return (a + b * b)
end addtwonumbers
script b
property c : 0
on addtwonumbers(a as integer, b as integer)
return (a + b)
end addtwonumbers
end script
script c
property c : 0
on addtwonumbers(a as integer, b as integer)
return (a + a + b)
end addtwonumbers
end script
on encapsScript(_parent)
script abc
property parent : _parent -- its own parent property
property d : 500
end script -- abc
end encapsScript
set es1 to encapsScript(b) -- set its own parent property to «script b»
tell es1 to addtwonumbers(1, 2) -- result:3
set es1 to encapsScript(c) -- set its own parent property to «script c»
tell es1 to addtwonumbers(1, 2) -- result:4
set es1 to encapsScript(me) -- set its own parent property to header script
tell es1 to addtwonumbers(1, 2) -- result:5