Re: Inheritance, Context, Scope, etc.
Re: Inheritance, Context, Scope, etc.
- Subject: Re: Inheritance, Context, Scope, etc.
- From: Axel Luttgens <email@hidden>
- Date: Mon, 26 Jan 2004 00:26:01 +0100
[ === PART III === ]
GLOBALS AND SCOPE
=================
At the top level of your script, you may have:
properties declarations
handlers definitions
script object definitions
executable statements
When you have executable statements, they together constitute the
so-called "implicit run handler"; these are the statements that get
executed when you click the "Run" button in SE (or when you double-click
an applet's icon in the Finder).
On the other hand, you could grab all these statements together and
enclose them with "on run" and "end run"; you then have an "explicit run
handler". This is the one that gets executed on a run event.
You can have either an implicit or an explicit run handler, but not both
(just try - that's something SE understands immediately ;-) ).
I'll focus on implicit run handlers (IRH), as they are the most commonly
used. [8]
That simple script:
-- Example 20
set G to "Hello"
just consists of an IRH, itself reduced to a single statement. Nothing
great, but yet hiding an important fact: through execution, one creates
a global variable taking value "Hello".
-- Example 21
set G to "Hello"
on getG() -- No G within scope
G --> G is undefined
end
getG()
Well, that's a good thing: one may have troubles enough with the
visibility of properties within a script's text. Remember Example 13, or
even a simplified version thereof:
-- Example 22
property P : "Hey"
on getP()
P
end getP
getP() --> "Hey"
So, script of Example 21 needs some adjustment if getG had really to get
the value of global G:
-- Example 23
set G to "Hello"
on getG()
global G -- Hint
G
end
getG() --> "Hello"
Note that the "global G" statement doesn't create anything; it is just a
hint to indicate that the global name space has to be used.
But such a "global" statement may be very annoying when put at the TLS,
as it will then provide the corresponding identifier with the same
visibility as that of a property:
-- Example 24
global G -- A very powerful hint
set G to "Hello"
script S
on doThis() -- G won't be local here
get G
end doThis
end script
S's doThis()
In fact, you really have the same kind of syntactic scoping:
-- Example 24
set G to "Hello"
script S
on doThis() -- G unseen yet, so local
get G --> G is undefined
end doThis
end script
global G -- A bit too late, dude
S's doThis()
It is generally just a bad idea to put a "global" statement at the TLS.
The same way, it is a bad idea not to try to put it just where needed.
Let's say you have defined a very complicated script object, something
like this:
-- Example 25
script S
global G
on doThis()
G & " man"
end doThis
[tons of statements]
on doThat()
set G to 1
set H to 2
G + H
end doThat
[tons of statements]
end script
set G to "Hello"
s's dothat() --> 3
s's dothis() --> {1, " man"}
Clearly, doThis()'s intent is to use current value of global G and to
make something out of this, while doThat() just uses identifiers G and H
for intermediate calculations.
The "global" statement was at the wrong place...
This would be better:
-- Example 25b
script S
on doThis()
global G
G & " man"
end doThis
[tons of statements]
on doThat()
set G to 1
set H to 2
G + H
end doThat
[tons of statements]
end script
set G to "Hello"
s's doThat() --> 3
s's doThis() --> "Hello man"
Or even better, if your script is really big, be defensive:
-- Example 25b
script S
on doThis()
global G
G & " man"
end doThis
[tons of statements]
on doThat()
local G, H
set G to 1
set H to 2
G + H
end doThat
[tons of statements]
end script
set G to "Hello"
s's doThat() --> 3
s's doThis() --> "Hello man"
Finally, note that globals work across script files too:
-- Example 26
-- Main script
set S to load script alias "path:to:loaded:script"
S's doThis()
display dialog G
-- Loaded script
on doThis()
global G
set G to "Hello"
end doThis
And, because globals are unrelated to inheritance, this will work both
in SE and as an application.
Now, the question is: does one really need globals?
In most cases, one may avoid them (for example, by passing a reference
to some data to be shared). And in the remaining very few cases, when
they are a must [9], one just needs to be somewhat careful.
WHY ARE THINGS THAT WAY
=======================
I may be wrong, but the above should have clarified the concepts of
properties (aka inheritance), globals and scoping a la AppleScript. If I
managed to be somewhat clear, I'm not sure you would state your
questions the same way anymore.
Now, one could wonder why AS relies on such rules, which may surprise
programmers accustomed to other languages.
Here, as you guessed it, Chris N. would certainly the right man to answer.
I'll nevertheless try to find some hints.
As the language for the rest of us, AS had to be unobstrusive, easy to
use and nevertheless powerful.
To be unobstrusive meant to avoid such boring preliminaries like type
declarations, entry point definition, variable typing...
Ease of use means a kind of interpreted language, without a compilation
phase, linking and such other oddities; on the other hand, it should
also be able to produce applets independent of a run-time environment.
To be powerful needed a rather rich set of data classes, the
availability of handlers and a way to be modular; since it also had to
communicate through events with the outside world, the idea of an
object-oriented language seemed to be a good choice.
But then, for very simple tasks, asking the user to type
property P1: "Hello"
property P2: " man"
on doThat()
set X to ". Hoyado?
return my P1 & my P2 & X
end
my doThat()
would already have been too pedantic. [10]
So, why not introduce some scoping rules, so as to relax the
requirements put on the user:
property P1: "Hello"
property P2: " man"
on doThat()
set X to ". Hoyado?"
return P1 & P2 & X
end
doThat()
But, for real unobstrusiveness, the user should even be authorized to do
this:
set P1 to "Hello"
set P2 to " man"
display dialog P1 & P2 & ". Hoyado?"
Once authorized to do both of the above, the user would inevitably enter
the following:
property P: "Hello"
set G to " man"
display dialog P & G
Thus, either there is a superfluous keyword "property" (but then the
concept of objects with their own methods and variables is at the risk
of vanishing), or one somehow needs to introduce something else
(globals, perhaps?).
Hmmm... just a guess.
HTH,
Axel
------------
[8] The scoping rules for an explicit run handler are somewhat different.
[9] I remember of somebody having recently expound on this list a case
where globals were the easiest way to handle a problem.
But I damn can't put my hand on it anymore. :-(
Does the author recall?
[10] But strictly speaking needed, as everything is a script object,
with its properties, handlers and script objects.
[ === END === ]
_______________________________________________
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.