Mailing List Archive: 49091 messages
  • Home
  • Script library
  • AltME Archive
  • Mailing list
  • Articles Index
  • Site search
 

[REBOL] Who is that grouch? -or- Fun with functions! Re:(6)

From: joel:neely:fedex at: 5-Oct-2000 16:02

Hi, Andrew, I love peer review! Open source works! [Al--Bri--xtra--co--nz] wrote:
> > nondiv: func [d] [func [n] [either n // d = 0 [none] [n]]] > > This could be quicker as: > nondiv: func [d] [func [n] [if n // d <> 0 [n]]] > as 'if returns 'none when the condition is false. > > Also, this: > > map: function [[catch] b [block!] f [function!] /all] > is better as: > > map: function [[catch] b [block!] f [any-function!] /all] > > so you can use native! functions as well. >
I've changed my copy to reflect these suggestions. Thanks! (I *did* say it was the "latest" version, not the "last" version...)
> jn, is there a name for a generic function like: > > >> something: function [B [block!] F [any-function!]] [Arg1] [ > [ Arg1: first B > [ B: next B > [ foreach Arg2 B [ > [ Arg1: F Arg1 Arg2 > [ ] > [ Arg1 > [ ] > >> > >> something [1 2 3 4 5] :+ > == 15 >
Well, APL called it "reduce", but that name is already taken! ;-) The next most common name I can recall for that kind of thing is accumulate , but I'm too lazy to type that all the way out. I suggest one slight change: supplying the initial value of the accumulator lets it function correctly even with an empty block of values. Normally one would use a left identity appropriate for the f in use (e.g., 0 for addition, 1 for multiplication, etc.). With this change in hand, we get: accumulate: func [a [any-type!] b [block!] f [any-function!]] [ foreach c b [a: f a c] a ] which allows us to say
>> accumulate 0 iota 20 :+
== 210 or
>> accumulate 1 iota 10 :*
== 3628800 Since the accumulation function need not be symmetric, we can also say
>> accumulate "" iota 10 :append
== "12345678910" Of course, some functions don't have a left identity (theoretically or practically), so it's up to the user to choose a reasonable stand-in:
>> accumulate 9999999 iota 20 :min
== 1
>> accumulate -9999999 iota 20 :max
== 20 Incidentally, there's a whole family of such so-called higher-order functions that can be quite interesting. The next one (I can't recall if there's a common name for it) can be used for statistics and other fun things: pair-wise: function [ b1 [block!] b2 [block!] f [any-function!] ][ r ][ r: make block! min length? b1 length? b2 loop min length? b1 length? b2 [ append r f first b1 first b2 b1: next b1 b2: next b2 ] r ] ...such as...
>> my-scores: [4 7 16 2 12 13]
== [4 7 16 2 12 13]
>> your-scores: [9 5 15 1 15 15]
== [9 5 15 1 15 15]
>> winning-scores: pair-wise my-scores your-scores :max
== [9 7 16 2 15 15]
>> losing-scores: pair-wise my-scores your-scores :min
== [4 5 15 1 12 13]
>> spreads: pair-wise winning-scores losing-scores :subtract
== [5 2 1 1 3 2] Then (hold on to your Funk-and-Wagnall's) a function named after the mathematical operation known as "convolution" can be defined as convolve: func [ a [any-type!] b1 [block!] b2 [block!] fa [any-function!] fb [any-function!] ][ accumulate a pair-wise b1 b2 :fb :fa ] ...which can do tricks such as...
>> worst-winning-score: convolve 9999 my-scores your-scores :min :max
== 2
>> best-losing-score: convolve -9999 my-scores your-scores :max :min
== 15
>> season-grand-score: convolve 0 my-scores your-scores :+ :max
== 64 ...as well as the more mathematical...
>> inner-product: convolve 0 my-scores your-scores :+ :*
== 688
> And if you're Grouchy, who's Sneezy, Happy, Doc,... ? :-) >
Well, after all the interesting and useful suggestions from the list, I guess I'm Happy! (Although overlooking the quadratic time complexity of my earlier versions of iota and map made me feel Dopey!) -jn- -- ; Joel Neely [joel--neely--fedex--com] 901-263-4460 38017/HKA/9677 REBOL [] print to-string debase decompress #{ 789C0BCE0BAB4A7176CA48CAB53448740FABF474F3720BCC B6F4F574CFC888342AC949CE74B50500E1710C0C24000000}