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