#1 - If
I use If as a good example of polymorphism. In Rebol we have two
variants- If and Either (which is better and more readable/simple
than the obsolete If ... Else pair).
In other languages are constructs like:
if ... then ... endif
if ... then ... else ... endif
if ... then ... elsif ... else ... endif
Enough words. Let's see an example:
sign1: func [x [number!]] [
either x < 0 [ -1] [
either x = 0 [0] [1]
]
]
This is a well-known function. Lots of Rebols dislike the above
code (eg. Jeff, IIRC) and I don't blame them - it really isn't too
readable. They invented a nicer, although less general code not
using If at all:
sign2: func [x [number!]] [
to integer! (x > 0) - to integer! (x < 0)
]
The problem is, that this code isn't useful as a recipe what to do
in the similar cases, where you have more than two possibilities
to choose from, and, moreover, the code looks a little bit
cryptic. I think, that more polymorphic approach to functions in
Rebol could do well in this case (and in other cases too, as I
will try to show later...).
sign3: func [x [number!]] [
pif [
x < 0 [-1]
x = 0 [0]
[1]
]
]
For this to work, one needs a polymorphic if (Pif) function in
Rebol, that can take unlimited number of arguments. That isn't
hard to write in Rebol, as can be seen below (although a more
elegant version could be helpful). As a benefit we get a function
less error-prone than the original.
BTW, Joel, i liked your (NON)boring version of CC verify function
description (I catched myself using some principles you
diapproved - especially the code copying is really a drug
sometimes...). Could you PLEASE write similarly critical notes on
the code below?
; polymorphic if
pif: func [block [block!] /local current state1 state2 count][
;argument evaluation
block: reduce block
; argument check
state1: 0
foreach elem block [
state2: either logic? elem [0] [
either block? elem [1] [
print "Error. Pif expected logic/block."
halt
]
]
; state1 table:
; 0 - no values found
; 1 - first logic found
; 2 - at least one logic/block pair found
; 3 - next logic found
; 4 - the else block found
state1: switch state1 * 2 + state2 [
0 [1]
1 [print "Error. Pif expected logic." halt]
2 [print "Error. Pif expected block." halt]
3 [count: 1 2]
4 [3]
5 [4]
6 [print "Error. Pif expected block." halt]
7 [count: count + 1 2]
8 [print "Error. Pif expected end." halt]
9 [print "Error. Pif expected end." halt]
]
]
if all [state1 <> 4 state1 <> 2] [
print "Error. Pif expected more."
halt
]
; now the execution
current: block
for i 1 count 1 [
if first current [
return do second current
]
current: next next current
]
either empty? current [false] [do first current]
]