Re: Scope of globals, parents and children, "load script" and all that
Re: Scope of globals, parents and children, "load script" and all that
- Subject: Re: Scope of globals, parents and children, "load script" and all that
- From: Sander Tekelenburg <email@hidden>
- Date: Sun, 20 May 2001 21:36:55 +0200
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1
At 18:58 +0200 UTC, on 20/05/2001, Brennan Young wrote:
>
This is a very interesting thread.
It is, isn't it? :)
>
Here's how I understand it.
>
>
If A is a script stored in an external file, and B (also a script) loads
>
the script object into itself, we might expect A to suddenly see all of B's
>
globals. Global means 'seen everywhere' or else it means nothing at all.
>
>
I believe this is Sander's beef, and I can follow him on this.
Yes. It seems the term "global" got me confused. Apparently globals are only
globals locally, not globally ;)
>
The way I see it though, scripts are compiled seperately, so there's no way
>
that the compiler of A can know that B has a global with a given name, so
>
it will complain about that.
>
>
The reason you are obliged to declare globals in both places, then, is
>
because the compiler needs to connect the variables to the same value in
>
both objects. There is no way that it can do this unless some kind of
>
preprocessor is involved - and Applescript has none.
I'll take your word for it. My assumption though, was that because globals
are called "global", they would be global. Apparently they're not, and that's
good to know ;) It's still not something I truly understand though.
[...]
>
As Victor says, 'Globals aren't "bad"', but they are messy, and apart from
>
all the name-space conflicts that they can cause, they require the
>
programmer to mentally keep track of them - which is a dreadful waste of
>
any programmer's most valuable resource: attention span. In other words,
>
they're not bad, but it's almost always better to use another technique if
>
you can.
Yes. I will probably go over all the code and see if I can get rid of the
globals. Will take some time, but it seems that that would a good road to
take.
>
I would argue that most people use globals out of ignorance
I admit to having been guilty of that :)
[...]
>
[...] try and isolate the access to your globals into handlers
>
as a first step, then see whether you can't wrap these handlers further
>
into a script object.
Yep. So far in my short scripting career I never declared anything as a
script object. Only now that I ran into this "globals issue" do I begin to
see how declaring stuff as a script object can be useful. I'll probably learn
how to use this.
>
If you find that you have a situation where more than one script object
>
needs to see the same data, try to find out when this is happening - i.e.
>
how often is that data being referred to. It's likely that only one object
>
needs to 'own' the data. The others can ask for it when they need it, or
>
ask the object to do something for them with its internal data.
Just to make sure I understand you correctly: with "ask" you mean something
like the following right?
script myObject
on DoStuff()
set Var1 to "hello"
set myName to get computer name
return {Var1, myName}
end DoStuff
end script
- --ask the above object for the values of its variables:
set {Var1, Var2} to DoStuff() of myObject
- -- pick the needed variable and use it:
display dialog Var2
Is this what you mean?
Is there another method/syntax possible? I would like to simply say something
like:
get myName of DoStuff() of myObject
Also: isn't the downside of using this approach instead of using globals,
that you repeatedly tell yopur script to do the same thing? I mean, of it is
declared to be a global, you only need to define its value once. Could affect
speed. Right?
>
You should be able to have the objects caching the data in a property or
>
local variable at initialisation time, or at the beginning of some
>
procedure or
>
handler.
I don't understand what you're saying.
>
That way, you can pass 'the data formally scoped as global' as a
>
parameter to an init() handler or something like that.
Don't you mean "formerly"? (If you really mean "formally" then I don't
understand what you're saying.)
>
With datatypes that are passed by reference, rather than by value, you
>
won't even be caching the data, you just store a reference to it, so even
>
if it is dynamic, the object or handler will always use the most up-to-date
>
value.
I don't understand this. What do you mean with "datatypes" and what with "by
reference" vs "by value"?
>
If you have a situation where data is very dynamic and still needs to be
>
seen by more than one object, you might make a script object to manage just
>
that data, and store a reference to the manager object everywhere you need
>
it. Provide a handler inside the manager object which allows outsiders to
>
access the data,
Like this?
script myObject
on DoStuff()
set Var1 to "Hello"
set myName to get computer name
return {Var1, myName}
end DoStuff
end script
script myOtherObject
on DoStuff()
tell application "Finder"
set Var1 to name of startup disk
return {Var1}
end tell
end DoStuff
end script
script Manager
on getsomeVars()
set {Var1, Var2} to DoStuff() of myObject
return {Var1, Var2}
end getsomeVars
on getSomeOthervars()
set {Var3} to DoStuff() of myOtherObject
return {Var3}
end getSomeOthervars
end script
on DoDialog(a, b)
display dialog a & ". " & "This puter is named " & b & "."
end DoDialog
on SayStuff(a)
say "This puter's startup disk is named " & a
end SayStuff
set {a, b} to getsomeVars() of Manager
DoDialog(a, b)
set {a} to getSomeOthervars() of Manager
SayStuff(a)
Btw, I noticed that the "script Manager" above needs to come after the other
script objects, or else (upon run) I get an error:
--> The variable myObject is not defined.
with Script Editor hiliting the first occurence of "myObject" in the "script
Manager" object.
>
[...] or (better still) get the manager object to take in other, more
>
transient, data as parameters and use it to act on the (previously global,
>
but now internal) data directly.
Eh? :)
[...]
>
Using instances is another great way to think out of the box of using
>
globals. I suspect that many Applescripters are not using instances much,
>
or at all.
I wouldn't know if I use them. What *is* an "instance"? :)
[...]
[the Parent property]
>
Try this:
>
>
Script 1
>
>
property a : ""
>
>
on test()
>
>
set d to display dialog "Test" default answer "Hello"
>
set a to the text returned of d
>
>
end test
>
>
>
Script 2 (in a seperate file)
>
>
property parent : (load script (choose file)) -- chose script 1 of course
>
>
on run()
>
>
test() -- this handler only exists in the ancestor
>
a -- so does this property. Look in the result window
>
>
end run
I think I understand this. But it seems to be the other way around from what
I thought I wanted to do. Here, the child loads the parent. I thought I
needed the parent to load the child...
Concerning my real-wold script: what I mean with "parent" is an applet that
the user activates. The child is a separate script, containing some handlers,
which is loaded by the parent. Perhaps it is a mistake to consider the
user-launched applet to automatically have to be the parent? Could/should the
user-launched applet be the child, and load its parent (through "property
parent : load script [alias]")?
[...]
>
> Btw, isn't my child script (which is only a bunch of handlers in my
>
> current version) an implicit "script object" (when I load it into the main
>
> script through a "load script" command)?
>
>
Sure, but it's not inherited by the main script unless you use the parent
>
property - you'd still need to refer to the object returned by (load
>
script) if you wanted to use it.
Yes. I think I understand.
>
Sander, what are you up to that you need 17 globals?
{grin}
This refers to my ($10) shareware applet "Disk Watcher". See
<
http://www.euronet.nl/~tekelenb/software/diskwatcher/index.html>.
It started out real simple. As a study project, back in the days that I just
started scripting. I took John Rethorst's "AutoCheck" apart and rewrote it so
it would work with vanilla AS. When I had finally learned enough about AS to
do that, I started extending the script with more and more features. By now
it's something I'm quite proud of. Disk Watcher works very well and is quite
powerful. People are buying it. No bug reports so far. I have many ideas for
more features, but I need to first reorganise the code or I'll drown :)
So all those globals are the last remaining bits of an inheritance from the
days when I didn't know any better. Today, I would do it differently if I
would write it from scratch - which is exactly why I'm asking all these
questions: I want to understand the relevant issues before I rewrite the
thing.
>
Maybe we can help reorganize it.
You all *are* helping tremendously already! :)
As I said, it's currently about 1000 lines of code A bit much to post here.
(Except for the globals most of that is really needed - nothing much
redundant. While extending it, I constantly ran into Script Editor's "1 32k
limit" so I had to constantly make the code more efficient - another great
learning experience :)) Plus, since I'm asking a few bucks for it I'm not
that anxious to make the code public. (But I would be happy to offer all the
helpful participants in this thread a free registration code for Disk Watcher
- - mail me privately if you're interested.)
-----BEGIN PGP SIGNATURE-----
Version: PGPfreeware 7.0.3 for non-commercial use <
http://www.pgp.com>
iQA/AwUBOwgcz+sywKfXgqKdEQIVbgCgpivsC6TM1uyF2EflYaQ2qb2VCUwAmwSd
dE6K/1I+A/yeuZ8yOWH3Fhr7
=Jy0M
-----END PGP SIGNATURE-----
--
Sander Tekelenburg, <
http://www.euronet.nl/~tekelenb/>
Mac user: "Macs only have 40 viruses, tops!"
PC user: "SEE! Not even the virus writers support Macs!"