Re: Coercing a list to string (nasty behaviour IMHO)
Re: Coercing a list to string (nasty behaviour IMHO)
- Subject: Re: Coercing a list to string (nasty behaviour IMHO)
- From: Axel Luttgens <email@hidden>
- Date: Sun, 26 Aug 2001 23:34:54 +0200
- Organization: ---
Nigel Garvey wrote:
>
Axel Luttgens wrote on Tue, 21 Aug 2001 23:25:06 +0200:
>
>
>-- Example 1
>
>on f(X)
>
> log {1, X, 2000} as string
>
>end f
>
>set X to {7, 8}
>
>f(X)
>
> --> 1782000
>
>
[...]
>
>
>First example has just been written to make clear that we are working with
>
>references.
>
>
No. There are no references here. The value of X is the list {7, 8}.
Well, this is a point that always puzzled me in AppleScript (could perhaps be
worth another thread: "What exactly is a reference in AS?").
I tend to believe that as soon as you can do something like this:
on f(Y)
set item 1 of Y to 1
end f
set X to {5, 6}
f(X)
log X
--> {1, 6}
you are working on a reference: using a classical terminology, Y must be a
pointer and not a list passed by value.
So, if I sligthly rewrite example 1 as follows:
-- Example 1bis
on f(Y)
log {1, Y, 2000} as string
end f
set X to {7, 8}
f(X)
--> 1782000
it more clearly appears that I am performing a string coercion of a list
containing a reference.
More generally, I have the feeling that once you are using lists (or records) in
AppleScript, you are somehow working on references (with the language trying to
make its best to let lists -or records- appear as basic objects).
And that's why, with that semi-implicit asumption, I audaciously wrote some
other examples directly using list variables instead of making explicit
references as in first example.
>
>This may even go deeper, as in:
>
>
>
>-- Example 3
>
>set X to {5, 6}
>
>set Y to {7, 8}
>
>set Z to {X, Y}
>
>log {1, Z, 2000} as string
>
> --> "156782000"
>
>
>
>So, it appears that the interpretor is smart enough to recursively evaluate
>
>the components of an expression, going as deep as needed, and to convert
>
>references to their contents when needed.
>
>
Again, no. The value of Z is {{5, 6}, {7, 8}} - another list - which has
>
been built in stages by running the three lines before the coercion.
>
There's no recursive evaluation involved.
I insist :-)
There must be an evaluation:
-- Example 3bis
set X to {5, 6}
set Y to {7, 8}
set Z to {X, Y}
set item 1 of X to 9
log {1, Z, 2000} as string
--> "196782000"
If Z had been assigned value {{5, 6}, {7, 8}} by running the first three lines,
4th line would not have been able to change that value.
I'm of the opinion that the interpretor evaluates Z when it encounters that
symbol in 'log {1, Z, 2000} as string', and only at that moment. Before that
moment, Z is just known to be a list of two variables (that could be anything;
hence the recursive evaluation capability).
This would not have been the case with a construct such as:
set X to 1
set Y to 2
set Z to X+Y
log {1,Z,2000} as string
Here, I would have agreed with you: Z already has a value of 3 when encountered
in 'log {1, Z, 2000} as string'.
>
>> References themselves are not coercible types. In a multi-item list,
>
>> their interpretation as value or expression is a scripting matter.
>
>>
>
>> {1, Dte's month, 2000} as string
>
>>
>
>> ... means "coerce a list containing the number 1, the reference 'Dte's
>
>> month', and the number 2000 to a string."
>
>
>
>I think it should be spelled a bit differently:
>
>
>
>... means: "considering that '{1, Dte's month, 2000} as string' is of the
>
>form 'Exp as Cls', where Exp appears to be a list and Cls is 'string',
>
>(recursively) evaluate each item of the list, convert each evaluated item to
>
>a string (if possible), and concatenate resulting items.
>
>
>
>That way, we tend to obtain an operational definition of "coercing a list to
>
>a string".
>
>
However, the way it *is* spelled is probably as I've described:
>
>
>> The operation fails at the
>
>> second item, not because of an AppleScript fault but because the scripter
>
>> hasn't properly described what he/she wants. What's intended is:
>
>>
>
>> {1, Dte's month, 2000}
>
>> result as string
>
>
>
>
>So, programmers have to be explicit about what they want.
>
>I fully agree with you :-)
>
>
[...]
>
>-- Example 5
>
>log "1" & item 1 of {3,4} & 2000
>
> --> "132000"
>
>log {"1", item 1 of {3,4}, 2000} as string
>
> --> "1"
>
>
>
>Why doesn't the first line hang at the reference 'item 1 of {3,4}'?
>
>Why should the programmer be considered more precise while writing the first
>
>line instead of the second one?
>
>
Because in the first line, the reference is part of the instruction
>
itself: 'Concatenate item 1 of {3, 4} to "1".') The second line is an
>
instruction to do something with a list that contains the reference as a
>
value of class reference. The list - as written in the line - doesn't
>
require any evaluation in order to exist and so is interpreted "as is".
>
It's a passive object.
>
>
If you leave off the 'as string', the line becomes an instruction to
>
*get* a list. The list as written then becomes an active description of
>
the list that you want and the reference is "evaluated" as part of that.
>
Put another way, the list *is* the instruction in that line. Running it
>
produces the result {"1", 3, 2000} which can then be coerced to string as
>
a separate operation.
But you can't leave off the 'as string' without introducing side effects in the
reasoning: the 'as' operator appearing within the context of an 'aList as
string' expression has a fully precise meaning.
>
The two operations can be combined in one line like so:
>
>
(get {"1", item 1 of {3, 4}, 2000}) as string
>
>
Alternatively, you can run just the reference first and specify the
>
result in the list:
>
>
item 1 of {3, 4}
>
{"1", result, 2000} as string
>
>
... which combines as:
>
>
{"1", get item 1 of {3, 4}, 2000} as string
That use of 'get' (a variant of what I called 'deferring evaluation' in previous
posts) is interesting when confronted to the ASLG:
The Get command [...] returns the value of an expression
[...] and assigns the value returned to the predefined
variable result.
[get] anyAppleScriptExpression
If no error is generated, the result is the value of the
specified [...] expression.
[...]
The word get in the Get command is optional because AS
automatically gets the value of expressions [...] when
they appear in scripts.
So, an OPTIONAL keyword makes the difference:
{"1", get item 1 of {3, 4}, 2000} as string
--> "132000"
{"1", item 1 of {3, 4}, 2000} as string
--> "1"
That's what I meant by writing that a general rule is broken in the context of a
'aList as string' expression: AS seems to forget to evaluate an index or
property reference form, and to need some help.
Or it doesn't forget to evaluate, because it can't (if we follow your thesis),
but it then forgets to explicitely raise an error.
Or I am completely wrong without understanding why (perhaps the less stupid
thing I have written about all that stuff?).