[REBOL] Re: Hashes in Rebol
From: knizhnik:garret:ru at: 9-Dec-2003 22:03
Thank you very much for explanation.
Certainly it is very universal approach to treat everything as
series. But as all universal solutions is is not always convenient to
use:). If I remove exactly one element from the hash - what will be
result of such operation...
But actually I need hash table with integer key (object OID).
And here once again Rebol rules are not compatible with my
== make hash! [1 "one" 2 "two"]
>> h select 1
** Script Error: select expected series argument of type: series port
Is it possible to have hash table with integer key?
Or I should first convert it to string?
Tuesday, December 9, 2003, 6:01:44 PM, you wrote:
GI> Hi Konstantin,
KK>> Why them are implemented in Rebol in such strange way?
GI> I think for consistency with other series types. REBOL's standard path
GI> 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! 
GI> == make hash! 
>>> append hash [A 1 B 2 C 3 D 4]
GI> == make hash! [A 1 B 2 C 3 D 4]
GI> == 2
>>> hash/b: 22
GI> == make hash! [A 1 B 22 C 3 D 4]
>>> remove/part find hash 'b 2
GI> == make hash! [C 3 D 4]
GI> == make hash! [A 1 C 3 D 4]
GI> You can also use intermediate words as variables, along with the
GI> get-word! syntax in the path to evaluate them
>>> key: 'c
GI> == c
GI> == 3
GI> But you can't set values that way.
>>> hash/:key: 33
GI> ** Syntax Error: Invalid word -- :key:
GI> ** Near: (line 1) hash/:key: 33
GI> You need to do something like the following:
>>> head change next find hash key 33
GI> == make hash! [A 1 C 33 D 4]
GI> 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
GI> == make hash! [A 1 C 33 D 44]
GI> Of course, you could make things work how you want, any number of
GI> ways. e.g.
GI> ; Keys don't *have* to be strings.
GI> ; If you assign a block to _data, it's up to you to make it a hash! if you want.
GI> dictionary: make object! [
GI> ; Odd items are keys, even items are values. I.e.
GI> ; [key1 value1 key2 value2...]
GI> _data: make hash! 
GI> clear: does [_data: make hash! ]
GI> count: does [(system/words/length? _data) / 2]
GI> length?: :count
GI> empty?: does [count = 0]
GI> keys: does [extract head _data 2]
GI> values: does [extract next head _data 2]
GI> item: func [key] [
GI> if has-key? key [_data/:key]
GI> has-key?: func [key] [
GI> found? find/skip _data key 2
GI> remove: func [key] [
GI> if has-key? key [system/words/remove/part find/skip _data key 2 2]
GI> change: func [key value] [
GI> either has-key? key [_data/:key :value][append _data reduce [key :value]]
GI> contains?: func [value /only] [
GI> either only [
GI> found? find/skip/only next _data value 2
GI> found? find/skip next _data value 2
GI> ;d: make dictionary 
GI> ;d/_data: ["A" 1 "B" 2 "C" 3 "D" 4]
GI> ;d/change 0.0.0 "black"
GI> ;d/item 0.0.0
GI> In your case that might be a good choice, but the main thing to look
GI> at for "normal" REBOL usage is how the model fits with standard REBOL
GI> idioms and style. REBOL is quite different from other languages, and
GI> sometimes trying to make it work like them will look good initially,
GI> because you're making it act in a familiar way. Sometimes, though, it
GI> will lead to inelegant solutions later because you just keep adding
GI> things, rather than stripping them away.
GI> The main thing to remember with REBOL is that everything is just
GI> data--a series of values--until it is evaluated.
GI> -- Gregg