Re: Inheritance, Context, Scope, etc.
Re: Inheritance, Context, Scope, etc.
- Subject: Re: Inheritance, Context, Scope, etc.
- From: Axel Luttgens <email@hidden>
- Date: Sun, 25 Jan 2004 18:03:04 +0100
Sorry, once again a bit long, so...
[ === PART I ===]
On 23/01/04 2:07, Wallace, William wrote:
[...] Emmanuel pointed out that I had the wrong definition for the
error, but it didn't really help me understand what was going on
there. In this case it seemed that a script object could not set the
value of a global variable unless it was both declared as global AND
initialized to an arbitrary value in the top level of the main script.
You touch on this in your example 21, but I'd like to understand the
logic behind this behavior better. [...]
On 23/01/04 19:32, Wallace, William wrote:
[...] But I still wouldn't mind hearing from Mr. Nebel (or anyone else
who may know) about the underlying philosophy for this behavior. I now
know how to enable child script objects to change the value of their
parent's global variables, but I'm still curious as to why it is
forbidden for a child script object to be able to set the initial
value for a parent's global variable (I mean how could this be a bad
thing?). [...]
You already got some replies to above messages, but I'm fearing you were
in fact somehow confusing properties with globals, while the replies
took the word "global" literally.
INHERITANCE AND SCOPE
=====================
Unless I'm wrong, the whole matter started with your message "Error
Number: -10006 H-E-L-L-L-P!"; here follows a really simplified version
of your original code:
-- Example 1
--main script
global w
set m to load script alias "path:to:loaded:script"
m's doIt()
display dialog w
--loaded script
to doIt()
set my parent's w to (item 1 of my parent's y)
--> error -10006: cant set w to ...
end doIt
Emmanuel provided you with the error's definition:
errOSACantAssign = -10006,
/* Signaled when an object cannot be set in a container.*/
The explanation I gave you was: "Here, nothing really usable, just a
name w in the global name space. Something has thus to be created. Given
the reference form "my parent's w", this should be a new property for
the parent script. But script objects can't be modified; only the values
of their properties may. Bang."
So, yes, you have introduced name w through the "global w" statement;
but this was just a name (no value has been bound to that name).
Now, when loaded script searches for "my parent's w", it first searches
for a property named w of the parent, aka the top level script (TLS).
There is none; so enters that ***very confusing behavior*** of
AppleScript: loaded script then searches for a global named w.
But there is just a name, no value associated to name w.
So, a place holder has still to be created (should there have been one,
it would have been used).
But the loaded script was asked to create "my parent's w" that is, a
property of its parent.
Now, you can't create a new property of a script object, as that would
change the object's definition.
A script object is a collection of properties, handlers and script
objects intended to perform certain tasks as a kind of black box.
If needed, the behavior of that black box may be adapted by inheritance:
just define a new script object as a child.
But a script object's definition can't be changed by program: you can't
add (remove) components to (from) the object.
Only the values bound to existing properties may be changed.
That's a part of the philosophy.
You get exactly the same behavior with a code like this one:
-- Example 2
script S
property P : "Hey"
end script
set S's W to "Hello"
--> error -10006: Cant set W to "Hello" [1]
which clearly shows that one is attempting to add a new property to a
script object, namely "script S". The same as above is happening: no
property W, no global W, try to create a property (because of the "my"),
error.
Or a variant:
-- Example 3
script S
on doThis()
set my W to "Hello"
--> error
end doThis
end script
S's doThis()
Anyway, the initial problem didn't go about globals at all: there was an
attempt to CREATE a property.
Let's go a bit further on properties before speaking about globals.
Consider this one:
-- Example 4
property W: "Bye"
script S
on doThis()
set my W to "Hello"
end doThis
end script
S's doThis()
W --> "Hello"
So, script S finds the parent's property W and changes the value bound
to it; this is really a matter of inheritance, as shown by that
counter-example:
-- Example 5
property W : "Bye"
script S
property parent : application "Finder"
on doThis()
set my W to "Hello"
--> Finder error: can't set W to "Hello"
end doThis
end script
S's doThis()
W
Now, let's just remove the "my":
-- Example 6
property W: "Bye"
script S
on doThis()
set W to "Hello"
end doThis
end script
S's doThis()
W --> "Hello"
Same result as with Example 4. Hmm... must again be a matter of inheritance.
Sure? Let's see:
-- Example 7
property W : "Bye"
script S
property parent : application "Finder"
on doThis()
set W to "Hello"
end doThis
end script
S's doThis()
W --> "Hello"
We clearly couldn't have changed a Finder's property...
In fact, this has nothing to do with inheritance: it is a matter of pure
syntactic scoping.
As soon as a property has been defined in the script (I really mean the
text here), the name of that property may be used "as is" past that
point, where it makes sense and unless overridden by an other statement.
Where it makes sense:
-- Example 8
script S
property W : "Bye"
on doThis()
set W to "Hello" -- Use W as is
end doThis
end script
S's doThis()
S's W -- Right: W belongs to S
--> "Hello"
W -- No such top-level data
--> W is undefined
Unless overridden - one way to do it:
-- Example 9
property W : "Bye"
script S
property W : "Hoyado" -- This hides above W
on doThis()
set W to "Hello" -- So we use the latter
end doThis
end script
S's doThis()
S's W --> "Hello"
W --> "Bye"
Unless overridden - another way to do it:
-- Example 10
property W : "Bye"
script S
on doThis()
local W -- Confine W to the handler
set W to "Hello" -- So this will be lost
end doThis
end script
S's doThis()
W --> "Bye"
But again, this is purely a syntactic scoping matter, occurring within a
same script text: nothing to do with inheritance, nor even with objects...
That syntactic aspect is even clearer through following example:
-- Example 11
script S
on doThis() -- I haven's seen W yet
set W to "Hello" -- So I'll take it as local
end doThis
end script
property W : "Bye"
S's doThis()
W --> "Bye"
But, as soon as the "my" keyword is used, this indicates one's intent to
reach a property [2]:
-- Example 11
script S
on doThis()
set my W to "Hello" -- Oh, my parent has one
end doThis
end script
property W : "Bye"
S's doThis()
W --> "Hello"
------------
[1] This is the error when run as an application. In SE, the error is:
"error 10: NSCannotCreateScriptCommandError".
Which one do you prefer? ;-)
[2] With the usual caveat: if I inherit from the TLS, if there is no
such property, but there is a global, well take that one...
[ === GO TO PART II === ]
_______________________________________________
applescript-users mailing list | email@hidden
Help/Unsubscribe/Archives:
http://www.lists.apple.com/mailman/listinfo/applescript-users
Do not post admin requests to the list. They will be ignored.