[REBOL] [SELECT SWITCH CASE] SELECT-CASE (was: The best shortcut word for "not none?")
From: greggirwin::mindspring::com at: 6-Sep-2006 11:49
LM> OK, here is the improved version, which I am proposing to Carl too:
LM> REBOL [
LM> Author: ["Ladislav Mecir" "Gabriele Santilli"]
LM> Purpose: "A SWITCH alternative, see example"
LM> ]
LM> switch1: func [
LM> "Selects a choice and evaluates the first block that follows it."
LM> [throw]
LM> value "Value to search for."
LM> cases [block!] "Block of cases to search."
LM> /default case [block!] "Default case if no others are found."
LM> ][
LM> if value: find cases value [value: find next value block!]
LM> do either value [first value] [case]
LM> ]
LM> example: [
LM> switch1 1 [2 4 6 ['even] 1 3 5 ['odd]]
LM> ]
My only concern is that it's a significant semantic change from the
current behavior, so it could break code. That said, I know *my* brain
always wants to think of SWITCH and SELECT as working against an
implied "/SKIP 2" refinement, which is not the case.
I don't think it will break much, if any, code, but the potential is
there. Ignoring compatibility, I think it's a much more powerful
model, and clearer in intent. That is, it makes it obvious that the
distinction is between non-block values (tests) and blocks (actions).
I would vote for this change, because we also have the CASE function
(a recent addition); that *does* support the condition-action model.
Let me add another thought to the mix. Coming from BASIC dialects, I
can tell you that the SELECT CASE statement was very useful (IMO). I
mention it because it supports the same concept of testing multiple
values as SWITCH1 that Ladislav posted.
Here is an example for those not familiar with it:
SELECT CASE string_expression
CASE > b$ ' relational; is expression > b$?
' <action>
CASE "X" ' equality (= is assumed); is expression equal
' to "X"?
' <action>
CASE "A" TO "C" ' range; is expression between "A" and "C"
' (inclusive)?
' <action>
CASE "Y", b$ ' two equality tests; is expression equal to
' "Y" or equal to b$?
' <action>
CASE "A" TO "C","Q" ' combination range and equality; is
' expression between "A" and "C" (inclusive)
' or equal to "Q"?
' <action>
CASE ELSE
' <action>
END SELECT
In REBOL, tests might look like this:
select-case expr [
:negative? value [] ; value ref's 'expr
< 3 []
case is < 5 []
6 to 10 []
between 11 and 15 []
from 16 to 20 []
21 23 25 []
[find [22 24] value] [] ; value ref's 'expr
26 to 100 or 175 []
case is > 1000 []
case else []
]
The implementation won't be as concise as the current SWITCH approach,
but the idea is that a small dialect can save us a lot of work and
make our application code more readable. How to reference the value
(expr) is something to think about, where it's always implied in
BASIC.
The other concept this ties into is ranges and bounds. I've mentioned
that a few times before, so I won't go into it here again, but I think
that's another powerful model worth considering in REBOL.
-- Gregg