#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]
]

Reply via email to