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

Python Dictionaries

 [1/2] from: al:bri:xtra at: 22-Sep-2001 19:47


> Python Dictionaries look like this: > >>> rolodex = {'name' : 'Jason', 'email' : ['jasonic--nomadics--org']}
<<quoted lines omitted: 8>>
> etc > RQ1: With much bigger block, how do you keep track in these implicit pairs
of what is a 'key' and what is a 'value'. In Python the extra punctuation is more verbose, but always unambiguous One alternative is to use an object:
>> rolodex!: make object! [
[ Name: string! [ eMail: email! [ Site: url! [ ]
>> rolodex: make rolodex! [Name: "Jason" eMail: [jasonic--nomadics--org]] >> probe rolodex
make object! [ Name: "Jason" eMail: [jasonic--nomadics--org] Site: url! ]
> Named arguments for Python functions and classes allow one to set default
values very nicely. you can also call arguments in any order. The result is terrific readibility, because you don't have ask what argument is what, or deal with a predefined order. If you follow the pre-defined order, then you can drop the 'name=' part instead provide just the value. Another alternative is use 'parse as in the 'layout function in Rebol/View. The tutorial on VID at the Rebol site has examples.
> def name([arg, arg=value, *arg, **arg]): suite > > arg simple name > arg=value default if arg not passed > *arg collects extra positional args > **arg collects extra keyword args > > RQ2: Can anyone translate this into REBOL or suggest strategy for
attaining a keyword clarity. Perhaps it is not even desirable/necessary.. This one is a bit trickier, because Rebol doesn't really have variable arguments to functions. Instead, just pass a block of parameters and run it through 'parse rules (like Layout in View), or 'set to an object. For instance, a recursive function call: Stack/push/only reduce [Directory Files Pages] Sub: Generate Directory/:File set [Directory Files Pages] Stack/pop Andrew Martin ICQ: 26227169 http://zen.scripterz.org

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

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