r3wp [groups: 83 posts: 189283]
  • Home
  • Script library
  • AltME Archive
  • Mailing list
  • Articles Index
  • Site search
 

World: r3wp

[RAMBO] The REBOL bug and enhancement database

Gabriele
24-Nov-2006
[2198x2]
With some help from Carl, I got to this:

switch: func [
    "Selects a choice and evaluates the block that follows it."
    [ throw ]
    value "Value to search for."
    cases [block!] "Block of cases to search."
    /default case "Default case if no others are found."
    /all "Evaluate all matches (not just first one)."

    /local code found?
][
    code: clear [ ]
    while [cases: find cases value] [
        either cases: find next cases block! [
            found?: yes
            append code first cases
            cases: next cases
            unless all [break]
        ] [break]
    ]
    do either found? [code] [case]
]
two local words, but shorter. also, it turns out that using a path 
for system/words/all is slower than using the either inside the while.
[unknown: 5]
24-Nov-2006
[2200]
thats cool Gabriele.  Nice and concise
Chris
24-Nov-2006
[2201x2]
I had this (how many ways to skin a cat?):
switch: func [val cases /all /default case][
    all: if all [make block! []] 
    while [cases: find/tail cases val] [
        either cases: find cases block! [
            either all [
                case: append all first cases
            ][
                case: first cases
                break
            ]
        ][break]
    ]
    do case
]
[unknown: 5]
24-Nov-2006
[2203x3]
I like Carl's code - I can't remember the last time I used the 'unless 
function.
or your code Gabriele - or both
Ok I looked at the performance from a trace perspective of three 
switch implementations - mine, Gabriels and Chris's.  Out of all 
of them mine was least efficient, while Chris's was the most efficient. 
 So if all of them do what is needed then I would say go with Chris's 
implementation.
Henrik
24-Nov-2006
[2206]
what if append was replaced with insert tail? that would make it 
a tiny bit faster
[unknown: 5]
24-Nov-2006
[2207]
Yes I would think so Henrik
Chris
24-Nov-2006
[2208]
Don't forget that 'append will be made native.  Also is it faster 
yet to change the first line to -- all: if all [clear []] -- as with 
Gabriele's function?
[unknown: 5]
24-Nov-2006
[2209x3]
I can check
Yep barely faster
When I say faster I mean in less trace output
Henrik
24-Nov-2006
[2212]
paul, that's a good idea, using trace to do that. wonder if that 
could be wrapped into a counting function that counts the amount 
of trace output?
[unknown: 5]
24-Nov-2006
[2213]
I do it all the time to optimize my scripts these days
Henrik
24-Nov-2006
[2214x2]
trace is native. I vote for adding something to trace to make stats 
from the output, perhaps just a single integer that shows how many 
functions were run through.
I hardly ever use it because I think it provides too much output
[unknown: 5]
24-Nov-2006
[2216x2]
yeah but it gives you a good idea of what is going on.
especially the resulting values
Henrik
24-Nov-2006
[2218]
is it possible to store trace output?
[unknown: 5]
24-Nov-2006
[2219x2]
sure
you can use echo or copy from the console
Henrik
24-Nov-2006
[2221]
hmm.... a bit inflexible, I think. It would be nice to bypass console 
output, and store the output in memory for later scrutiny. this would 
avoid needing to popup a console to an end user.
[unknown: 5]
24-Nov-2006
[2222x3]
just echo the information
before you turn on trace just do this:
echo %trace.txt
Henrik
24-Nov-2006
[2225]
still outputs to console. I'd like to avoid that.
[unknown: 5]
24-Nov-2006
[2226x2]
oh I see
I never tried it - or had need to without console output
Henrik
24-Nov-2006
[2228]
well, I'm not sure how useful trace is to me anyway.
Gabriele
24-Nov-2006
[2229x4]
chris, that is nice too.
about trace, if you need a count you can probably just use the STATS 
function.
however, in a trace a call to a slow function will count the same 
as a call to a fast function.
(second stats/eval should be the number of function calls)
[unknown: 5]
24-Nov-2006
[2233x2]
wow I just looked at stats on the latest view 2.7.1 and never noticed 
all the options for it before.
Yeah that is very useful Gabriele.
Anton
25-Nov-2006
[2235x6]
Paul, I don't share your concern about using ALL as a refinement 
of switch. I don't see that "killing the global ALL function" is 
a risk here. We are all aware of the danger of accidentally leaking 
words.
The advantage is we gain the freedom to use any word we like for 
the user interface.
Gabriele, slight optimization, swap these two lines:
            cases: next cases
            unless all [break]
Also, does this line:
	code: clear [ ]
mean that switch can't be used recursively ?
Chris' version looks pretty good too. (He just needs to document 
it properly.. :P)
Chris, what about [throw] ?
Gabriele
25-Nov-2006
[2241]
calling switch recursively - hmm, indeed it will be a problem. then 
i prefer chris' version which can avoid the allocation if not needed.
Anton
25-Nov-2006
[2242]
Yes, Chris' first line now seems clear to me. :)
Chris
25-Nov-2006
[2243x2]
Indeed I did abbreviate the function header.
Re. recursive, if you were to make block! [] instead of clear [] 
- I guess it's a difference in resultant garbage: with 'make the 
block becomes unbound when a subsequent switch is called, while with 
clear the cleared values become unbound.
[unknown: 5]
25-Nov-2006
[2245x3]
do we even need 'all - I mean I think we should just make that the 
default for switch and leave select to do the light lifting.
here is a switch that defaults to 'all
switch: func [
    "Finds all choices and evaluates what follows each."
    [throw]
    value "Value to search for."
    cases [block!] "Block of cases to search."
    /default case "Default case if no others are found."
    
][  
    default: copy []
    while [cases][
        if cases: find cases value [
            append default first cases: find cases block! 
        ]
    ]
    if not empty? default [case: default]
    do case    
]