# map in concatenative languages

## icpdesign — 2005-09-21 14:58:46

    The map function in Common Lisp is defined as follows:

    "map result-type function &rest sequences+ => result

    Applies function to successive sets of arguments in which

    one argument is obtained from each sequence. The function

    is called first on all the elements with index 0, then on

    all those with index 1, and so on. The result-type specifies

    the type of the resulting sequence.

    map returns nil if result-type is nil. Otherwise, map returns

    a sequence such that element j is the result of applying

    function to element j of each of the sequences."

    We see that map as defined in lisp is an application of a given

    function to its parameters given in a sequence of lists, and

    the result is a list of the results.

    Since all Joy combinators (operators) have exactly one input

    and one output that is the stack, we are inclined to define

    map for Joy as follows:

    [S1 S2 ... Sn] [P] map => [R1 R2 ... Rn]

    where map applies the program P to each list Si and returns a list

    [R1 R2 ... Rn] where Ri is the list result of Si P

    ex.

    [[2 3] [5 4]] [+] map => [[5] [9]]

    [[1] [5] [7]] [dup] map => [[1 1] [5 5] [7 7]]

    [[2 3 +] [5 7 *]] [i] map => [[5] [35]]

    [[1 2 3] [5]] [dup *] map => [[1 2 9] [25]]

    [[] [pop]] [i] map => [#err #err]

    I am wondering if FORTH has map, filter, reduce, ... words

    Taoufik Dachraoui

## icpdesign — 2005-09-21 15:14:27

    I am replying to myself, I wanted to add that map as defined below

    can be implemented recursively by calling Joy to run P with a stack

    initialized to Si

    Also, note that P is any valid Joy program, and this includes map

    combinator.

    In the current Joy implementation of map is there any constraints on

    the program P

    Taoufik Dachraoui

    --- In concatenative@yahoogroups.com, "icpdesign"

    <taoufik.dachraoui@w...> wrote:

     > The map function in Common Lisp is defined as follows:

    >

    > "map result-type function &rest sequences+ => result

    >

    > Applies function to successive sets of arguments in which

    > one argument is obtained from each sequence. The function

    > is called first on all the elements with index 0, then on

    > all those with index 1, and so on. The result-type specifies

    > the type of the resulting sequence.

    >

    > map returns nil if result-type is nil. Otherwise, map returns

    > a sequence such that element j is the result of applying

    > function to element j of each of the sequences."

    >

    > We see that map as defined in lisp is an application of a given

    > function to its parameters given in a sequence of lists, and

    > the result is a list of the results.

    >

    > Since all Joy combinators (operators) have exactly one input

    > and one output that is the stack, we are inclined to define

    > map for Joy as follows:

    >

    > [S1 S2 ... Sn] [P] map => [R1 R2 ... Rn]

    >

    > where map applies the program P to each list Si and returns a list

    > [R1 R2 ... Rn] where Ri is the list result of Si P

    >

    > ex.

    >

    > [[2 3] [5 4]] [+] map => [[5] [9]]

    >

    > [[1] [5] [7]] [dup] map => [[1 1] [5 5] [7 7]]

    >

    > [[2 3 +] [5 7 *]] [i] map => [[5] [35]]

    >

    > [[1 2 3] [5]] [dup *] map => [[1 2 9] [25]]

    >

    > [[] [pop]] [i] map => [#err #err]

    >

    > I am wondering if FORTH has map, filter, reduce, ... words

    >

    > Taoufik Dachraoui

## Magnus Jonsson — 2005-09-21 16:44:02

    I'm sorry but this is not what common lisp's map function does. I'll give

    corrections:

     > [[2 3] [5 4]] [+] map => [[5] [9]]

     => [[7] [7]]

     > [[1] [5] [7]] [dup] map => [[1 1] [5 5] [7 7]]

     => ??? (dup takes only one input)

    (All the other examples suffer from the same number of inputs/outputs

    problem)

    I will use mapcar below but the idea is the same as map. The only

    difference is that mapcar operates only on lists, not generic sequences.

    (mapcar fn (list (list a b c)

                      (list d e f)

                      (list g h i)))

    means

    (list (funcall fn a d g)

           (funcall fn b e h)

           (funcall fn c f i))

    I think you have misunderstood it to mean:

    (list (funcall fn a b c)

           (funcall fn d e f)

           (funcall fn g h i))

    So in some sense the difference is only a transposition.

    -Magnus Jonsson

## icpdesign — 2005-09-21 19:23:41

    As you said, the map in lisp applies the function to its parameters and the parameters

    happen to be distributed in a sequence of lists where each list has 1 parameter for the

    function.

    But, in Joy (or concatenative languages) the only parameter is the stack and the only

    result is the stack, for this reason what I written in my message is correct:

     [[2 3] [5 4]] [+] map => [[5] [9]]

    the map applies + to its 1st stack (list) parameter [2 3] and then to its second list

    parameter [5 4] . The result of the first applications is the list (or stack) [5] and the result

    of the second application is [9]

    Taoufik Dachraoui

     --- In concatenative@yahoogroups.com, Magnus Jonsson <magnus@s...> wrote:

    > I'm sorry but this is not what common lisp's map function does. I'll give

    > corrections:

    >

    > > [[2 3] [5 4]] [+] map => [[5] [9]]

    >

    > => [[7] [7]]

    >

    > > [[1] [5] [7]] [dup] map => [[1 1] [5 5] [7 7]]

    >

    > => ??? (dup takes only one input)

    >

    > (All the other examples suffer from the same number of inputs/outputs

    > problem)

    >

    > I will use mapcar below but the idea is the same as map. The only

    > difference is that mapcar operates only on lists, not generic sequences.

    >

    > (mapcar fn (list (list a b c)

    >                   (list d e f)

    >                   (list g h i)))

    >

    > means

    >

    > (list (funcall fn a d g)

    >        (funcall fn b e h)

    >        (funcall fn c f i))

    >

    >

    > I think you have misunderstood it to mean:

    >

    > (list (funcall fn a b c)

    >        (funcall fn d e f)

    >        (funcall fn g h i))

    >

    > So in some sense the difference is only a transposition.

    >

    > -Magnus Jonsson

## icpdesign — 2005-09-21 19:34:38

    Just to precise something, see below.

     --- In concatenative@yahoogroups.com, "icpdesign" <taoufik.dachraoui@w...> wrote:

    >

    > As you said, the map in lisp applies the function to its parameters and the parameters

    > happen to be distributed in a sequence of lists where each list has 1 parameter for the

    > function.

    >

    > But, in Joy (or concatenative languages) the only parameter is the stack and the only

    > result is the stack, for this reason what I written in my message is correct:

    >

    the map as i defined in my previous message is not how is defined in Joy

    currently. I am just proposing a new definition for map that goes with the

    spirit of concatenative language. I find the map as defined by Joy is a mimic

    of how map is defined in functional languages.

    >  [[2 3] [5 4]] [+] map => [[5] [9]]

    in the previous map command, we have the function + and 2 parameters

    (lists/stacks): 1st is [2 3] and the 2nd is [5 4]

    >

    > the map applies + to its 1st stack (list) parameter [2 3] and then to its second list

    > parameter [5 4] . The result of the first applications is the list (or stack) [5] and the

    result

    > of the second application is [9]

    >

    > Taoufik Dachraoui

    >

    >

    > --- In concatenative@yahoogroups.com, Magnus Jonsson <magnus@s...> wrote:

    > > I'm sorry but this is not what common lisp's map function does. I'll give

    > > corrections:

    > >

    > > > [[2 3] [5 4]] [+] map => [[5] [9]]

    > >

    > > => [[7] [7]]

    > >

    > > > [[1] [5] [7]] [dup] map => [[1 1] [5 5] [7 7]]

    > >

    > > => ??? (dup takes only one input)

    > >

    > > (All the other examples suffer from the same number of inputs/outputs

    > > problem)

    > >

    > > I will use mapcar below but the idea is the same as map. The only

    > > difference is that mapcar operates only on lists, not generic sequences.

    > >

    > > (mapcar fn (list (list a b c)

    > >                   (list d e f)

    > >                   (list g h i)))

    > >

    > > means

    > >

    > > (list (funcall fn a d g)

    > >        (funcall fn b e h)

    > >        (funcall fn c f i))

    > >

    > >

    > > I think you have misunderstood it to mean:

    > >

    > > (list (funcall fn a b c)

    > >        (funcall fn d e f)

    > >        (funcall fn g h i))

    > >

    > > So in some sense the difference is only a transposition.

    > >

    > > -Magnus Jonsson

## Magnus Jonsson — 2005-09-21 20:18:20

    Oh, I see. Sorry for the misundertanding. I've been thinking a bit and I

    think I know where the confusion stems from.

    I don't know if there's a word to make a distinction between the view of

    functions taking a stack and producing a stack, and the view of a function

    taking N values and producing M values (which happen to be received

    from and returned on a stack). If you see functions in the first sense, as

    Stack->Stack, then your suggestion makes perfect sense. I usually think in

    the other way when I program in concatenative languages though,

    Arg1...ArgM -> Ret1...RetM functions. Hence my confusion.

    Is there a way to easily distinguish between these two perspectives in

    written text?

    - Magnus

     On Wed, 21 Sep 2005, icpdesign wrote:

    >

    > As you said, the map in lisp applies the function to its parameters and the parameters

    > happen to be distributed in a sequence of lists where each list has 1 parameter for the

    > function.

## William Tanksley, Jr — 2005-09-22 04:51:48

    icpdesign <taoufik.dachraoui@...> wrote:

     > Since all Joy combinators (operators) have exactly one input

    > and one output that is the stack, we are inclined to define

    > map for Joy as follows:

    > [S1 S2 ... Sn] [P] map => [R1 R2 ... Rn]

     Nice! Ideally, there should be something else, perhaps a version of

    map that implicitly prepends a list in front of each Si, so that

    current Joy programmers could use this new map definition in their old

    programs.

    For example, if the current version of map was used like this:

    3 [1 2] [+] map => [4 5]

    The new version could look like this:

    [3]   [[1] [2]] newmap => [[4] [5]]

    For simplicity, the inner lists could possibly be left out:

    [3] [1 2] newmap => [4 5]

     > where map applies the program P to each list Si and returns a list

    > [R1 R2 ... Rn] where Ri is the list result of Si P

     I like it a lot.

     > I am wondering if FORTH has map, filter, reduce, ... words

     No -- Forth has no built-in list datatype.

     > Taoufik Dachraoui

     -Billy

## icpdesign — 2005-09-22 11:16:14

    --- In concatenative@yahoogroups.com, "William Tanksley, Jr"

    <wtanksleyjr@g...> wrote:

     > icpdesign <taoufik.dachraoui@w...> wrote:

    > > Since all Joy combinators (operators) have exactly one input

    > > and one output that is the stack, we are inclined to define

    > > map for Joy as follows:

    > > [S1 S2 ... Sn] [P] map => [R1 R2 ... Rn]

    >

    > Nice! Ideally, there should be something else, perhaps a version of

    > map that implicitly prepends a list in front of each Si, so that

    > current Joy programmers could use this new map definition in their

     old

     > programs.

     it is a good idea to generalize the newmap so that current

    Joy programs continue to work correctly. But it is also

    necessary to may be

    difficult because current Joy programs using map assume

    Lets use the following generalizations to newmap

    1. if Si is not a list the compiler/interpreter

       replaces Si by [Si]

    2. when P is applied on Si and Si is missing a value

       then this value is borrowed from the current stack

       (non-destructively, so the current stack is unchanged)

       Note: in this case P fails only if it cannot borrow a

       value from the current stack (stack is empty)

    Example:

    7 8 [1 2 [3 4]] + newmap

    => 7 8 [[8 1] [8 2] [3 4]] + newmap

    => 7 8 [[9] [10] [7]]

    BUT how can we generalize the result so that the current Joy

    program works correctly? this may be tricky, for this reason

    I propose, to leave unchanged the current map, and add nmap

    to Joy library. I find the new map definition looks more

    natural and less trickier then current definition

    QUESTION: How can we define nmap as defined in my previous

    message using Joy? nmap == ....?

     >

    > For example, if the current version of map was used like this:

    >

    > 3 [1 2] [+] map => [4 5]

    >

    > The new version could look like this:

    >

    > [3]   [[1] [2]] newmap => [[4] [5]]

    >

    > For simplicity, the inner lists could possibly be left out:

    >

    > [3] [1 2] newmap => [4 5]

    >

    > > where map applies the program P to each list Si and returns a

     list

     > > [R1 R2 ... Rn] where Ri is the list result of Si P

    >

    > I like it a lot.

    >

    > > I am wondering if FORTH has map, filter, reduce, ... words

    >

    > No -- Forth has no built-in list datatype.

    >

    > > Taoufik Dachraoui

    >

    > -Billy

     Taoufik Dachraoui