[REBOL] Rebol/Core User's Guide Re:(5)
From: joel:neely:fedex at: 12-Oct-2000 8:02
[giesse--dsiaq1--ing--univaq--it] wrote:
> [joel--neely--fedex--com] wrote:
>
> > I had expected that the argument type check would barf on my little
> > pathological case, but it didn't!!!!!
>
> It doesn't for the simple reason that:
>
> >> type? :b
> == paren!
> >> probe :b
> (a: negate a)
> == (a: negate a)
> >> type? b
> == integer!
> >> probe b
> -1
> == -1
>
> So you're actually passing an integer, not a paren, to IFS.
>
Yes. It finally sunk in... ;-)
> > so you can imagine my surprise to obtain these results!
> [...]
>
> You're still passing an integer, here. (You get "zero" because you
> have written IFS as:
>
> ifs: func [[throw] cexp pblk zblk nblk /local cval] [ ...
>
> notice PBLK ZBLK NBLK instead of PBLK NBLK ZBLK.)
>
> > Well, it appears that do does NOT distribute over evaluation of its
> > argument!!!!!
>
> It does, don't worry. :-)
>
I'm delighted to stand corrected. To quote someone from an earlier
post, "Silly me!"
> Anyway, let me partecipate with my own version:
>
> >> sign: func [num [number!]] [either zero? num [0] [divide num abs num]]
> >> sign 2
> == 1
> >> sign -2
> == -1
> >> sign 0
> == 0
>
Nice! Let me further suggest
signum: func [val [number! char! money! time!]] [
either zero? val [0] [either negative? val [-1] [1]]]
The change of name is suggested to reduce reading-aloud confusion
betweeen "sign" and "sine" -- from an old math textbook.
The replacement of your elegant division with more explicit logic
is to allow the domain to include all argument types accepted by
Positive? , Negative? , and Zero? .
> >> ifs: func [
> [ [throw]
> [ num [number!]
> [ if-pos [block!]
> [ if-zero [block!]
> [ if-neg [block!]
> [ ] [
> [ do get pick [if-neg if-zero if-pos] add 2 sign num
> [ ]
>
An elegant solution to the multiple-evaluation problem! My
compliments!
> >> ifs -2 ["positive"] ["zero"] ["negative"]
> == "negative"
> >> ifs 0 ["positive"] ["zero"] ["negative"]
> == "zero"
> >> ifs 2 ["positive"] ["zero"] ["negative"]
> == "positive"
>
> Seems to work as expected. With B also:
>
> >> ifs b ["positive"] ["zero"] ["negative"]
> == "positive"
> >> ifs b ["positive"] ["zero"] ["negative"]
> == "negative"
> >> ifs b ["positive"] ["zero"] ["negative"]
> == "positive"
>
> Notice that:
>
> >> ifs :b ["positive"] ["zero"] ["negative"]
> ** Script Error: ifs expected num argument of type: number.
> ** Where: ifs :b ["positive"] ["zero"] ["negative"]
>
Inspired by your Ifs above, let me offer to remove the type
constraint...
ifs: func [
[throw]
num if-pos [block!] if-zero [block!] if-neg [block!]
][
do get pick [if-neg if-zero if-pos] add 2 signum num]
...provide another pathological B ...
>> a: 1 == 1
>> b: to-paren [a: a + 2 // 3 - 1] == (a: a + 2 // 3 - 1)
>> b == -1
>> b == 0
>> b == 1
>> b == -1
>> b == 0
>> b == 1
Which seems to work both with B and :B ...
>> ifs b ["pos"] ["zero"] ["neg"] == "neg"
>> ifs b ["pos"] ["zero"] ["neg"] == "zero"
>> ifs b ["pos"] ["zero"] ["neg"] == "pos"
>> ifs :b ["pos"] ["zero"] ["neg"] == "neg"
>> ifs :b ["pos"] ["zero"] ["neg"] == "zero"
>> ifs :b ["pos"] ["zero"] ["neg"] == "pos"
-jn-