Re: Reference variables
Re: Reference variables
- Subject: Re: Reference variables
- From: email@hidden
- Date: Mon, 15 Jan 2001 19:50:30 -0500
On Sun, 14 Jan 2001 02:10:59 +0000, Nigel Garvey <email@hidden>
asked,
>
Could someone please clarify my understanding of the low-level workings
>
of reference variables?
>
>
1) What exactly *is* a reference variable (as set by the 'a reference to'
>
operator) physically? Is it a set of AppleScript tokens, some sort of
>
superpointer, or what?
It acts like a pointer, but with greater functionality, since a reference can
point to a range ("words 2 thru 5" or "text from word 2 to word 5")Its like a
LISP closure, or a call-by-name parameter in ALGOL. Except it doesn't
re-evaluate expressions. Expressions are evaluated, and then plugged into the
standard reference forms (as listed in Table 5-1 of the AppleScript Language
Reference Guide). Internally, these are built like Object Specifier Records, I
suppose. (I don't know the internals, but the basic reference forms are the
same: by index, by ID, by property, by range from object to object, and by
filter.)
But this late evaluation behavior doesn't show if you just have "a reference to
character 3 of myText", because myText is evaluated, and you get simply,
'character 3 of "abcdef"'. Your only get true closure-like behavior if the
parameter is also a reference, which then cuts off evaluation.
set target to "abcdef"
set tRef to a reference to target
set target to "xyz"
character 1 of tRef
--> "x"
>
2) How does its application to large items (such as the bigList example
>
on p.205 of the 1999 ASLG) achieve such spectacular speed increases? What
>
are the mechanics?
I'm surprised at how big the speedup is. I imagine that the operation of
resolving a reference, such as "item 3 of someRef" is much faster than passing
around the entire array as a result or intermediate value. Its not as efficient
as a pointer, since you still have to do a multiply and follow two pointers.
But that's much faster than passing an entire list around as a value.
>
3) What happens in the last line of this script?
>
>
set bill to missing value
>
set fred to a reference to bill
>
--> bill of +script;
>
set arthur to a reference to text 1 thru 8 of fred
>
--> text 1 thru 8 of bill of +script;
>
set sid to a reference to character 4 of arthur -- (no-one on this
>
list...)
>
--> character 4 of text 1 thru 8 of bill of <<script>>
>
>
set bill to "1234567890"
>
set charlie to contents of sid --> "4"
>
>
sid is a complete reference in its own right (so you can subsequently
>
change fred or arthur without affecting its connection with bill). When
>
its contents are accessed, is every part of it then called into
>
existence, including the intermediate string "12345678"?
In this case, pointers are a pretty good mental model, except that instead of
pointing to just a specific item, an AppleScript reference can point to a range,
or transformation of the object (like "word 3 of sid"). But note, any
expression stops the chain of references, and forces an evaluation of the
reference. So, if we change your example to read,
set arthur to a reference to text 1 thru 8 of fred & "ABC",
arthur isn't 'text 1 thru 8 of bill of <<script>> & "ABC"', but merely, 'text 1
thru 8 of {missing value, "ABC"}', since 'fred & "ABC"' is an expression and so
it is evaluated.
Here are some interesting observations I've made about reference forms, some
just noticed today as I tried some things out.
1. Properties of objects constitute a reference form, not an expression. So,
you can have,
set fred to a reference to reverse of bill
and have your list reversed. (You'll have to write references that apply to
lists, instead of 'text of...')
Note that "count" is an expression, while "length" is a property. So,
set target to "abcdefg"
set tRef to a reference to target
set lRef to a reference to length of tRef
set cRef to a reference to count of tRef
set target to "xyz"
{contents of lRef, contents of cRef}
--> {3, 7}
count is evaluated when cRef is set, when tRef points to "abcdefg".
This also makes the be a difference between a property of a script object, and
the value of a handler that returns the value of that property. This makes a
difference if you are doing object-oriented programming in AppleScript, and are
wondering if you should hide all your property behind "get data" handlers. If
you do, you can't produce these late-evaluating references. So, the script
object of the above shows that,
script target
property p1 : 42
on getp1()
return "Target's " & p1
end getp1
end script
set tRef to a reference to target
set pRef to a reference to p1 of tRef
set hRef to a reference to getp1() of tRef
script replacement
property p1 : 35
on getp1()
return "Replacement's " & p1
end getp1
end script
set target to replacement
contents of {pRef, hRef}
--> {35, "Handler 42"}
(Leaving out the 'contents of' gives
--> {p1 of target of <<script>>, "Handler 42"}
"getp1() of tRef" is an expression, and thus is evaluated, yielding "Handler
42". 'A reference' to that simply sheds the reference, and stays as a string.
2. A handler can return a reference to a variable, but only if the variable has
global persistence (its a property, a global, or a property of a script object
that has global persistence). If you return a reference to a local variable,
you can't access it outside the function. (You get "access denied"). This is
reasonable since once you return from a function, its local variables go out of
scope and are deleted. (In C, if you do this, you end up with a stale pointer,
pointing to something random in the stack.)
3. Conversely, you can pass a reference into a handler, which allows a handler
to modify its arguments. But again, the reference must be to a variable with
global persistence. Otherwise, the function could stash the reference away in a
global, and some other command could then try to access the referent after it
has gone out of scope.
(You might be able to bend these rules, perhaps by returning a reference to a
variable that is in-scope in a script object, but where the script object itself
is stored on the stack, so that when the referent goes out of scope, the
reference is also destroyed. But I haven't explored that route.)
4. References allow you to do things that use pointers in other languages, but
they are cumbersome to work with. I wrote a doubly-linked list with script
objects and reference, but I never used it in any real work. I just use
AppleScript lists and the "beginning of" and "end of" reference forms, and go
with "items 1 thru j-1 of L & items j+1 thru N of L" if I want to delete item j
of a list. Letting AppleScript do lots of work breaking the list and
reassembling it is still quicker than manipulating references in my script.
--
Scott Norton Phone: +1-703-299-1656
DTI Associates, Inc. Fax: +1-703-706-0476
2920 South Glebe Road Internet: email@hidden
Arlington, VA 22206-2768 or email@hidden