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

[REBOL] Python Dictionaries

From: greggirwin::starband::net at: 22-Sep-2001 12:30

Hi Jason, << The two main things I miss from Python: - dictionaries [associative hash arrays] - named arguments >> I've only been at REBOL for a couple months, in my spare time, and I'm writing little bits and pieces to help me get familiar with it. Here's a dictionary object I did recently. ; Keys don't *have* to be strings, do they? ; 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! 50 clear: does [_data: make hash! 50] count: does [return (system/words/length? _data) / 2] length?: :count empty?: does [return count = 0] keys: does [extract head _data 2] values: does [extract next head _data 2] item: func [key] [ if has-key? key [return first next find/skip _data key 2] ] has-key?: func [key] [ return 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 /only] [ either has-key? key [ either only [ system/words/change/only next find/skip _data key 2 :value ][ system/words/change next find/skip _data key 2 :value ] ][ either only [ append/only _data reduce [key :value] ][ append _data reduce [key :value] ] ] ] contains?: func [value /only] [ either only [ return found? find/skip/only next _data value 2 ][ return found? find/skip next _data value 2 ] ] ] d: make dictionary [] d/change "A" 1 d/change "B" 2 d/item "A" d/change 0.0.0 "black" d/item 0.0.0 d/keys d/values d/_data: ["A" 1 "B" 2 "C" 3 "D" 4] d/_data: make hash! ["A" 1 "B" 2 "C" 3 "D" 4] Let me know what you find wrong with it. It hasn't seen heavy testing yet. I'm not a python guy so I'd be interested to hear from you, or others, what you like (or don't) about it. RE: Named Arguments I haven't fully grokked the best way to do things in REBOL but refinements are something you can use where you want to have otpional arguments. I know it's not the same thing, but often times looking at things from a different perspective can yield good results. I.e. if you design a function and determine that most of the time you can use default values for 2 of the 3 parameters, use refinements for those parameters. Andrew posted another great solution. The way layout works, you can pass arguments in any order and, as long as they are different data types, it will figure out where they belong. I'd bet you could also write a wrapper that could take as parameters a function and a block of named arguments for that function. Impossible you say? Ahhhh, remember that REBOL is highly reflective and you can, at runtime, acquire the interface spec for a function.
>> first :length?
== [series]
>> first :find
== [series value /part range /only /case /any /with wild /skip size /match /tail /last /reverse]
>> first :append
== [series value /only] <...OK, so my interest was piqued and I had to see how this might be done...time passes...> At the risk of posting bad information, here is what I came up with. Bear in mind that I am a beginner at REBOL and this is surely not going to work in all cases you could throw at it. That said: ; Ladislav Mecir's nargs function nargs: func [ {The number of the function arguments} f [any-function!] ] [ -1 + index? any [find first :f refinement! tail first :f] ] do-fn-named-args: func [fn[action! function!] args[block!] /local arg fn-args] [ fn-args: array nargs :fn foreach arg args [ either (type? (second arg)) = word! [ change/part (at fn-args index? (find first :fn (to-word first arg))) (get second arg) 1 ][ change/part (at fn-args index? (find first :fn (to-word first arg))) (second arg) 1 ] ] do reduce [:fn fn-args] ] a: [1 2 3 4 5] do-fn-named-args :append [['value 1] ['series a]] do-fn-named-args :length? [['series a]] Note that I didn't bother to come up with a special syntax, handle leading ordinal parameters, or deal with refinements. Also note that you use a leading colon on the function, and the param names are words. Arguments you don't supply will be none in the function call. You could also pass a dictionary as your list of named arguments and iterate over the function parameters doing a dictionary lookup for each parameter. So, how useful will this be in REBOL? I'm not sure. Most REBOL functions take a very small number of arguments, which is a good thing. This kind of obviates the need for the simplifications afforded by named arguments. Still, it's something to keep in our bag of tricks. --Gregg