From: AR
Subject: Stumped (basic LISP question)
Date: 
Message-ID: <ac99go$lc5$1@woodrow.ucdavis.edu>
Hi

I need to write a function that takes in a list and a function, tests the
function over each of the members of the list and returns two lists : one
list is of the members where the function evaluates to true and the other is
where the function evaluates to false.

Example:

(split #' (lambda (x) (> x 4)) '( 1 2 3 4 5 6 7 8 9 10) )

gives ( (1 2 3 4) (5 6 7 8 9 10) )


So, I got the part where you return the list of elements for which the list
evaluates to be true:

(defun split ( pred l)
  (cond
    ((null l) '())

     ((funcall pred (car l))
      (cons (car l) (split pred (cdr l))))
          (t
      ( split pred(cdr l)))))

So for the sample output, I get (5 6 7 8 9 10 ).

How do I get the list for the elements that don't evaluate to true?

Thanks for any help.

From: Matthew X. Economou
Subject: Re: Stumped (basic LISP question)
Date: 
Message-ID: <w4oit5jfqq3.fsf@eco-fs1.irtnog.org>
>>>>> "AR" == AR  <········@yahoo.com> writes:

    AR> Hi I need to write a function that takes in a list and a
    AR> function, tests the function over each of the members of the
    AR> list and returns two lists : one list is of the members where
    AR> the function evaluates to true and the other is where the
    AR> function evaluates to false.

Your function, reformatted slightly for readability:

(DEFUN SPLIT (PRED L)
  (COND
    ((NULL L)
     '())
    ((FUNCALL PRED (CAR L))
     (CONS (CAR L) (SPLIT PRED (CDR L))))
    (T
     (SPLIT PRED (CDR L)))))

    AR> How do I get the list for the elements that don't evaluate to
    AR> true?

It is pretty obvious how you'd construct the second list.  But the key
question to ask yourself is, how do I store both lists at the same
time and still avoid side effects?

Let me give you a hint.  Let's say my professor wants me to write a
factorial function in continuation passing style, but his homework
software knows nothing of continuations and will call your FACTORIAL
function as (FACTORIAL N), not as (FACTORIAL N #'(LAMBDA (X) X)).

If course, I write two functions:

;;; User interface
(DEFUN FACTORIAL (N)
  (FACTORIAL-HELPER N #'(LAMBDA (X) X)))

;;; Actual factorial implementation
(DEFUN FACTORIAL-HELPER (N K)
  (IF (= N 0)
      (K 0)
    (FACTORIAL-HELPER (- N 1)
                      #'(LAMBDA (V)
                          (K (* N V))))))

If my hint of "write a second function" isn't enough of a hint, post a
response with your questions here in this newsgroup and I'll try to
make myself more clear.

-- 
Matthew X. Economou <···············@irtnog.org> - Unsafe at any clock speed!
I'm proud of my Northern Tibetian heritage! (http://www.subgenius.com)
From: Robert Maas
Subject: Re: Stumped (basic LISP question)
Date: 
Message-ID: <ef5aa6c5.0205221101.7ba2423a@posting.google.com>
"Matthew X. Economou" <···············@irtnog.org> wrote in message news:<···············@eco-fs1.irtnog.org>...
> Let me give you a hint.  Let's say my professor wants me to write a
> factorial function in continuation passing style, but his homework
> software knows nothing of continuations and will call your FACTORIAL
> function as (FACTORIAL N), not as (FACTORIAL N #'(LAMBDA (X) X)).

Side remark: To compute factorials, I prefer divide and conquer
rather than iteration. I.e. write a helper function that does
M * M+1 * ... * N-1 * N  ==  (M * ... * MID) * (MID+1 * ... * N)
From: Barry Margolin
Subject: Re: Stumped (basic LISP question)
Date: 
Message-ID: <g4UG8.15$zE.38@paloalto-snr1.gtei.net>
In article <····························@posting.google.com>,
Robert Maas <···@netmagic.net> wrote:
>Side remark: To compute factorials, I prefer divide and conquer
>rather than iteration. I.e. write a helper function that does
>M * M+1 * ... * N-1 * N  ==  (M * ... * MID) * (MID+1 * ... * N)

Any particular reason?  You still do the same number of multiplications.
In your method, the last few multiplications will be bignum*bignum, while
the traditional algorithm is mostly bignum*fixnum (unless you're computing
the factorial of a bignum, which probably won't fit in the memory space of
most systems).  I don't know offhand if there's much performance
difference, but if there is my intuition is that it would be in favor of
bignum*fixnum.

-- 
Barry Margolin, ······@genuity.net
Genuity, Woburn, MA
*** DON'T SEND TECHNICAL QUESTIONS DIRECTLY TO ME, post them to newsgroups.
Please DON'T copy followups to me -- I'll assume it wasn't posted to the group.
From: Raymond Toy
Subject: Re: Stumped (basic LISP question)
Date: 
Message-ID: <4ng00jeu8b.fsf@rtp.ericsson.se>
>>>>> "Barry" == Barry Margolin <······@genuity.net> writes:

    Barry> In article <····························@posting.google.com>,
    Barry> Robert Maas <···@netmagic.net> wrote:
    >> Side remark: To compute factorials, I prefer divide and conquer
    >> rather than iteration. I.e. write a helper function that does
    >> M * M+1 * ... * N-1 * N  ==  (M * ... * MID) * (MID+1 * ... * N)

    Barry> Any particular reason?  You still do the same number of multiplications.
    Barry> In your method, the last few multiplications will be bignum*bignum, while
    Barry> the traditional algorithm is mostly bignum*fixnum (unless you're computing
    Barry> the factorial of a bignum, which probably won't fit in the memory space of
    Barry> most systems).  I don't know offhand if there's much performance
    Barry> difference, but if there is my intuition is that it would be in favor of
    Barry> bignum*fixnum.

Actually there is a very big difference if you implement some of the
fast bignum multiplication operations.  This is a very big win if both
the numbers are about the same size.  When they're vastly different,
the old pencil-and-paper way is about as fast as you can go.

Ray
From: Kaz Kylheku
Subject: Re: Stumped (basic LISP question)
Date: 
Message-ID: <slrnaeoa63.u70.kaz@localhost.localdomain>
On 22 May 2002 12:01:45 -0700, Robert Maas <···@netmagic.net> wrote:
>"Matthew X. Economou" <···············@irtnog.org> wrote in message news:<···············@eco-fs1.irtnog.org>...
>> Let me give you a hint.  Let's say my professor wants me to write a
>> factorial function in continuation passing style, but his homework
>> software knows nothing of continuations and will call your FACTORIAL
>> function as (FACTORIAL N), not as (FACTORIAL N #'(LAMBDA (X) X)).
>
>Side remark: To compute factorials, I prefer divide and conquer
>rather than iteration. I.e. write a helper function that does
>M * M+1 * ... * N-1 * N  ==  (M * ... * MID) * (MID+1 * ... * N)

That's just too efficient, and utterly devoid of academic merit. No, what you
must do is construct an object that behaves like a virtual sequence of
consecutive integers, whose elements materialize at the last possible moment
prior to their access and then vaporize afterward. Apply the * function to
this sequence with a reduce-like function that accepts such sequences.
From: Frank A. Adrian
Subject: Re: Stumped (basic LISP question)
Date: 
Message-ID: <WV0G8.404$gA5.119749@news.uswest.net>
AR wrote:

> Hi
> 
> I need to write a function that takes in a list and a function, tests the
> function over each of the members of the list and returns two lists : one
> list is of the members where the function evaluates to true and the other
> is where the function evaluates to false.

The simplest form of the function might be one based on the built-in 
function "remove-if" and an appropriate use of the built-in function 
"complement".  See the CLHS for information on both.

faa

P.S.  This solution probably will not be the speediest, but probably does 
not have to be for your purposes.  It will probably be the quickest to 
write and debug.

P.P.S.  I assume to return two lists, you are also using the function 
"values".  if not, you might want to look into this handy function, as well.
From: AR
Subject: Re: Stumped (basic LISP question)
Date: 
Message-ID: <acb6q8$og4$1@woodrow.ucdavis.edu>
remove-f works great :-)

Well, look at the debate I inspired ;-)

Thanks for your time.


"Frank A. Adrian" <·······@ancar.org> wrote in message
·························@news.uswest.net...
> AR wrote:
>
> > Hi
> >
> > I need to write a function that takes in a list and a function, tests
the
> > function over each of the members of the list and returns two lists :
one
> > list is of the members where the function evaluates to true and the
other
> > is where the function evaluates to false.
>
> The simplest form of the function might be one based on the built-in
> function "remove-if" and an appropriate use of the built-in function
> "complement".  See the CLHS for information on both.
>
> faa
>
> P.S.  This solution probably will not be the speediest, but probably does
> not have to be for your purposes.  It will probably be the quickest to
> write and debug.
>
> P.P.S.  I assume to return two lists, you are also using the function
> "values".  if not, you might want to look into this handy function, as
well.
From: Pierre R. Mai
Subject: Re: Stumped (basic LISP question)
Date: 
Message-ID: <87k7pyesny.fsf@orion.bln.pmsf.de>
"Frank A. Adrian" <·······@ancar.org> writes:

> AR wrote:
> 
> > Hi
> > 
> > I need to write a function that takes in a list and a function, tests the
> > function over each of the members of the list and returns two lists : one
> > list is of the members where the function evaluates to true and the other
> > is where the function evaluates to false.
> 
> The simplest form of the function might be one based on the built-in 
> function "remove-if" and an appropriate use of the built-in function 
> "complement".  See the CLHS for information on both.

Another very simple way, which should also be of "optimal" performance
(i.e. O(n)), is to use LOOP:

(defun foo (list predicate)
  (loop for item in list
        if (funcall predicate item) collect item into successes
        else collect item into failures
        finally (return (values successes failures))))

And when using the two-pass remove-if solution, it might also be
appropriate to use remove-if-not for one of them, instead of remove-if
and complement.

Regs, Pierre.

-- 
Pierre R. Mai <····@acm.org>                    http://www.pmsf.de/pmai/
 The most likely way for the world to be destroyed, most experts agree,
 is by accident. That's where we come in; we're computer professionals.
 We cause accidents.                           -- Nathaniel Borenstein
From: Coby Beck
Subject: Re: Stumped (basic LISP question)
Date: 
Message-ID: <TLXF8.14742$Ka.939767@news2.calgary.shaw.ca>
"AR" <········@yahoo.com> wrote in message
·················@woodrow.ucdavis.edu...
> Hi
>
> I need to write a function that takes in a list and a function, tests the
> function over each of the members of the list and returns two lists : one
> list is of the members where the function evaluates to true and the other
is
> where the function evaluates to false.
>
> Example:
>
> (split #' (lambda (x) (> x 4)) '( 1 2 3 4 5 6 7 8 9 10) )
>
> gives ( (1 2 3 4) (5 6 7 8 9 10) )
>
>
> So, I got the part where you return the list of elements for which the
list
> evaluates to be true:
>
> (defun split ( pred l)
>   (cond
>     ((null l) '())
>
>      ((funcall pred (car l))
>       (cons (car l) (split pred (cdr l))))
>           (t
>       ( split pred(cdr l)))))
>
> So for the sample output, I get (5 6 7 8 9 10 ).
>
> How do I get the list for the elements that don't evaluate to true?

(not (funcall pred (car l)))

But I think this is unnecessarily complicated.  Why don't you DOLIST or LOOP
over the list and gather up your two return lists?  Recursion will be hard
to untangle visually and is not really a very intuitive aproach.  What you
want to do in words is go element by element through the list and put them
in basket A if they satisfy your predicate and basket B if they don't.  So
write the code that way.

(let ((yeps ()) (nopes ()))
    go item by item,
       if (funcall pred item)
         put it in yups
        else put it in nopes
   return (list yeps nopes))

(I answered assuming it is homework...?)
--
Coby Beck
(remove #\Space "coby 101 @ bigpond . com")
From: Joe Marshall
Subject: Re: Stumped (basic LISP question)
Date: 
Message-ID: <1o8G8.9069$Bn5.4116143@typhoon.ne.ipsvc.net>
"Software Scavenger" <··········@mailandnews.com> wrote in message
·································@posting.google.com...
> "Coby Beck" <·····@mercury.bc.ca> wrote in message news:<·····················@news2.calgary.shaw.ca>...
>
> > (let ((yeps ()) (nopes ()))
>
> vs
>
> (let (yeps nopes)
>
> Is an even more basic Lisp question.  When I see
> the longer style, it's like hearing an off-key
> musical note.  I know it's a perfectly valid style
> and there is some good reasoning behind it, but I
> just find it garish and happen to be in the mood
> to express such an opinion, even though I would
> normally ignore such an unimportant issue.

Well then, this is perfect fodder for a flame war!

I make this distinction:
(let ((yeps ())
      (nopes ()) ...

Means that yeps and nops start out as lists that happen
to be empty and that it is likely that they will remain
lists.  I wouldn't be surprised if the yeps and nops were
used before being assigned.

(let (yeps nops) ...

Means that yeps and nops are being bound so that their
names are visible in the body, but that they have yet to
be assigned.  I would not expect them to be of any particular
type and I would not expect them to be used before being
assigned.

Of course this is just my opinion.

(Wait, not enough vitriol.  Anyone who disagrees with me
is, of course, wrong.)
From: Stefan Schmiedl
Subject: Re: Stumped (basic LISP question)
Date: 
Message-ID: <acbbsg$o4kdh$2@ID-57631.news.dfncis.de>
On Mon, 20 May 2002 15:13:01 GMT,
Joe Marshall <·············@attbi.com> wrote:
> 
> Well then, this is perfect fodder for a flame war!

May I have a go? 

> 
> I make this distinction:
> (let ((yeps ())
>       (nopes ()) ...
> 
> Means that yeps and nops start out as lists that happen
> to be empty and that it is likely that they will remain
> lists.  I wouldn't be surprised if the yeps and nops were
> used before being assigned.

How can they be used before they are assigned when you
have already assigned them to be empty lists?

> 
> (Wait, not enough vitriol.  Anyone who disagrees with me
> is, of course, wrong.)
> 

You must be stark raving mad :-)

s.
From: Barry Margolin
Subject: Re: Stumped (basic LISP question)
Date: 
Message-ID: <nHaG8.4$kr3.531@paloalto-snr2.gtei.net>
In article <··············@ID-57631.news.dfncis.de>,
Stefan Schmiedl  <·@xss.de> wrote:
>On Mon, 20 May 2002 15:13:01 GMT,
>Joe Marshall <·············@attbi.com> wrote:
>> 
>> Well then, this is perfect fodder for a flame war!
>
>May I have a go? 
>
>> 
>> I make this distinction:
>> (let ((yeps ())
>>       (nopes ()) ...
>> 
>> Means that yeps and nops start out as lists that happen
>> to be empty and that it is likely that they will remain
>> lists.  I wouldn't be surprised if the yeps and nops were
>> used before being assigned.
>
>How can they be used before they are assigned when you
>have already assigned them to be empty lists?

He's implicitly distinguishing explicit assignment (what SETQ does) from
initialization.

Although (let (yeps nops) ...) is required to initialize the variables to
NIL, it's common to use this style only when the initial values aren't
important, and use (let ((yeps '()) (nopes '())) ...) when the initial
values are significant.  It makes no different to the implementation, but
it serves as a tiny clue of intent to human readers.

It's a stylistic convention much in the same vein as the *name* naming
convention for special variables.

-- 
Barry Margolin, ······@genuity.net
Genuity, Woburn, MA
*** DON'T SEND TECHNICAL QUESTIONS DIRECTLY TO ME, post them to newsgroups.
Please DON'T copy followups to me -- I'll assume it wasn't posted to the group.
From: Joe Marshall
Subject: Re: Stumped (basic LISP question)
Date: 
Message-ID: <xKfG8.9437$Bn5.4263670@typhoon.ne.ipsvc.net>
"Stefan Schmiedl" <·@xss.de> wrote in message ···················@ID-57631.news.dfncis.de...
> On Mon, 20 May 2002 15:13:01 GMT,
> Joe Marshall <·············@attbi.com> wrote:
> >
> > Well then, this is perfect fodder for a flame war!
>
> May I have a go?
>
> >
> > I make this distinction:
> > (let ((yeps ())
> >       (nopes ()) ...
> >
> > Means that yeps and nops start out as lists that happen
> > to be empty and that it is likely that they will remain
> > lists.  I wouldn't be surprised if the yeps and nops were
> > used before being assigned.
>
> How can they be used before they are assigned when you
> have already assigned them to be empty lists?

I meant that I wouldn't be surprised to see the variable
used prior to any call to SETQ on these variables (if there *are*
any SETQ calls).

In this:
(let (yeps nopes) ...)

I would expect to see SETQ on these variables before any use
of them.

>
> >
> > (Wait, not enough vitriol.  Anyone who disagrees with me
> > is, of course, wrong.)
> >
>
> You must be stark raving mad :-)

Tell me something I *don't* know.
From: Coby Beck
Subject: Re: Stumped (basic LISP question)
Date: 
Message-ID: <I3bG8.108722$xS2.8462840@news1.calgary.shaw.ca>
"Brian Spilsbury" <·····@designix.com.au> wrote in message
·································@posting.google.com...
> "Coby Beck" <·····@mercury.bc.ca> wrote in message
news:<·····················@news2.calgary.shaw.ca>...
> > "AR" <········@yahoo.com> wrote in message
> > ·················@woodrow.ucdavis.edu...
> > > Hi
> > >
> > > I need to write a function that takes in a list and a function, tests
the
> > > function over each of the members of the list and returns two lists :
one
> > > list is of the members where the function evaluates to true and the
other
> >  is
> > > where the function evaluates to false.
>
> > But I think this is unnecessarily complicated.  Why don't you DOLIST or
LOOP
> > over the list and gather up your two return lists?  Recursion will be
hard
> > to untangle visually and is not really a very intuitive aproach.
[snip an iterative solution]
> The recursive form is pretty simple.
>
[snip a recursive solution]
> Few things are intuitive until understood :)

Intuitive means making sense without really being understood.  I have no
problem reading (or writing) your code, but it still supports my position.

(from dictionary.com:
intuition: The act or faculty of knowing or sensing without the use of
rational processes; immediate cognition)

--
Coby Beck
(remove #\Space "coby 101 @ bigpond . com")
From: Brian Spilsbury
Subject: Re: Stumped (basic LISP question)
Date: 
Message-ID: <f0f9d928.0205210037.2dde98c9@posting.google.com>
"Coby Beck" <·····@mercury.bc.ca> wrote in message news:<························@news1.calgary.shaw.ca>...
> "Brian Spilsbury" <·····@designix.com.au> wrote in message
> > Few things are intuitive until understood :)
> 
> Intuitive means making sense without really being understood.  I have no
> problem reading (or writing) your code, but it still supports my position.
> 
> (from dictionary.com:
> intuition: The act or faculty of knowing or sensing without the use of
> rational processes; immediate cognition)

If you are using that to take exception to 'until understood', then
the only things which will qualify will be instincts and reflexes.

Once understood and internalised or automated many things become
intuitive, but very few things start out that way. :)

(Even developmental processes such as the ability to conserve quantity
in two dimensions have a significant learned component, as the
difference in performance of children in primitive cultures with and
without schooling shows - would you think that it is intuitive that
the amount of liquid does not change when we pour it from one glass
into another?)

Perhaps I should have said 'learned' above instead of 'understood'.

Regards,

Brian.
From: pizza
Subject: Re: Stumped (basic LISP question)
Date: 
Message-ID: <pan.2002.05.20.14.53.41.655160.2752@parseerror.com>
On Sun, 19 May 2002 18:38:05 -0400, AR wrote:

> Hi
> 
> I need to write a function that takes in a list and a function, tests
> the function over each of the members of the list and returns two lists
> : one list is of the members where the function evaluates to true and
> the other is where the function evaluates to false.


;newbie answer
 
(defun yesno (l f) ;l = list, f = predicate function
  (setq y nil n nil) 'create y and n lists
  (dolist (i l) ;iterate over l
    (if (funcall f i) ;test
      (setq y (cons i y)) ;if true add to y
      (setq n (cons i n)) ;else add to false
    )
  )
  (setq a (list y n)) ;return list of y and n
)

love,

--pizza

 Posted Via Usenet.com Premium Usenet Newsgroup Services
----------------------------------------------------------
    ** SPEED ** RETENTION ** COMPLETION ** ANONYMITY **
----------------------------------------------------------        
                http://www.usenet.com
From: Coby Beck
Subject: Re: Stumped (basic LISP question)
Date: 
Message-ID: <dVaG8.108715$xS2.8457476@news1.calgary.shaw.ca>
"pizza" <·····@parseerror.com> wrote in message
········································@parseerror.com...
> On Sun, 19 May 2002 18:38:05 -0400, AR wrote:
>
> > Hi
> >
> > I need to write a function that takes in a list and a function, tests
> > the function over each of the members of the list and returns two lists
> > : one list is of the members where the function evaluates to true and
> > the other is where the function evaluates to false.
>
>
> ;newbie answer

Please accept my comments in the constructive spirit they are offered in...

> (defun yesno (l f) ;l = list, f = predicate function
>   (setq y nil n nil) 'create y and n lists

You have just created two special variables, y and n that are now visible
anywhere in any code in this package.  If that is not your explicit desire
make sure you use (let (x y) ...)  If it is you explicit desire,
conventional wisdom says to put *'s around them: *y* *n* and declare them
outside of this function.

>   (dolist (i l) ;iterate over l
>     (if (funcall f i) ;test
>       (setq y (cons i y)) ;if true add to y
>       (setq n (cons i n)) ;else add to false

      save a few keystrokes and use (push i n)

>     )
>   )
>   (setq a (list y n)) ;return list of y and n
> )

Every common lisp form returns something so it is unnecessary to do things
like create and bind a return variable or call return-from at the end of
your function.  Your last line needs only to be:
(list y n)

-also, you have again created a global variable, A here!

dolist also lets you specify its return value, so you could rewrite the
above as:

(let (y n)
  (dolist (i l (list y n))
    (if (funcall f i)
        (push i y)
      (push i n))))

NB: I'm not a big fan of one letter variables with a few exceptions, but I
just left them as is for easier comparison.

--
Coby Beck
(remove #\Space "coby 101 @ bigpond . com")
From: John Wiseman
Subject: Re: Stumped (basic LISP question)
Date: 
Message-ID: <m2elg6y7ix.fsf@server.local.lemon>
"Coby Beck" <·····@mercury.bc.ca> writes:

> > (defun yesno (l f) ;l = list, f = predicate function
> >   (setq y nil n nil) 'create y and n lists
> 
> You have just created two special variables, y and n that are now
> visible anywhere in any code in this package.

Maybe.  Actually the effects are undefined; some implementations do
what you describe, some don't.


John Wiseman
From: Coby Beck
Subject: Re: Stumped (basic LISP question)
Date: 
Message-ID: <IYcG8.109284$xS2.8539683@news1.calgary.shaw.ca>
"John Wiseman" <·······@server.local.lemon> wrote in message
···················@server.local.lemon...
> "Coby Beck" <·····@mercury.bc.ca> writes:
>
> > > (defun yesno (l f) ;l = list, f = predicate function
> > >   (setq y nil n nil) 'create y and n lists
> >
> > You have just created two special variables, y and n that are now
> > visible anywhere in any code in this package.
>
> Maybe.  Actually the effects are undefined; some implementations do
> what you describe, some don't.

You are right, of course!

--
Coby Beck
(remove #\Space "coby 101 @ bigpond . com")
From: pizza
Subject: Re: Stumped (basic LISP question)
Date: 
Message-ID: <pan.2002.05.21.15.48.46.201700.4729@parseerror.com>
On Mon, 20 May 2002 14:04:57 -0400, Coby Beck wrote:


> "pizza" <·····@parseerror.com> wrote in message
> ········································@parseerror.com...
>> On Sun, 19 May 2002 18:38:05 -0400, AR wrote:
>>
>> > Hi
>> >
>> > I need to write a function that takes in a list and a function, tests
>> > the function over each of the members of the list and returns two
>> > lists
>> > : one list is of the members where the function evaluates to true and
>> > the other is where the function evaluates to false.
>>
>>
>> ;newbie answer
> 
> Please accept my comments in the constructive spirit they are offered
> in...
> 
>> (defun yesno (l f) ;l = list, f = predicate function
>>   (setq y nil n nil) 'create y and n lists
> 
> You have just created two special variables, y and n that are now
> visible anywhere in any code in this package.  If that is not your
> explicit desire make sure you use (let (x y) ...)  If it is you explicit
> desire, conventional wisdom says to put *'s around them: *y* *n* and
> declare them outside of this function.
> 
>>   (dolist (i l) ;iterate over l
>>     (if (funcall f i) ;test
>>       (setq y (cons i y)) ;if true add to y (setq n (cons i n)) ;else
>>       add to false
> 
>       save a few keystrokes and use (push i n)
> 
>>     )
>>   )
>>   (setq a (list y n)) ;return list of y and n
>> )
> 
> Every common lisp form returns something so it is unnecessary to do
> things like create and bind a return variable or call return-from at the
> end of your function.  Your last line needs only to be: (list y n)
> 
> -also, you have again created a global variable, A here!
> 
> dolist also lets you specify its return value, so you could rewrite the
> above as:
> 
> (let (y n)
>   (dolist (i l (list y n))
>     (if (funcall f i)
>         (push i y)
>       (push i n))))
> 
> NB: I'm not a big fan of one letter variables with a few exceptions, but
> I just left them as is for easier comparison.
> 
> --
> Coby Beck
> (remove #\Space "coby 101 @ bigpond . com")
 
Coby,

Thanks for the response, I learned from it.

love,

pizza

 Posted Via Usenet.com Premium Usenet Newsgroup Services
----------------------------------------------------------
    ** SPEED ** RETENTION ** COMPLETION ** ANONYMITY **
----------------------------------------------------------        
                http://www.usenet.com
From: Kaz Kylheku
Subject: Re: Stumped (basic LISP question)
Date: 
Message-ID: <slrnael1ul.sbg.kaz@localhost.localdomain>
On Sun, 19 May 2002 15:38:05 -0700, AR <········@yahoo.com> wrote:
>Hi
>
>I need to write a function that takes in a list and a function, tests the
>function over each of the members of the list and returns two lists : one
>list is of the members where the function evaluates to true and the other is
>where the function evaluates to false.

I have exactly such a function in the Meta-CVS project, or rather a pair
of functions. These are modeled after the conventions of the Common Lisp
sequences library, and are basically wrappers for the remove family
of functions. The two lists are returned as a pair of values.
Feel free to do whatever you want with these functions.

defun separate-if (test sequence &rest keys)
  (let ((wheat (apply #'remove-if-not test sequence keys))
        (chaff (apply #'remove-if test sequence keys)))
    (values wheat chaff)))

(defun separate (item sequence &key (test #'eql) key)
  (let ((wheat (funcall #'remove-if-not #'(lambda (x) (funcall test item x))
                                      sequence :key key))
        (chaff (funcall #'remove item sequence :key key :test test)))
    (values wheat chaff)))

>(defun split ( pred l)
>  (cond
>    ((null l) '())
>
>     ((funcall pred (car l))
>      (cons (car l) (split pred (cdr l))))
>          (t
>      ( split pred(cdr l)))))

Brain damaged by Scheme? You do know that Lisp implementations are not
required to be tail recursive?
From: Kaz Kylheku
Subject: Re: Stumped (basic LISP question)
Date: 
Message-ID: <slrnael20c.sbg.kaz@localhost.localdomain>
On Sun, 19 May 2002 15:38:05 -0700, AR <········@yahoo.com> wrote:
>Hi
>
>I need to write a function that takes in a list and a function, tests the
>function over each of the members of the list and returns two lists : one
>list is of the members where the function evaluates to true and the other is
>where the function evaluates to false.

I have exactly such a function in the Meta-CVS project, or rather a pair
of functions. These are modeled after the conventions of the Common Lisp
sequences library, and are basically wrappers for the remove family
of functions. The two lists are returned as a pair of values.
Feel free to do whatever you want with these functions.

(defun separate-if (test sequence &rest keys)
  (let ((wheat (apply #'remove-if-not test sequence keys))
        (chaff (apply #'remove-if test sequence keys)))
    (values wheat chaff)))

(defun separate (item sequence &key (test #'eql) key)
  (let ((wheat (funcall #'remove-if-not #'(lambda (x) (funcall test item x))
                                      sequence :key key))
        (chaff (funcall #'remove item sequence :key key :test test)))
    (values wheat chaff)))

>(defun split ( pred l)
>  (cond
>    ((null l) '())
>
>     ((funcall pred (car l))
>      (cons (car l) (split pred (cdr l))))
>          (t
>      ( split pred(cdr l)))))

Brain damaged by Scheme? You do know that Lisp implementations are not
required to be tail recursive?
From: Geoff Summerhayes
Subject: Re: Stumped (basic LISP question)
Date: 
Message-ID: <jxwG8.113722$xS2.9029388@news1.calgary.shaw.ca>
"Kaz Kylheku" <···@localhost.localdomain> wrote in message
·······················@localhost.localdomain...
> I have exactly such a function in the Meta-CVS project, or rather a pair
> of functions. These are modeled after the conventions of the Common Lisp
> sequences library, and are basically wrappers for the remove family
> of functions. The two lists are returned as a pair of values.
> Feel free to do whatever you want with these functions.
>
> (defun separate-if (test sequence &rest keys)
>  ...

Neat. My turn. With overkill. MWAH, HA, HA. :-)

(defmacro sift-list (list &rest tests)
  (let ((collectors (mapcar #'gensym tests))
        (last (gensym)))
    `(let (,@collectors ,last)
       (dolist (item ,list)
         (cond ,@(mapcar (lambda (x y)
                           `((funcall ,x item) (push item ,y)))
                         tests collectors)
               (t (push item ,last))))
       (values ,@collectors ,last))))

> (sift-list '( 1 2 3 4 5 6 7 8 9 10) (lambda (x) (> x 4)))
(10 9 8 7 6 5)
(4 3 2 1)

> (sift-list '(1 2 3 -1 -2 -3) #'oddp #'plusp)
(-3 -1 3 1)
(2)
(-2)

> (sift-list '(1 2 3 -1 -2 -3) #'plusp #'oddp)
(3 2 1)
(-3 -1)
(-2)

--------
Geoff
From: Geoff Summerhayes
Subject: Re: Stumped (basic LISP question)
Date: 
Message-ID: <rGwG8.113303$GG6.9574661@news3.calgary.shaw.ca>
"Geoff Summerhayes" <·············@hNoOtSmPaAiMl.com> wrote in message
·····························@news1.calgary.shaw.ca...
>
>
> (defmacro sift-list (list &rest tests)
>   (let ((collectors (mapcar #'gensym tests))
Oops!                           ^^^^^^
should read:                    (lambda (x) (gensym))
>     `(let (,@collectors ,last)
>        (dolist (item ,list)
>          (cond ,@(mapcar (lambda (x y)
>                            `((funcall ,x item) (push item ,y)))
>                          tests collectors)
>                (t (push item ,last))))
>        (values ,@collectors ,last))))
>

Geoff
From: Barry Margolin
Subject: Re: Stumped (basic LISP question)
Date: 
Message-ID: <hTwG8.8$uF.1153@paloalto-snr2.gtei.net>
In article <························@news1.calgary.shaw.ca>,
Geoff Summerhayes <·············@hNoOtSmPaAiMl.com> wrote:
>Neat. My turn. With overkill. MWAH, HA, HA. :-)
>
>(defmacro sift-list (list &rest tests)
>  (let ((collectors (mapcar #'gensym tests))
>        (last (gensym)))
>    `(let (,@collectors ,last)
>       (dolist (item ,list)
>         (cond ,@(mapcar (lambda (x y)
>                           `((funcall ,x item) (push item ,y)))
>                         tests collectors)
>               (t (push item ,last))))
>       (values ,@collectors ,last))))

Is there any good reason why this needs to be a macro instead of a
function?  It evaluates all its arguments just like an ordinary function
call would.

-- 
Barry Margolin, ······@genuity.net
Genuity, Woburn, MA
*** DON'T SEND TECHNICAL QUESTIONS DIRECTLY TO ME, post them to newsgroups.
Please DON'T copy followups to me -- I'll assume it wasn't posted to the group.
From: Geoff Summerhayes
Subject: Re: Stumped (basic LISP question)
Date: 
Message-ID: <8pxG8.23516$Ka.1845890@news2.calgary.shaw.ca>
"Barry Margolin" <······@genuity.net> wrote in message
····················@paloalto-snr2.gtei.net...

> Is there any good reason why this needs to be a macro instead of a
> function?  It evaluates all its arguments just like an ordinary function
> call would.
>

No, it was just started that way and I found it easier to write.

-----------

Geoff
From: Robert Maas
Subject: Re: Stumped (basic LISP question)
Date: 
Message-ID: <ef5aa6c5.0205221135.23ab5e6f@posting.google.com>
···@localhost.localdomain (Kaz Kylheku) wrote in message news:<··················@localhost.localdomain>...
> (defun separate-if (test sequence &rest keys)
>   (let ((wheat (apply #'remove-if-not test sequence keys))
>         (chaff (apply #'remove-if test sequence keys)))
>     (values wheat chaff)))

Unfortnately that applies the test to each key twice instead of
the desired once. If it's an expensive test, that doubles the cost.
If it's a non-deterministic test, the same element might be in both
or neither list instead of always in exactly one list. For example,
if the test is whether an IP number resolves with RevDNS, it's both
expensive and non-deterministic. Better would be to build a third list
with just T NIL values, via MAPL, then do the remove-if and remove-if-not
by just looking at those pre-computed results.

Does anybody think my wisdom and practical experience is of any value??
I'm desperately in search of employment. See my CGI/CMUCL demo:
  <http://shell.rawbw.com/~rem/cgi-bin/topscript.cgi>
I'd to write FAQ-search engines, educational software, etc. using CGI/CMUCL.
From: Robert Maas
Subject: Re: Stumped (basic LISP question)
Date: 
Message-ID: <ef5aa6c5.0205221047.7744d0fa@posting.google.com>
"AR" <········@yahoo.com> wrote in message news:<············@woodrow.ucdavis.edu>...
> I need to write a function that takes in a list and a function, tests the
> function over each of the members of the list and returns two lists : one
> list is of the members where the function evaluates to true and the other is
> where the function evaluates to false.

That's pretty trivial: You create two empty lists at the start: revt revnil
Then you map down the input list, deciding whether to push each element
onto revt or revnil. Then when done, return nreverse of revt and revnil.

> So, I got the part where you return the list of elements for which the list
> evaluates to be true:
>
> (defun split (pred l)
>   (cond
>     ((null l) '())
>     ((funcall pred (car l))
>      (cons (car l) (split pred (cdr l))))
>     (t (split pred (cdr l)))))

What you're consing the two results into a pair at each level then
immediately breaking it back up? That's too much extra CONSing.
At least if you finished the code per your style that's what you'd be doing.
If you absolutely must write it with recursion instead of mapping and
nreverse, use multiple value instead of dotted pair to pass up partial results.

Hint: When writing something that traverses all possible branches of
a tree, use recursion. When writing something that merely maps down a
linear list, use mapping and/or loops and then nreverses of the final
accumulated results.