[REBOL] Re: hash questions
From: joel::neely::fedex::com at: 8-Jan-2002 6:27
Hi, David,
David Hawley wrote:
> I come from the perl, tcl world where hashes are more like
> array indicies. In rebol, it seems that I can build a hash
> list, of some arbitrary values, but cannot associate keys
> with data. Am I missing soemthing?
>
> is in perl $hash{ "joe" } = $joesData
> and $data = $hash{ " joe" }
>
> can I do something like this in REBOL?
>
You can do this in REBOL:
favoriteLanguage:
[ "Larry" "Perl"
"Carl" "REBOL"
"Guido" "Python"
"Matz" "Ruby"
"Richard" "LISP"
]
and then
>> print select favoriteLanguage"Guido"
Python
However, if you want to maintain a dynamic set of associations
it's a bit more work:
assoc: make object!
[ data: []
default: 0
clear: func [] [data: copy []]
store: func [k [string!] v [string!] /local pos]
[ pos: find/skip data k 2
either found? pos
[ change next pos v]
[ append append data k v]
]
fetch: func [k [string!] /local r]
[ either found? r: select/skip data 2 k [r] [default]]
]
used as follows:
>> favlang: make assoc [default: "INTERCAL"]
>> favlang/fetch "David"
== "INTERCAL"
>> favlang/store "David" "REBOL"
== ["David" "REBOL"]
>> favlang/store "Bjarne" "c++"
== ["David" "REBOL" "Bjarne" "c++"]
>> favlang/store "Edsger" "Mathematics"
== ["David" "REBOL" "Bjarne" "c++" "Edsger" "Mathematics"]
>> favlang/fetch "David"
== "REBOL"
>> favlang/fetch "Edsger"
== "Mathematics"
Both blocks and hashes can be used with SELECT and FIND (and other
access/manipulation functions as well). Hashes use a hash-coding
scheme (internally) to speed the searching.
You may be wondering about the /SKIP above. The reason is that
REBOL by default treats blocks and hashes as ordered collection
of *single*values* which means that one could also say
>> select favlang/data "REBOL"
== "Bjarne"
to conclude that REBOL's favorite programming language is Bjarne!
The /SKIP refinement tells FIND, SELECT, et al, to treat the
first argument as a collection of n-tuples, where n is the last
argument. When we say SELECT/SKIP block val 2 we're asking
SELECT to consider only the first value of every *pair* of
entries, so that we get
>> select/skip favlang/data "Edsger" 2
== ["Mathematics"]
>> select/skip favlang/data "REBOL" 2
== none
which is more likely what you'd expect, coming from Perl. You
can, of course, use other tuple sizes than 2, as in
guruData:
[ "Edsger" "Dijkstra" "UT Austin"
"Don" "Knuth" "Stanford"
"Tony" "Hoare" "Oxford"
"David" "Gries" "Cornell"
]
which then can be treated as triples of data via
>> select/skip guruData "Tony" 3
== ["Hoare" "Oxford"]
(Notice that the remainder of the triple is returned as a block.)
Even though
>> find/skip guruData "Don" 3
== [
"Don" "Knuth" "Stanford"
"Tony" "Hoare" "Oxford"
"David" "Gries" "Cornell"
]
succeeds, notice that
>> find/skip guruData "Oxford" 3
== none
fails, since "Oxford" doesn't *begin* any triple of values.
HTH!
-jn-
--
; sub REBOL {}; sub head ($) {@_[0]}
REBOL []
# despam: func [e] [replace replace/all e ":" "." "#" "@"]
; sub despam {my ($e) = @_; $e =~ tr/:#/.@/; return "\n$e"}
print head reverse despam "moc:xedef#yleen:leoj" ;