Re: hash arrays and other mysteries
Re: hash arrays and other mysteries
- Subject: Re: hash arrays and other mysteries
- From: has <email@hidden>
- Date: Wed, 17 Oct 2001 18:43:13 +0100
Arthur J Knapp wrote:
>
>
> Plunging straight into the deep end (this is what happens when you start
>
> sniffing around other languages...), I'd very much like to use hash arrays
>
> (that's the correct term, yes?) or their nearest sensible equivalent in
>
> Applescript.
>
>
We've just had a very lengthy discussion about this on the other list:
>
>
<http://listserv.dartmouth.edu/scripts/wa.exe?A0=macscrpt&D=1&H=0&O=D&T=1>
Ooh, lots of new reading material. Thanks. (Do you think I should subscribe
to this dartmouth list too, or am I causing enough nuisance already just on
this one?<g>) BTW, please feel free to repost there any relevant stuff from
here if you think it'll be useful.
-----
>
> So now I've got this, which uses Smile to cook the books a bit:
>
>
Nice. :)
Thanks. It's sinking in that this is actually a small achievement (ooh, I
done good!<g>). Still not as good as hash arrays, mind you, but close
enough to be useful.
BTW, if you really want to be vanilla about it, you can use Standard
Addition's "run script" instead of "do script". But it's much slower for
some reason (I don't know why "run script" takes so much longer to compile
and run a string of code than Smile's "do script" does). Though seeing the
speed difference I think I'll be sticking with Smile myself.
(I've included the finished vanilla version of the coerceToRecord handler
at the end of this mail, and will post it to macscripter later for general
consumption.)
-----
Rolling on...
Going back the way, e.g:
{a:1, b:"hi", c:false} --> {{"a", 1}, {"b", "hi"}, {"c", false}}
is similarly amusing:
======================================================================
property x : {a:1, b:"2", c:false}
--set the path to this file here
property pathtothisfile : "bob:desktop folder:xprop"
tell application "Smile" to set array to text 2 thru -2 of (do script
[NO-BREAK]"
set x to x of (load script \"" & pathtothisfile & "\")
" as string)
set vals to x as list
set AppleScript's text item delimiters to {", "}
set array to every text item of array
set AppleScript's text item delimiters to {":"}
repeat with itemno from 1 to count of array
set item itemno of array to {text item 1 of item itemno of array,
[NO-BREAK]item itemno of vals}
end repeat
set AppleScript's text item delimiters to {""}
array
======================================================================
[formatted using ScriptToEmail - gentle relief for mailing list pains]
[
http://files.macscripter.net/ScriptBuilders/ScriptTools/ScriptToEmail.hqx]
Note: This is just a rough demonstration. You'll need to save it to disk
and modify the pathtothisfile property accordingly for it to work. Once
I've knocked it into something of practical use I'll be happy to post it
again. (I'll probably be using a script server eventually, so won't need to
use this ugly "store script"/"load script" approach to pass variables.
Unless I've missed something obvious like using property parents, but they
don't seem to work for me. Thoughts?)
Anyway, it's crazy, but it works. And since I've not thought of any other
way to coerce a record to a string whilst preserving property names (as
strings), here it is.
Unlike the coerceToRecord handler, going from record to list *definitely*
requires Smile as "run script" can't coerce the result into a string (which
is the whole reason for using "do script" here). So if vanilla's your thing
then you're plum outta luck with record->list ...unless there IS another
way of doing it and I've just been stupid and missed it.
-----
I reckon it should be possible to use similar tricks to turn the names of
variables into strings (and vice-versa), and maybe other mad stuff as well.
With any luck I'll figure a way to refer to a record property using a
string, getting things closer still to hash array-style behaviour.
Hrmm. Still kinda hanker for real list<->record coercions though. Or just
proper hash arrays in the first place.<sigh>
-----
[Arthur's solution]
>
> And it's not vanilla either, but it's the closest I've managed to get. Has
>
> anyone got any other ideas?
TIDs (...but of course;). Very nice.
Pure vanilla too, which can be handy. Personally I don't mind values being
coerced to strings as that's easy to rectify after. The only real downside
seems to be that looking up values is still a significantly slower than
with using records**, although whether this would be a problem or not would
depend on how much it was used and how fast the script needs to be. (Do you
know how well it fares with bigger/longer lists?)
-----
>
> Last but not least, does anyone know if it's possible to bounce between
>
> using AS and the sparkly new JavaScript OSA within a script?
>
>
You can check out this posting of mine that centers on this basic idea:
>
>
<http://groups.yahoo.com/group/jsosa/message/268>
Cool. Thanks. I'd actually noticed these boards a couple days ago (strange
how _at_least_ half the messages posted there are by one "Arthur J
Knapp"...;). I shall go have a proper rummage around as I clearly didn't
look hard enough the first time.:)
has
--------------
**Speed comparison:
In a _very_ lazy and wholly unreliable test, looking up the value for
"Paul" (1000 times) yielded:
0.4167 - your method
1.2167 - loop-based list search of {{"john", "1654"}, {"paul", "5064"}, etc}
0.0167 - looking up a property called "paul" in a record
I didn't do a test to see which method was fastest for adding/setting
values so I don't know how these would compare. I figure that lookups are
probably much more common than adding new key:value pairs though, so speed
there is less important.
--------------
Last but not least, here's the final (unless anyone can suggest a better
name for the handler!) version of the list-to-record (pseudo-coercion)
handler. Enjoy!
======================================================================
(*
coerceToRecord
The coerceToRecord handler converts a list into a record.
Think of it as a pseudo-coercion - as in:
{{"a", 1}, "b", 2}} as record
--> {a:1, b:2}
although what you'd actually write is:
coerceToRecord for {{"a", 1}, "b", 2}}
---
NOTES
The list must be correctly formatted to contain one or more sublists,
[NO-BREAK]where each sublist is of form: {propertyName,
[NO-BREAK]propertyValue}.
The propertyName must be a string. This can be almost anything - but
[NO-BREAK]avoid using characters other than a-z and A-Z for property
[NO-BREAK]names unless you know what you are doing.
The propertyValue can be any simple object; e.g. boolean, number or
[NO-BREAK]string. It cannot be a complex object such as a list or
[NO-BREAK]record, however. If you want your properties to contain
[NO-BREAK]lists or records then you will have to use dummy values
[NO-BREAK]whilst constructing the record, then add the real values
[NO-BREAK]later.
---
OTHER NOTES
Note that Standard Additions' "run script" is relatively slow.
To improve the handler's speed, Smile users can replace:
run script
with:
tell application "Smile" to do script
Other script editing tools may offer similar facilities.
---
Use and distribute freely. (And give credit where due...)
has2001
*)
to coerceToRecord for array
try
set str to ""
repeat with nameValuePair in array
set str to str & "|" & item 1 of nameValuePair & "|:\"" &
[NO-BREAK]item 2 of nameValuePair & "\" as " & class of item 2 of
[NO-BREAK]nameValuePair & ", "
end repeat
on error
error "Unable to coerce the list to a record. Check the list is
[NO-BREAK]correctly formed."
end try
run script "{" & (characters 1 thru -3 of str) & "}"
end coerceToRecord
--Example
coerceToRecord for {{"a", 1}, {"bob", "hi"}, {"big trouble", false}}
--> {a:1, bob:"hi", |big trouble|:false}
======================================================================
[formatted using ScriptToEmail - gentle relief for mailing list pains]
[
http://files.macscripter.net/ScriptBuilders/ScriptTools/ScriptToEmail.hqx]