Hi Ladislav,
You wrote:
>Sorry for disappointing you, but the proposed version doesn't
>handle correctly the computed blocks and Break. A different
>approach:
Actually you haven't disappointed me, because I didn't intend to
handle computed blocks, and BREAK seems to work as well as I'd hope
it to. But since you as the author of PIF have the final say as
to what is correct and incorrect behavior, I'll rename my reworking
of your function to REIF and try to explain clearly what I had
in mind. Note that this is a revision of my original suggestion to
Joel, but its handling of blocks and BREAK is still basically
the same.
REIF takes a block argument of the following structure:
[
sub-expression value
sub-expression value
...
sub-expression value
optional-value
]
Each sub-expression is evaluated until one returns a true value (i.e.
anything but NONE or FALSE). If the value following that sub-expression
is a block, its contents are evaluated and the return value is returned.
If that value is anything besides a block, it is returned. Any value
following a sub-expression that evaluates false is skipped over. If no
sub-expression returns a true value and there is a final optional-value,
it is handled as if it were a value following TRUE. If there is no
optional-value, FALSE is returned.
That's pretty simple-minded, I'll agree, but that's how I wanted it.
Here're a couple of examples of it in use:
>> for x 1 10 1 [ reif [
[ zero? x // 2 [print [x "is even"]]
[ x = 5 [print [x "and no more!"] break]
[ ]]
2 is even
4 is even
5 and no more!
>> foreach x [
[ "various" "strings" "to test" "and examine" "with find and reif"
[ ][ reif [
[ find x "x" [print "it's got an x - bailing out!" break]
[ p: find x " " [print ["it's got a space at" index? p]]
[ ]]
it's got a space at 3
it's got an x - bailing out!
With your latest version of PIF this happens:
>> foreach x [
[ "various" "strings" "to test" "and examine" "with find and pif"
[ ][ pif [
[ find x "x" [print "it's got an x - bailing out!" break]
[ p: find x " " [print ["it's got a space at" index? p]]
[ ]]
== " find and pif"
which isn't so useful. If FIND returns a true value, you might want to
do something with that value before returning. I don't see why you
should restrict doing the following block only to those cases where
the sub-expression actually returns the logic value TRUE.
I'd be very happy to hear more about what you intended with PIF,
and where you think REIF could be improved.
Thanks again,
Eric
========== code ==========
reif: func [
[throw]
{if with multiple conditions - descended from,
but not to be confused with, PIF by Ladislav Mecir}
args [block!]
/local choice
] [
choice: false
while [not tail? args] [
if 1 = length? args [
choice: first args
break
]
args: do/next args
if all [
not unset? first args
first args
][
choice: first second args
break
]
args: skip second args 1
]
either block? choice [do choice][choice]
]
reif2: func [
[throw]
{recursive multiple-choice if - thanks Ladislav!}
args [block!]
/local choice
] [
either 1 = length? args [db first args][
args: do/next args
either all [
not unset? first args
first args
][
db first second args
][ reif2 skip second args 1 ]
]
]
db: func [[throw] arg] [
either block? arg [do arg] [arg]
]
pif: func [[throw]
{polymorphic if, lazy evaluation, minimal checking}
args [block!]
] [
either unset? first args: do/next args [] [
either first args [
either logic? first args [
db first do/next second args
] [
db first args
]
] [pif second do/next second args]
]
]