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

Binding problem with 'do

 [1/20] from: tim::johnsons-web::com at: 30-Jul-2005 8:43


I'm working with a switch that has a lot of repetitive patterns: i.e.: switch/default type[ "button" [append auto do-button name layout] "checkbox" [append auto do-checkbox name layout] "time" [append auto do-time name layout] "hidden" [append auto do-hidden name layout] "radio" [append auto do-radio name layout] ;; ... which is tedious. But works ;; Now I want to simplify using 'load and 'do. ;; As in the following output: copy [] foreach plist glbs/plists[ foreach [name layout] plist[ type: select layout "type" code: load rejoin["append output do-" type " name layout"] ?? code ;; see code "dump" below do code ] ] code: [append output do-text name layout ] ;; dump from ?? code ;; some abbreviation of code here, of course ;; with the second method, rebol stops me with the following error ;; message: output has no value ;; say what? I thought 'load was supposed to bind words to global ;; context! any help would be appreciated. I'd hate to do all that 'switch coding. thanks tim -- Tim Johnson <[tim--johnsons-web--com]> http://www.alaska-internet-solutions.com

 [2/20] from: volker:nitsch::gmail at: 30-Jul-2005 19:29


On 7/30/05, Tim Johnson <[tim--johnsons-web--com]> wrote:
> I'm working with a switch that has a lot of repetitive patterns: > i.e.:
<<quoted lines omitted: 23>>
> ;; say what? I thought 'load was supposed to bind words to global > ;; context!
This works: !>> do probe load rejoin["pri" "nt 1" " + 1"] [print 1 + 1 ] 2 So either you have 'output local, or the error-message is misleading. Because here lurks trouble: foreach [name layout] ;; makes the words implicitely local and then "append output do-" type " name layout" ;; uses global words. Some thinks coming to my mind: try do bind code 'output that should change the error-message, see above ;) code: compose[append output (to-word join "do-" type) name layout] that keeps more bindings. I would think about splitting the "do-something" in some kind of path too, like actions: [ "something" [.. ] "something-else" [..] ] code: compose[append output (actions/:type) name layout] do code and from there, why composing first? repend output[actions/:type name layout] Or, if you don't want to change all the "do-*", repend output [ to-word join "do-" type name layout ] ( I hope i made no mistakes, nothing tested.. )
> any help would be appreciated. I'd hate to do all that 'switch coding. > thanks
<<quoted lines omitted: 5>>
> To unsubscribe from the list, just send an email to > lists at rebol.com with unsubscribe as the subject.
-- -Volker Any problem in computer science can be solved with another layer of indirection. But that usually will create another problem. David Wheeler

 [3/20] from: tim::johnsons-web::com at: 30-Jul-2005 10:23


* Volker Nitsch <[volker--nitsch--gmail--com]> [050730 09:39]:
> On 7/30/05, Tim Johnson <[tim--johnsons-web--com]> wrote: > >
<<quoted lines omitted: 52>>
> repend output [ to-word join "do-" type name layout ] > ( I hope i made no mistakes, nothing tested.. )
You nailed it! I had to bind 'layout as well. Dunno why. ;; ...... code: load cat["append output do-" type " name layout" bind code 'output bind code 'layout Thanks very much. tim
> > any help would be appreciated. I'd hate to do all that 'switch coding. > > thanks
<<quoted lines omitted: 17>>
> To unsubscribe from the list, just send an email to > lists at rebol.com with unsubscribe as the subject.
-- Tim Johnson <[tim--johnsons-web--com]> http://www.alaska-internet-solutions.com

 [4/20] from: lmecir:mbox:vol:cz at: 31-Jul-2005 12:10


Hi Tim,
>I'm working with a switch that has a lot of repetitive patterns: >i.e.:
<<quoted lines omitted: 16>>
> ] > ]
....snip... that load rejoin [...] is a "beginner's gotcha" described in the doc. It brings more problems that it can solve. Don't use "command strings" when you don't have to, always use blocks - it is faster, safer and simpler. What about this one? type-handler: make object! [ button: func [name layout] [print "this is do-button" 'do-button] checkbox: func [name layout] [print "this is do-checkbox" 'do-checkbox] time: func [name layout] [print "this is do-time" 'do-time] hidden: func [name layout] [print "this is do-hidden" 'do-hidden] radio: func [name layout] [print "this is do-radio" 'do-radio] ] ; usage: output: copy [] foreach plist glbs/plists [ foreach [name layout] plist [ type: in type-handler to word! select layout "type" append output do type name layout ] ]

 [5/20] from: volker:nitsch:gma:il at: 31-Jul-2005 18:41


Hi Ladislav, Tim, all ;) On 7/31/05, Ladislav Mecir <[lmecir--mbox--vol--cz]> wrote:
> Hi Tim, > > >I'm working with a switch that has a lot of repetitive patterns:
[snip stuff about generating code-strings and doing them]
> that load rejoin [...] is a "beginner's gotcha" described in the doc. It > brings more problems that it can solve. Don't use "command strings" when
<<quoted lines omitted: 15>>
> ] > ]
Disclaimer: "beginners" does not mean "programming beginners" or small programs . Tims code surely produces the results he wants :) Means "not experts in the deeper tricks of rebol". I can understand "Beginners" doing it the string way. To do it the "professional way", one needs some knowledge about some functions. Like 'in and 'to and 'compose (/only /deep) and 'reduce (/only) subtleties with pathes: did/do not work everywhere, like in parse or get etc. "joined" words do. How to get a function out of a path? :a-function works. :a/function executes it. others? Building a string works fine until you you use own contexts. Which "beginners" don't do anyway. And a rejoin ["append output to-" type] may be easier to read as compose[append output (to-word join "to-" type)] (Hint hint hint: Don't read those sources, add a 'probe, run it, look at result!) Which is the first way they would try, before restructuring the data as in your example. Problems come when you get deeper. Start using contexts or strive for performance. Or just want to do it "right" ;) Maybe we need some Tutorial how to join code the "right" way? Maybe some people who join strings could post some examples, and us syntax-gurus try to explain improvements? With some explanation what they archive ("picking things from somewhere by name") -- -Volker Any problem in computer science can be solved with another layer of indirection. But that usually will create another problem. David Wheeler

 [6/20] from: tim::johnsons-web::com at: 31-Jul-2005 8:46


* Ladislav Mecir <[lmecir--mbox--vol--cz]> [050731 02:18]:
> > code: load rejoin["append output do-" type " name layout"] > > ?? code ;; see code "dump" below
<<quoted lines omitted: 8>>
> you don't have to, always use blocks - it is faster, safer and simpler. > What about this one?
Hi Ladislav: Boy am I behind in docs! What I have doesn't have any gotchas. Can you point me to those docs?
> type-handler: make object! [ > button: func [name layout] [print "this is do-button" 'do-button] > checkbox: func [name layout] [print "this is do-checkbox" 'do-checkbox] > time: func [name layout] [print "this is do-time" 'do-time] > hidden: func [name layout] [print "this is do-hidden" 'do-hidden] > radio: func [name layout] [print "this is do-radio" 'do-radio]
That's almost pythonistic in it's engineering (from me that's a complement) :-). However, if I understand you correctly, it would be as large and repetitive as the original switch.
> output: copy [] > foreach plist glbs/plists [ > foreach [name layout] plist [ > type: in type-handler to word! select layout "type" > append output do type name layout
I would upon recoding, place all type handlers in a context with the same name as the type. ;Then replace append output do type name layout ;; with append output type-handler/:type name layout Or even create a 'name and 'layout member for the type-handler context - to cut down on the interface specs for the methods. For the time being, the solution was to use do compose[append output (to-word join "do-" type) name layout]] ;; but a formal type-handler context is more professional, methinks Regards tim -- Tim Johnson <[tim--johnsons-web--com]> http://www.alaska-internet-solutions.com

 [7/20] from: lmecir::mbox::vol::cz at: 31-Jul-2005 23:24


Tim Johnson napsal(a):
>* Ladislav Mecir <[lmecir--mbox--vol--cz]> [050731 02:18]: >>> code: load rejoin["append output do-" type " name layout"]
<<quoted lines omitted: 17>>
> Boy am I behind in docs! What I have doesn't have any gotchas. > Can you point me to those docs?
See e.g. http://www.rebol.com/docs/core23/rebolcore-4.html#section-4.6: Unless it is necessary, evaluating strings is not generally a good practice...
>>type-handler: make object! [ >> button: func [name layout] [print "this is do-button" 'do-button]
<<quoted lines omitted: 7>>
> complement) :-). However, if I understand you correctly, it would > be as large and repetitive as the original switch.
That may be a misunderstanding. As far as I understand your code it uses a set of functions called DO-BUTTON, DO-CHECKBOX, DO-TIME, DO-HIDDEN, DO-RADIO, but you didn't "provide" them. So I just wrote a "bogus" implementation of the above mentioned functions to have a more complete example, that is all.

 [8/20] from: lmecir:mbox:vol:cz at: 31-Jul-2005 23:58


Tim Johnson napsal(a): ....
> That's almost pythonistic in it's engineering (from me that's a > complement) :-). However, if I understand you correctly, it would > be as large and repetitive as the original switch. >
.... If that is the case, then it is highly probable, that the design issue is deeper than you presented and the solution should be more complex. I have some code that solves such issues in a more elegant way (using associative arrays e.g.), but that is a "higher level" solution, i.e. it was possible only when I knew the actual problem more thoroughly than you described in your question. -Ladislav

 [9/20] from: tim:johnsons-web at: 31-Jul-2005 14:05


* Ladislav Mecir <[lmecir--mbox--vol--cz]> [050731 13:39]:
> See e.g. http://www.rebol.com/docs/core23/rebolcore-4.html#section-4.6:
Thanks! Keeping that by my bedside .....
> "Unless it is necessary, evaluating strings is not generally a good > practice..."
That's good advice for any language (but javascript, which has no file/system access) I do bend the rules when I do something quick-and-dirty not meant for public access and is performance is not an issue. But then one can forget and leave in tacky code. thanks tim
> >>type-handler: make object! [ > >> button: func [name layout] [print "this is do-button" 'do-button]
<<quoted lines omitted: 46>>
> To unsubscribe from the list, just send an email to > lists at rebol.com with unsubscribe as the subject.
-- Tim Johnson <[tim--johnsons-web--com]> http://www.alaska-internet-solutions.com

 [10/20] from: tim:johnsons-web at: 31-Jul-2005 14:26


* Ladislav Mecir <[lmecir--mbox--vol--cz]> [050731 14:04]:
> Tim Johnson napsal(a): > ...
<<quoted lines omitted: 10>>
> was possible only when I knew the actual problem more thoroughly than > you described in your question.
I spend (roughly) equal times in python and rebol. After being up to my elbows in python, it is always refreshing to get back to rebol, but when I switch from rebol to python, I find myself enjoying python dictionaries, both the explicit ones and the builtin _dict_ structures. # Example: explicit def do_sql(name,layout): dispatch = { 'radio':kbLists.do_sql_radio(), 'text':kbLists.do_sql_text(), 'textarea':kbLists.do_sql_textarea(), 'decimal':kbLists.do_sql_decimal(), 'uinteger':kbLists.do_sql_uinteger(), 'select':kbLists.do_sql_select(), 'date':kbLists.do_sql_date(), 'checkbox':kbLists.do_sql_checkbox(), 'password':kbLists.do_sql_text(), } return ' %s %s,' % (name,dispatch[layout['type']]) # Example: using builtin _dict_ in class constructor def __init__(self, url='', text='', **kw): self.target = None self.onClick = None self.onMouseOver = None self.onMouseOut = None self.url = url self.text = text # target ... text constitutue self.__dict__ when they are # preceded by 'self.' for item in kw.keys(): if self.__dict__.has_key(item): self.__dict__[item] = kw[item] else: raise KeyError, `item`+' not a valid parameter for this class.' I've written an associative list context for rebol but it is very simple and does not well employ rebol's reflective and self-composing features. I seldom use it directly but from another context. I have found that sometimes when you use examples of another language in a specific language forum, some might protest, but for me, it is oftentimes productive to work out a solution in one language and translate to another. In the days of slower processors, python was often used to prototype code that was then translated to C or C++, or so it did advertise itself. Tim -- Tim Johnson <[tim--johnsons-web--com]> http://www.alaska-internet-solutions.com

 [11/20] from: antonr::lexicon::net at: 1-Aug-2005 17:58


Hi Tim,
> I have found that sometimes when you use examples of another language in > a specific language forum, some might protest, but for me, it is > oftentimes productive to work out a solution in one language and > translate to another.
Rebol is quite different so translating "literally" doesn't work all that well. Happily, refactoring it in rebol will likely shrink your code by half. Anton.

 [12/20] from: antonr:lexicon at: 1-Aug-2005 19:22


Hi Tim, Your code below seems to be generating code using a macro. It seems extremely unwieldy to me and needs a clever bit of rebol to shrink it to its essence. What are the changing parts (what value and type are they) ? It looks to me like the changing parts are: - widget style - widget feel where the feel is just used to detect different key presses (?) I would love to know the intention of your code so we can refactor it. Anton.

 [13/20] from: lmecir::mbox::vol::cz at: 1-Aug-2005 12:05


I think, that it is necessary to articulate the "rule of thumb" regarding string execution: *Do not transform Rebol code to string, if you are going to evaluate it*. Let's have a look at the original code: code: load rejoin["append output do-" type " name layout"] ?? code ;; see code "dump" below do code So, what is wrong about it? The wrong part is, that there is a transformation of legal Rebol code [append output do-type name layout] to string and back again, while the only thing that had to be transformed was the do-type part and it had to be transformed *from* string, i.e. in the opposite direction. Is that understandable enough for less experienced readers? -L

 [14/20] from: lmecir::mbox::vol::cz at: 1-Aug-2005 12:27


Ladislav Mecir napsal(a):
>I think, that it is necessary to articulate the "rule of thumb" >regarding string execution:
<<quoted lines omitted: 10>>
>Is that understandable enough for less experienced readers? >-L
Appendix: the code above is a wrong way, so what is the "right beginner's way" of doing things in this case? Here is the simplest way I came to: ; transform the type string to a word and get the value of it do-type: get to word! join "do-" type ; evaluate the code append output do-type name layout *Warning! because the do-type "translation" uses TO WORD!, the word created this way will be global, while the original intention of the programmer might have been to use e.g. 'do-checkbox word, which was meant to be local.* How to make the code more "bulletproof", i.e. not being "caught" by the fact, that TO WORD! creates globals? Here is an improvement: ; transform the type string to a do-... word in the same context as the 'do-radio word is and get its value do-type: get bind to word! join "do-" type 'do-radio ; evaluate the code append output do-type name layout Hope it will be of some use. -Ladislav

 [15/20] from: greggirwin:mindspring at: 1-Aug-2005 7:45


Hi Ladislav, This is one of the areas that would benefit from some official documentation that discusses how to work with dynamic code in more detail. I think you're on the right track, though, in having some examples for beginners. -- Gregg

 [16/20] from: tim:johnsons-web at: 1-Aug-2005 7:24


* Anton Rolls <[antonr--lexicon--net]> [050801 01:38]:
> Hi Tim, > Your code below seems to be generating code using a macro.
<<quoted lines omitted: 7>>
> I would love to know the intention of your code so we > can refactor it.
<grin> We just did. We refactored it in rebol. Yes. python is cumbersome, but it scales well, and some customers want it. Even the code below could be factored more. FI: dispatch should be a method of kblists... tim
> Anton. > > # Example: explicit
<<quoted lines omitted: 11>>
> > } > > return ' %s %s,' % (name,dispatch[layout['type']])
to elaborate: python automagically builds in internal dictionary with the declared class members. Among other things, it allows testing for validity of keyword values... thus the 'for item in keys' test loop.
> > # Example: using builtin _dict_ in class constructor > > def __init__(self, url='', text='', **kw):
<<quoted lines omitted: 15>>
> To unsubscribe from the list, just send an email to > lists at rebol.com with unsubscribe as the subject.
-- Tim Johnson <[tim--johnsons-web--com]> http://www.alaska-internet-solutions.com

 [17/20] from: tim::johnsons-web::com at: 1-Aug-2005 8:19


* Ladislav Mecir <[lmecir--mbox--vol--cz]> [050801 02:38]:
> Ladislav Mecir napsal(a): > >I think, that it is necessary to articulate the "rule of thumb"
<<quoted lines omitted: 30>>
> programmer might have been to use e.g. 'do-checkbox word, which was > meant to be local.*
It should be noted in this case that all of the do-* subroutines *are* global. Makes it moot in this case, but your attention to this issue is very well taken, and I hope that this can be used as further examples to illustrate the many subtleties in rebol evaluation. I note that rebol and Common Lisp have much in common. In fact, Carl states that Lisp is an influence on rebol. And part of the similarities is the great variety of ways that sympols and lists (blocks) of symbols can be evaluated. Lisp, however, has a larger variety of 'operators' and also has a larger code base. There is more documentation and more of example code base available. In sum evaluation is the "agony and ecstasy of rebol" and probably needs more attention in documentation and illustration. newbies (and that's me after 5 years) could be well advised to analyze the dynamically composed code closely and look out for "leaks" such as could be created in this example because they can raise bloody hell somewhere down the execution path. Thanks Good thread tim
> How to make the code more "bulletproof", i.e. not being "caught" by the > fact, that TO WORD! creates globals? Here is an improvement:
<<quoted lines omitted: 8>>
> To unsubscribe from the list, just send an email to > lists at rebol.com with unsubscribe as the subject.
-- Tim Johnson <[tim--johnsons-web--com]> http://www.alaska-internet-solutions.com

 [18/20] from: volker:nitsch:gma:il at: 1-Aug-2005 21:59


Hi Tim, On 8/1/05, Tim Johnson <[tim--johnsons-web--com]> wrote:
> * Anton Rolls <[antonr--lexicon--net]> [050801 01:38]: > >
<<quoted lines omitted: 21>>
> of kblists... > tim
Maybe looking at other languages and showing how to do that in rebol is not to bad for bilinguists. After all rebol can do pretty conventional oops.. And i would learn what return ' %s %s,' % (name,dispatch[layout['type']]) does! :) So lets enter a lesson of Dr Rebols tutorial SQUEEZING CODE LIKE A PYTHON! Ok, first lets enter the area of rebol-psychology. Did you know rebol has a first self and a second self? And when getting older, even got a third? see: pdp: func[dump][print mold/all do ?? dump] proof: context[ me: does[pdp[first self]] metoo: does[pdp[ second self]] methree: does[pdp[ third self]] me metoo methree ] --output: dump: [first self] [self me metoo methree] dump: [second self] [ #[object! [ me: #[function! [][pdp [first self]]] metoo: #[function! [][pdp [second self]]] methree: #[function! [][pdp [third self]]] ]] #[function! [][pdp [first self]]] #[function! [][pdp [second self]]] #[function! [][pdp [third self]]]] dump: [third self] [me: #[function! [][pdp [first self]]] metoo: #[function! [][pdp [second self]]] methree: #[function! [][pdp [third self]]]] (Exercise: figure out what these selfs are ;)
> > Anton. > >
<<quoted lines omitted: 12>>
> > > } > > > return ' %s %s,' % (name,dispatch[layout['type']])
i hope i get it: pdp: func [dump] [print mold/all do ?? dump] ; python can easily put kbLists.do_sql_radio() in a list. ; rebol likes to buck when getting functions from pathes. ; so i resort to using functions, more ugly, other way shown later. ; i want to stay close to python-code. do_sql: func [name layout /local dispatch] [ dispatch: reduce [ "radio" get in kb-lists 'do_sql_radio "text" get in kb-lists 'do_sql_text ; .. ] reduce [name select dispatch layout/type] ] kb-lists: context [ do_sql_radio: does [#radio] do_sql_text: does [#text] ; .. ] layo: [ type "radio" ; .. ] pdp [do_sql "name" layo] ; if the dispatchees are always from lb-lists, we can do do_sql: func [name layout /local dispatch word] [ dispatch: [ "radio" do_sql_radio "text" do_sql_text ; .. ] word: select dispatch layout/type reduce [name get in kb-list word] ] ; and if the words match to the names, like "radio" -> "do_sql_radio" do_sql: func [name layout /local dispatch word] [ word: to-word join "do_sql_" name reduce [name get in kb-list word] ] ; i guess python has similar ways to get from a string to a function, ; tell me ;)
> to elaborate: python automagically builds in internal dictionary > with the declared class members. Among other things, it allows > testing for validity of keyword values... > thus the 'for item in keys' test loop. >
See rebol-psychology above ;)
> > > # Example: using builtin _dict_ in class constructor > > > def __init__(self, url='', text='', **kw):
<<quoted lines omitted: 13>>
> > > for this class.' > >
clazz: context [ ; extra 'demo^init to allow super-call, we are pythonizing init: demo^init: func [kw /url url* /text text*] [ foreach item next first kw ; the "keys", skip 'self [ either in self item [ self/:item: get in kw item ; if it can be functions, else kw/:item is ok ] [ make error! rejoin [ "KeyError, " item " not a valid parameter for this class." ] ] ] self ] ; can be initialized immediate target: on-click: on-mouse-over: on-mouse-out: none ] demo: make clazz [] probe demo/init context [on-click: does["click"]] probe demo/init context [on-magic: does["magic"]] ; in this simple case we would use the inbuild stuff of course: demo: make clazz [ on-click: does["click"] ]
> -- > Tim Johnson <[tim--johnsons-web--com]> > http://www.alaska-internet-solutions.com > -- > To unsubscribe from the list, just send an email to > lists at rebol.com with unsubscribe as the subject. >
-- -Volker Any problem in computer science can be solved with another layer of indirection. But that usually will create another problem. David Wheeler

 [19/20] from: tim:johnsons-web at: 1-Aug-2005 14:22


Volker: The entire text of your email is very had to read. My mailer is receiving it full of equal signs and number combination and is practically speaking, obfuscating your code. What's up? Is this your mailer, or my mailer or is it the mailing list? I see this a lot especially in this ML. I know that you have much good code to share, but I just can't see it for all of the weird text. Sorry Tim * Volker Nitsch <[volker--nitsch--gmail--com]> [050801 12:15]:
> Hi Tim, > On 8/1/05, Tim Johnson <[tim--johnsons-web--com]> wrote:
<<quoted lines omitted: 183>>
> To unsubscribe from the list, just send an email to > lists at rebol.com with unsubscribe as the subject.
-- Tim Johnson <[tim--johnsons-web--com]> http://www.alaska-internet-solutions.com

 [20/20] from: volker::nitsch::gmail::com at: 2-Aug-2005 1:16


On 8/2/05, Tim Johnson <[tim--johnsons-web--com]> wrote:
> Volker: > The entire text of your email is very had to read. My mailer is
<<quoted lines omitted: 4>>
> I know that you have much good code to share, but > I just can't see it for all of the weird text.
I get the same. copypasted all from linux-view to firefox. Till now i have never deleted and replaced the whole text, maybe that confuses something. Will try testing a bit
> Sorry > Tim > > * Volker Nitsch <[volker--nitsch--gmail--com]> [050801 12:15]: > > > > Hi Tim, > >
[snip] ---Volker Any problem in computer science can be solved with another layer of indirection. But that usually will create another problem. David Wheeler

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