[REBOL] Who is that grouch? -or- Fun with functions!
From: joel::neely::fedex::com at: 4-Oct-2000 22:35
I fear that anyone reading my last few posts may conclude that I'm
a real grouch. (Of course, it's not necessary to read my emails to
draw that conclusion! ;-)
In the interest of Suitable Doses of Levity, let's have fun with
functions in REBOL!
First, let's define an oldie from APL:
>> iota: function [n [integer!]] [r i] [
[ r: copy []
[ i: 0
[ while [i < n] [append r i: i + 1]
[ r
[ ]
>> iota 20
== [1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20]
>> iota 100
== [1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42
43 44 45 4...
...so that iota n returns a block containing the first n positive
integers.
Now let's do another oldie, this time from Lisp and Perl:
>> map: function [[catch] b [block!] f [function!] /all] [r v] [
[ r: copy []
[ foreach c b [
[ if any [found? v: do [f c] all] [append/only r v]
[ ]
[ r
[ ]
...so that map some-block some-single-arg-function returns a
block containing the results of applying the function to each
element of the argument block. (Results of none are suppressed
unless the /all refinement is supplied with the call.)
Thus we have...
>> map iota 20 func [n] [n + n - 1]
== [1 3 5 7 9 11 13 15 17 19 21 23 25 27 29 31 33 35 37 39]
...the first twenty odd positive integers.
Now let's get creative, and define:
>> nondiv: func [d] [func [n] [either n // d = 0 [none] [n]]]
...so that nondiv n returns a function that transforms anything
divisible by n to none and leaves all other values alone.
(Yes, I know I forgot the type specs... It's close to bedtime!)
With this new toy, we can compute:
>> map iota 20 nondiv 3
== [1 2 4 5 7 8 10 11 13 14 16 17 19 20]
...all integers between 1 and 20 that aren't divisible by 3. By:
>> map/all iota 20 nondiv 3
== [1 2 none 4 5 none 7 8 none 10 11 none 13 14 none 16 17 none
19 20]
...we see that the /all refinement is doing its job.
STOP! Have you guessed where this is heading yet?
An all-around trivial-but-handy numeric function is:
>> square: func [n [number!]] [n * n]
...which does Just What You Think It Does.
With all of these nice toys in hand, we are now in a position to
define:
>> plist: function [n [integer!]] [p c d] [
[ p: copy []
[ c: next iota n
[ while [0 < length? c] [
[ append p d: first c
[ c: map c nondiv d
[ ]
[ p
[ ]
...so that we can say things like:
>> plist 50
== [2 3 5 7 11 13 17 19 23 29 31 37 41 43 47]
In case you were wondering why we defined square (other than to
drop another subtle hint...), it was so that we could do the
obvious optimization, with an even more obvious name:
>> primes: function [n [integer!]] [p c d] [
[ p: copy []
[ c: next iota n
[ while [all [0 < length? c (square d: first c) <= last c]] [
[ append p d
[ c: map c nondiv d
[ ]
[ append p c
[ ]
>> primes 50
== [2 3 5 7 11 13 17 19 23 29 31 37 41 43 47]
>> primes 65
== [2 3 5 7 11 13 17 19 23 29 31 37 41 43 47 53 59 61]
and
>> print primes 1000
2 3 5 7 11 13 17 19 23 29 31 37 41 43 47 53 59 61 67 71 73 79 83
89 97 101 103 107 109 113 127 131 137 139 149 151 157 163 167 173
179 181 191 193 197 199 211 223 227 229 233 239 241 251 257 263
269 271 277 281 283 293 307 311 313 317 331 337 347 349 353 359 3
67 373 379 383 389 397 401 409 419 421 431 433 439 443 449 457 46
1 463 467 479 487 491 499 503 509 521 523 541 547 557 563 569 571
577 587 593 599 601 607 613 617 619 631 641 643 647 653 659 661
673 677 683 691 701 709 719 727 733 739 743 751 757 761 769 773 7
87 797 809 811 821 823 827 829 839 853 857 859 863 877 881 883 88
7 907 911 919 929 937 941 947 953 967 971 977 983 991 997
Enjoy playing with maps!
-jn-