Mailing List Archive: 49091 messages
  • Home
  • Script library
  • AltME Archive
  • Mailing list
  • Articles Index
  • Site search
 

Hashes in Rebol

 [1/12] from: knizhnik:garret:ru at: 9-Dec-2003 14:47


Sorry, I am trying to implement Rebol API to my OO database DyBASE and not yet familiar with Rebol. I completely confused by lack of normal associative arrays or hashes. Yes - in Rebol there is hash! type and "select" function makes it possible to extract values from hash. But I also want to remove and replace elements in hash. There no hash specific "replace" and "remove" functions which can deal with <key, value> pairs. Certainly, I am sure that it is possible to update hash table using standard "remove" and "replace" function but it seems to be non trivial. So may be I missed something? Associative arrays are one of the most fundamental structure especially in scripting language and some languages provides no other collection types except arrays. Why them are implemented in Rebol in such strange way? Once again sorry for question which may be obvious for experienced Rebol programmers, but how can I 1. Remove <key, value> pair from hash 2. Change value associated with the particular key -- Best regards, Konstantin mailto:[knizhnik--garret--ru]

 [2/12] 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

 [3/12] from: andreas:bolka:gmx at: 9-Dec-2003 15:59


Tuesday, December 9, 2003, 12:47:53 PM, Konstantin wrote:
> Once again sorry for question which may be obvious for experienced > Rebol programmers, but how can I > 1. Remove <key, value> pair from hash
remove/part find hash key 2
> 2. Change value associated with the particular key
change find/tail hash key newvalue -- Best regards, Andreas

 [4/12] from: knizhnik:garret:ru at: 9-Dec-2003 21:56


Hello Andreas, Tuesday, December 9, 2003, 5:59:27 PM, you wrote: AB> Tuesday, December 9, 2003, 12:47:53 PM, Konstantin wrote:
>> Once again sorry for question which may be obvious for experienced >> Rebol programmers, but how can I >> 1. Remove <key, value> pair from hash
AB> remove/part find hash key 2
>> 2. Change value associated with the particular key
AB> change find/tail hash key newvalue Thank you very much. AB> -- AB> Best regards, AB> Andreas -- Best regards, Konstantin mailto:[knizhnik--garret--ru]

 [5/12] from: knizhnik:garret:ru at: 9-Dec-2003 22:03


Hello Gregg, 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 expectations: == 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]
>>> hash/b
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]
>>> hash
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
>>> hash/:key
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> ] GI> has-key?: func [key] [ GI> found? find/skip _data key 2 GI> ] GI> remove: func [key] [ GI> if has-key? key [system/words/remove/part find/skip _data key 2 2] GI> ] GI> change: func [key value] [ GI> either has-key? key [_data/:key :value][append _data reduce [key :value]] GI> ] GI> contains?: func [value /only] [ GI> either only [ GI> found? find/skip/only next _data value 2 GI> ][ GI> found? find/skip next _data value 2 GI> ] GI> ] GI> ] 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> HTH! GI> -- Gregg -- Best regards, Konstantin mailto:[knizhnik--garret--ru]

 [6/12] from: chris:langreiter at: 9-Dec-2003 20:33


> == make hash! [1 "one" 2 "two"] >>> h select 1
select h 1

 [7/12] from: ingo:2b1 at: 9-Dec-2003 20:51


Hi Konstantin, I guess you suffer from too much object oriented programming ;-)
>> h: make hash! [3 "three" 1 "one" 2 "two" ]
== make hash! [3 "three" 1 "one" 2 "two"]
>> select h 1
== "one" (pay especially close attention to the order in which select, h, and 1 stay on this line ... ) And btw, please do ask all the questions you have, it's not uncommon for even seasoned Rebolers to find something new in the answers to seemeingly easy questions (as just happened to me with the usage of find/tail) Kind regards, Ingo Konstantin Knizhnik wrote:

 [8/12] from: knizhnik:garret:ru at: 9-Dec-2003 22:57


Hello Christian, Tuesday, December 9, 2003, 10:33:44 PM, you wrote:
>> == make hash! [1 "one" 2 "two"] >>>> h select 1
CL> select h 1 O, sorry - such stupid mistyping:( I was confused, because h select "1" doesn't report any error and returns none... -- Best regards, Konstantin mailto:[knizhnik--garret--ru]

 [9/12] from: nitsch-lists::netcologne::de at: 9-Dec-2003 20:56


Am Dienstag 09 Dezember 2003 20:03 schrieb Konstantin Knizhnik:
> Hello Gregg, > Thank you very much for explanation.
<<quoted lines omitted: 10>>
> Is it possible to have hash table with integer key? > Or I should first convert it to string?
Better convert it to this syntax:
>> h: make hash! [1 "one" 2 "two"]
== make hash! [1 "one" 2 "two"]
>> select h 1
== "one" ;) method object in rebol for inbuilds. -Volker

 [10/12] from: nitsch-lists:netcologne at: 9-Dec-2003 21:09


Am Dienstag 09 Dezember 2003 15:59 schrieb Andreas Bolka:
> Tuesday, December 9, 2003, 12:47:53 PM, Konstantin wrote: > > Once again sorry for question which may be obvious for experienced
<<quoted lines omitted: 4>>
> > 2. Change value associated with the particular key > change find/tail hash key newvalue
some notes when used to "usual" hash-tables: 1) there is /skip for find and such. If you have the same type for key and data, that helps. then: find/skip block key 2 instead of find block key with different types it does not matter, because 'fid is type-sensitive. 2) use /only when adding blocks to blocks. append/only, change/only.
>> append to-hash[1 2 3] [4 5] ; wrong
== make hash! [1 2 3 4 5]
>> append/only to-hash[1 2 3] [4 5] ;right
== make hash! [1 2 3 [4 5]] 3), when changing/adding items first check if they are pesent. in other languages old keys are overwritten, rebol wants a user-check. ;to add something either pos: find/tail hash key [ change/only pos value ] [ repend hash [key value] ; = append hash reduce[key value] ] -Volker

 [11/12] from: the:optimizer:tiscali:it at: 9-Dec-2003 21:16


On Tue, 9 Dec 2003 22:03:52 +0300, Konstantin Knizhnik <[knizhnik--garret--ru]> wrote:
> But actually I need hash table with integer key (object OID). > And here once again Rebol rules are not compatible with my
<<quoted lines omitted: 4>>
> Is it possible to have hash table with integer key? > Or I should first convert it to string?
Not a big expert but you MAY TRY:
>> h: make hash! [1 "one" 2 "two"]
== make hash! [1 "one" 2 "two"] select h 1 == "one"
>> select h 2
== "two" Is this what you wanted? M&F

 [12/12] from: nitsch-lists:netcologne at: 9-Dec-2003 21:37


Am Dienstag 09 Dezember 2003 20:57 schrieb Konstantin Knizhnik:
> Hello Christian, > Tuesday, December 9, 2003, 10:33:44 PM, you wrote:
<<quoted lines omitted: 6>>
> h select "1" > doesn't report any error and returns none...
eeks. yes, ARGUMENTS: series -- (Type: series port) value -- (Type: any-type) that means any-type, including nothing. like this:
> a: reduce[1 "one" () "what??"]
!== [1 "one" unset "what??"]
>> (select a)
!== "what??" if it does not find unset, it returns none. like your error:
>> (select [1 2])
== none has some uses in console. for example 'help can be called with or without a word. with 'select its quite confusing. -Volker

Notes
  • Quoted lines have been omitted from some messages.
    View the message alone to see the lines that have been omitted