From: Jonathan Siegel
Subject: Passing multiple parameters through mapcar?
Date: 
Message-ID: <ju05OdmqlUDU2tGthpsZxOM24729@4ax.com>
Hi,

I want to call a function with 1 constant parameter, one index
parameter and a parameter that will iterate through a list of
elements. I have thought of doing this with mapcar, but I have to go
through some work to prep the arguments for this call and it seems
like there would be an easier answer. I have recently started
programming LISP from more traditional languages and have come to the
understanding that it is usually better to avoid iterative loops, but
I feel that a loop might be better in this circumstance. Does anyone
have any thoughts on how this can be done without a loop or without
the massaging of parameters to mapcar?

pseudo-code:

(setf counters '(1 2 3))
(setf a-const   4.5)
(setf a-list        '("apples" "oranges" "bananas"))

(mapcar a-three-argument-function
	counters
	(make-list 3 :initial-element a-const)
	a-list)

;; This is ugly, isn't it?


Thanks,
Jonathan
···@scorekeep.com

From: Christopher C Stacy
Subject: Re: Passing multiple parameters through mapcar?
Date: 
Message-ID: <x8lbt1hx5dr.fsf@world.std.com>
>>>>> On Sun, 04 Jun 2000 05:55:50 GMT, Jonathan Siegel ("Jonathan") writes:
 Jonathan> (setf counters '(1 2 3))
 Jonathan> (setf a-const   4.5)
 Jonathan> (setf a-list        '("apples" "oranges" "bananas"))
 Jonathan> (mapcar a-three-argument-function
 Jonathan> 	counters
 Jonathan> 	(make-list 3 :initial-element a-const)
 Jonathan> 	a-list)


Hi,

If you want do use a functional style, you could encapsulate the
constant in an anonymous function:

(mapcar #'(lambda (x z) (a-three-argument-function x a-const z))
		counters a-list)

I wouldn't name that variable A-LIST, though, because that might lead
someone to assume that it was an association-list.
	

However, there's absolutely nothing wrong with using iteration!

If that first parameter is really an index that just goes up,
I think the most understandable code would be:

(loop for idx upfrom 0
      for fruit in '(apples oranges bannanas )
      doing (a-three-argument-function idx a-const fruit))


If the index is just another random parameter:

(loop for idx in counters
      for fruit in '(apples oranges bannanas )
      doing (a-three-argument-function idx a-const fruit))

cheers,
Chris
From: Tim Bradshaw
Subject: Re: Passing multiple parameters through mapcar?
Date: 
Message-ID: <ey3d7lxojv7.fsf@cley.com>
* Jonathan Siegel wrote:

> (setf counters '(1 2 3))
> (setf a-const   4.5)
> (setf a-list        '("apples" "oranges" "bananas"))

> (mapcar a-three-argument-function
> 	counters
> 	(make-list 3 :initial-element a-const)
> 	a-list)

You'd probably be better off with something like

    (mapx #'(lambda (a b)
	      (fn a const b))
	  l1 l2)

where mapx is mapcar or mapc depending on whether you want the results
or not.

--tim
From: Joe Marshall
Subject: Re: Passing multiple parameters through mapcar?
Date: 
Message-ID: <ya4la8d5.fsf@alum.mit.edu>
Jonathan Siegel <···@scorekeep.com> writes:

> I have recently started programming LISP from more traditional
> languages and have come to the understanding that it is usually
> better to avoid iterative loops...

There's nothing wrong with iterative loops in lisp.  You don't have to
avoid them.  (Just out of curiosity, why did you come to this
conclusion?)

Since a few people have already posted a MAPCAR and LOOP version of
your iteration, allow me to post a DO version and a LABELS version
(making the assumption that idx is a counter).

{do ((idx 1 (1+ idx))
     (const 4.5)
     (list '("apples" "oranges" "bananas") (cdr list))
     (result nil (cons (a-three-argument-function idx const (car list)) result)))
    ((endp list) (reverse result)))

(let ((const 4.5))
  (labels ((luup (idx list result)
             (if (endp list)
                 (reverse result)
                 (luup (1+ idx) 
                       (cdr list)
                       (cons (a-three-argument-function idx const (car list)) result)))))
    (luup 1 '("apples" "oranges" "bananas") nil)))

You could NREVERSE the list instead of REVERSEing it if you wanted to.

The differences in these versions are a matter of taste.
From: Christopher Browne
Subject: Re: Passing multiple parameters through mapcar?
Date: 
Message-ID: <slrn8jl3l0.3j8.cbbrowne@knuth.brownes.org>
Centuries ago, Nostradamus foresaw a time when Joe Marshall would say:
>Jonathan Siegel <···@scorekeep.com> writes:
>
>> I have recently started programming LISP from more traditional
>> languages and have come to the understanding that it is usually
>> better to avoid iterative loops...
>
>There's nothing wrong with iterative loops in lisp.  You don't have to
>avoid them.  (Just out of curiosity, why did you come to this
>conclusion?)

Most likely, it comes as a result of Lisp being treated in a course
as a pedagogical tool on recursion ands lists, where the point of the
exercise was to teach recursion.

When that is the goal, it is quite legitimate to "lose marks" for using
iterative mechanisms, thus rejecting the pedagogical goal.

Unfortunately, this too-brief Lisp presentation never gets around to
having any other goals, and thus all is left is the impression that
"iteration is bad."
-- 
········@acm.org - <http://www.ntlug.org/~cbbrowne/>
"Sponges grow in  the ocean. I wonder how much  deeper the ocean would
be if that didn't happen." -- Steven Wright
From: Jonathan Siegel
Subject: Re: Passing multiple parameters through mapcar?
Date: 
Message-ID: <IZY6ObpQgzy5APpCvJg4T08fI9zT@4ax.com>
Joe,

Thank you for your suggestion on how to implement this. In regards to
your question, basically Christopher pegged the reason. That is, in
learning LISP it seemed that a lot of power was gained in recursion
and it makes a novice wary of "missing" the recursive solution to a
problem.

Thanks again,
Jonathan
···@scorekeep.com


On 04 Jun 2000 09:22:46 -0400, Joe Marshall <·········@alum.mit.edu>
wrote:

>Jonathan Siegel <···@scorekeep.com> writes:
>
>> I have recently started programming LISP from more traditional
>> languages and have come to the understanding that it is usually
>> better to avoid iterative loops...
>
>There's nothing wrong with iterative loops in lisp.  You don't have to
>avoid them.  (Just out of curiosity, why did you come to this
>conclusion?)
From: Thom Goodsell
Subject: Re: Passing multiple parameters through mapcar?
Date: 
Message-ID: <393BAC64.F7B31316@cra.com>
That's one of the (many) things I love about Lisp: powerful recursion
AND powerful iteration let you choose the solution which best fits the
problem.

Thom


Jonathan Siegel wrote:
> 
> Joe,
> 
> Thank you for your suggestion on how to implement this. In regards to
> your question, basically Christopher pegged the reason. That is, in
> learning LISP it seemed that a lot of power was gained in recursion
> and it makes a novice wary of "missing" the recursive solution to a
> problem.
> 
> Thanks again,
> Jonathan
> ···@scorekeep.com
> 
> On 04 Jun 2000 09:22:46 -0400, Joe Marshall <·········@alum.mit.edu>
> wrote:
> 
> >Jonathan Siegel <···@scorekeep.com> writes:
> >
> >> I have recently started programming LISP from more traditional
> >> languages and have come to the understanding that it is usually
> >> better to avoid iterative loops...
> >
> >There's nothing wrong with iterative loops in lisp.  You don't have to
> >avoid them.  (Just out of curiosity, why did you come to this
> >conclusion?)
From: Thomas A. Russ
Subject: Re: Passing multiple parameters through mapcar?
Date: 
Message-ID: <ymi3dmsgm8z.fsf@sevak.isi.edu>
Jonathan Siegel <···@scorekeep.com> writes:

> I want to call a function with 1 constant parameter, one index
> parameter and a parameter that will iterate through a list of
> elements.

> pseudo-code:
> 
> (setf counters '(1 2 3))
> (setf a-const   4.5)
> (setf a-list        '("apples" "oranges" "bananas"))
> 
> (mapcar a-three-argument-function
> 	counters
> 	(make-list 3 :initial-element a-const)
> 	a-list)

I will assume from your description that you really only want to have a
single parameter "a-list" that you need to supply directly.  I would
suggest something along these lines, then:

(defun map-special (a-3-argument-function a-const a-list)
  (let ((count 0))
    (mapcar #'(lambda (list-element)
                 (funcall a-3-argument-function
                          (incf count)
                          a-const
                          list-element))
            a-list)))

If you do a lot of mapping operations, you will find that using lambda
expressions to construct anonymous functions, and exploiting the lexical
binding properties of lisp will be useful.  This function introduces a
local variable that is incremented as the counter.  [Although I wonder
why you need the counter -- there may be a different way of doing things
inside the function so that the counter isn't necessary.]

I second the comments about iteration not being evil.

-- 
Thomas A. Russ,  USC/Information Sciences Institute          ···@isi.edu