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

[REBOL] Re: Switch with refinements/hmmm!

From: joel:neely:fedex at: 1-Nov-2001 14:10

Hi, Media, (Is that your real name, or is it short for Mediator? ;-) Media wrote:
> > If you expect at most one refinement to be used > > > > refine-switch: func [ /refa /refb /refc ] [ > > either refa [ > > print "ref A" > > ][either refb [ > > print "ref B" > > ][either refc [ > > print "ref C" > > ][ > > print "NO ref" > > ]]] > > ] > > I just thought I'd share some knowledge... The above can also > be coded like so: > > refine-switch: func [ /refa /refb /refc ] [ > any[ > all [refa print "ref A"] > all [refb print "ref b"] > all [refc print "ref c"] > print "NO ref" > ] > ] > > this sort of fixes doc kimbel's approach IMHO >
I'm afraid it doesn't. If an ALL block contains an expression which evaluates to NONE or FALSE, then that block is short- circuit exited at that point. A trivial example is all [optionflag locword: none otherstuff] in which OTHERSTUFF never gets evaluated. This could be "fixed" by rewrapping the rest of the block after OPTIONFLAG as all [optionflag do [locword: none otherstuff]] but that's just obfuscation IMHO, if what we're really trying to say is if optionflag [locword: none otherstuff]
> you could also code the following: > > refine-switch: func [ /refa /refb /refc ] [ > any[ > all [refa refb refc print "all refs are set !"] > all [refa refb print "ref a & b"] > all [refa refc print "ref a & c"] > all [refb refc print "ref b & c"] > all [refa print "ref a"] > all [refb print "ref b"] > all [refc print "ref c"] > print "NO ref" > ] > ] > > this approach actually handles all cases... either all, two > or only one of the refs may be set, and you can react > differently to each different case. >
Hmmmm... Two thoughts: 1) This has the same short-circuit-exiting issue as described above. 2) This creates a combinatorial explosion as more refinements are added. Adding /REFD to the mix *doubles* the size of the code, as opposed to refcombos: func [/refa /refb /refc /local r n limit check] [ r: copy [] n: 0 limit: 3 check: func [opt label] [ if opt [repend r [pick ["&" ""] (n: n + 1) > 1 label]] ] check refa "A" check refb "B" check refc "C" print switch/default n reduce [ 0 ["NO refs"] limit ["all refs are set !"] ][join "ref " form r] ] which scales up linearly with an increasing number of options.
> the nice thing about the any and all combo is that its VERY > easy to create large or complex value filters. the syntax > so simple, it doesn't make such a bad program if you insert > the values by hand like I did above... doing that in IF/ELSE > would have been a MAJOR pain... just try it you'll see. >
... but notice also that it can require LOTS of redundant evaluation of the same refinements. Compared with reftree: func [/refa /refb /refc] [ either refa [either refb [either refc [print "all refs are set!"] [print "ref A & B"]] [either refc [print "ref A & C"] [print "ref A"]]] [either refb [either refc [print "ref B & C"] [print "ref B"]] [either refc [print "ref C"] [print "NO refs"]]] ] (which only evaluates each refinement once) it looks like a classic case of "pay me now or pay me later". We either spend programmer time to craft a faster process or we spend the cycles at run time. -jn- -- This sentence contradicts itself -- no actually it doesn't. -- Doug Hofstadter joel<dot>neely<at>fedex<dot>com