[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