Hi, Chris,

Actually, it depends on which Lisp...

According to the LISP 1.5 Programmer's Manual, page 60,

    Table Building and Table Reference Functions

    pair[x;y]          :     SUBR

        The function pair has as value the list of pairs of
    corresponding elements of the lists x and y.  The arguments
    x and y must be lists of the same number of elements. ...

Of course, that manual has serious grey hair!  The preface is dated
17 Aug 1962 (although my copy is from the 6th printing, April 1972).

Actually, if I were going to go by that ancient manual, I'd have to
call the apply-function-across-list operator  maplist , because the
name  map  was given to a side-effects-only version that always
returned  nil .

(OK, I couldn't help but throw in a little archaeology ;-)


Actually, I had a more pragmatic reason for ducking the multiple-
lists-as-arguments issue -- REBOL syntax!

[EMAIL PROTECTED] wrote:
> 
>      In Lisp this function is still MAP. MAP takes any number of
>      sequences and the function takes a number of arguments equal
>      to the number of sequences:
> 
>      (map 'vector #'max '(4 7 16) '(9 5 15))
>      => '(9 7 16)
> 
>      Perhaps the REBOL map implementation could do the same.
> 

As Lisp explicitly delimits each function application, it's easy to
tell how many lists are being supplied as arguments to  map  (as in
your example).  The only reliable way I know in REBOL to pass a
varying number of arguments is to put them in a block...

    map  [ [...] [...] [...] ] some-function

...but I was hesitant to do that for a few reasons.

First of all, I'd like to be able to do things like these:

    >> accum: func [a [any-type!] b [any-block!] f [any-function!]][
    [    foreach c b [a: f a c]
    [    a
    [    ]
    >> map [[1 2 1] [2 3 3] [3 6 5]] func [b [block!]] [
    [    append b (accum 0 b :+) / (length? b)
    [    ]
    == [[1 2 1 1.33333333333333] [2 3 3 2.66666666666667] [3 6 5
    4.66666666666667]]

...or...

    >> namer: make object! [
    [    curr: #"a"
    [    next: func [/local r] [
    [        r: curr  curr: curr + 1  r
    [        ]
    [    ]
    >> map [[1 2 1] [2 3 3] [3 6 5]] func [b [block!]] [
    [    head insert head copy b to-string namer/next
    [    ]
    == [["a" 1 2 1] ["b" 2 3 3] ["c" 3 6 5]]

where the function is to be applied to each block that is an
element of the (single!) argument block.

Second, I'd thought about (although I didn't include it in my
earlier posts) adding a  /deep  refinement by analogy with a
similar one for  copy  (etc.) that would recur(se) on any
nested blocks.

Finally, I'd considered handling the structure-traversing issues
separately from the data-manipulation issues, by defining (this
version is VERY quick and dirty):

    >> transpose: function [b [block!]] [w i s r] [
    [    r: make block! w: accum length? b/1 map b :length? :min
    [    repeat i w [
    [        s: make block! length? b
    [        foreach c b [append/only s c/:i]
    [        append/only r s
    [        ]
    [    r
    [    ]
    >> transpose [[1 2 3 4 5] ["a" "b" "c" "d" "e"]]
    == [[1 "a"] [2 "b"] [3 "c"] [4 "d"] [5 "e"]]
    >> transpose [[1 2 3] [14 15 16] [27 28 29]]
    == [[1 14 27] [2 15 28] [3 16 29]]

    >> 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]
    >> games: transpose reduce [my-scores your-scores]
    == [[4 9] [7 5] [16 15] [2 1] [12 15] [13 15]]

...and so forth.

Critiques/comments/debugging welcome!

-jn-

Reply via email to