[REBOL] Re: Hashes in Rebol
From: greggirwin:mindspring at: 9-Dec-2003 8:01
Hi Konstantin,
KK> Why them are implemented in Rebol in such strange way?
I think for consistency with other series types. REBOL's standard path
notation is extremely convenient.
KK> ...how can I
KK> 1. Remove <key, value> pair from hash
KK> 2. Change value associated with the particular key
>> hash: make hash! []
== make hash! []
>> append hash [A 1 B 2 C 3 D 4]
== make hash! [A 1 B 2 C 3 D 4]
>> hash/b
== 2
>> hash/b: 22
== make hash! [A 1 B 22 C 3 D 4]
>> remove/part find hash 'b 2
== make hash! [C 3 D 4]
>> hash
== make hash! [A 1 C 3 D 4]
You can also use intermediate words as variables, along with the
get-word! syntax in the path to evaluate them
>> key: 'c
== c
>> hash/:key
== 3
But you can't set values that way.
>> hash/:key: 33
** Syntax Error: Invalid word -- :key:
** Near: (line 1) hash/:key: 33
You need to do something like the following:
>> head change next find hash key 33
== make hash! [A 1 C 33 D 4]
Or write a little wrapper for that (no error handling in example!):
>> my-replace: func [series key value][change next find series key value]
>> head my-replace hash 'd 44
== make hash! [A 1 C 33 D 44]
Of course, you could make things work how you want, any number of
ways. e.g.
; Keys don't *have* to be strings.
; If you assign a block to _data, it's up to you to make it a hash! if you want.
dictionary: make object! [
; Odd items are keys, even items are values. I.e.
; [key1 value1 key2 value2...]
_data: make hash! []
clear: does [_data: make hash! []]
count: does [(system/words/length? _data) / 2]
length?: :count
empty?: does [count = 0]
keys: does [extract head _data 2]
values: does [extract next head _data 2]
item: func [key] [
if has-key? key [_data/:key]
]
has-key?: func [key] [
found? find/skip _data key 2
]
remove: func [key] [
if has-key? key [system/words/remove/part find/skip _data key 2 2]
]
change: func [key value] [
either has-key? key [_data/:key :value][append _data reduce [key :value]]
]
contains?: func [value /only] [
either only [
found? find/skip/only next _data value 2
][
found? find/skip next _data value 2
]
]
]
;d: make dictionary []
;d/_data: ["A" 1 "B" 2 "C" 3 "D" 4]
;d/change 0.0.0 "black"
;d/item 0.0.0
In your case that might be a good choice, but the main thing to look
at for "normal" REBOL usage is how the model fits with standard REBOL
idioms and style. REBOL is quite different from other languages, and
sometimes trying to make it work like them will look good initially,
because you're making it act in a familiar way. Sometimes, though, it
will lead to inelegant solutions later because you just keep adding
things, rather than stripping them away.
The main thing to remember with REBOL is that everything is just
data--a series of values--until it is evaluated.
HTH!
-- Gregg