From: defn noob
Subject: defun take-if, how to pass comparing function?
Date: 
Message-ID: <7a621b22-0cfa-4860-bec9-e5cee4215481@m45g2000hsb.googlegroups.com>
I am doing simple exercises do learn CL. I implemented take as so:

(defun take (n lista)
  (if (> n 0)
      (cons (car lista) (take (- n 1) (cdr lista)))
      '()))

I want a function take-if that works like take but takes the first n
element where x meets a condition pred.

(defun take-if (n pred lista)
  (if (> n 0)
      (if (pred)
	  (cons (car lista) (take-if (- n 1) pred (cdr lista)))
	  (take-if (- n 1) pred (cdr lista)))
      '()))

so:
(take-if 3 (> x 2) '(1 2 3 4 5 6 7 8 9))
should return (3 4 5)


(take-if 3 (lambda (x) (> x 2)) '(1 2 3 4 5))
; Evaluation aborted

From: Kenny
Subject: Re: defun take-if, how to pass comparing function?
Date: 
Message-ID: <48afa67f$0$29516$607ed4bc@cv.net>
defn noob wrote:
> I am doing simple exercises do learn CL. I implemented take as so:
> 
> (defun take (n lista)
>   (if (> n 0)
>       (cons (car lista) (take (- n 1) (cdr lista)))
>       '()))
> 
> I want a function take-if that works like take but takes the first n
> element where x meets a condition pred.
> 
> (defun take-if (n pred lista)
>   (if (> n 0)
>       (if (pred)
> 	  (cons (car lista) (take-if (- n 1) pred (cdr lista)))
> 	  (take-if (- n 1) pred (cdr lista)))
>       '()))
> 
> so:
> (take-if 3 (> x 2) '(1 2 3 4 5 6 7 8 9))
> should return (3 4 5)
> 
> 
> (take-if 3 (lambda (x) (> x 2)) '(1 2 3 4 5))
> ; Evaluation aborted

(lambda (x) ..) takes one argument. The form (pred) passes no arguments 
to the function named 'pred. That sentence suggests two problems. I 
would be less sphinxian if this did not seem like homework.

kzo
From: Frank Buss
Subject: Re: defun take-if, how to pass comparing function?
Date: 
Message-ID: <1w9zu2q4l9gwj$.1axj0lviif40x$.dlg@40tude.net>
Kenny wrote:

> (lambda (x) ..) takes one argument. The form (pred) passes no arguments 
> to the function named 'pred. That sentence suggests two problems. I 
> would be less sphinxian if this did not seem like homework.

I don't think list comprehensions and higher order functions in Lisp are
homework. Lisp homework usually is much more boring, e.g. something like
this:

http://www.cs.iit.edu/~cs480/LISPHW1.html
http://babbage.cs.qc.edu/courses/cs300/Spring00/LISP_Homework_Solutions.html

-- 
Frank Buss, ··@frank-buss.de
http://www.frank-buss.de, http://www.it4-systems.de
From: ······@corporate-world.lisp.de
Subject: Re: defun take-if, how to pass comparing function?
Date: 
Message-ID: <0bfa78c2-1269-450b-b394-324a3be01d25@p25g2000hsf.googlegroups.com>
On Aug 23, 8:15 am, Frank Buss <····@frank-buss.de> wrote:
> Kenny wrote:
> > (lambda (x) ..) takes one argument. The form (pred) passes no arguments
> > to the function named 'pred. That sentence suggests two problems. I
> > would be less sphinxian if this did not seem like homework.
>
> I don't think list comprehensions and higher order functions in Lisp are
> homework. Lisp homework usually is much more boring, e.g. something like
> this:
>
> http://www.cs.iit.edu/~cs480/LISPHW1.html http://babbage.cs.qc.edu/courses/cs300/Spring00/LISP_Homework_Solutio...
>
> --
> Frank Buss, ····@frank-buss.dehttp://www.frank-buss.de,http://www.it4-systems.de

I don't think that's true.

http://moodle.cs.ualberta.ca/mod/resource/view.php?id=1906
From: Stanisław Halik
Subject: Re: defun take-if, how to pass comparing function?
Date: 
Message-ID: <g8osqi$18qb$1@opal.icpnet.pl>
thus spoke Frank Buss <··@frank-buss.de>:

> Kenny wrote:

>> (lambda (x) ..) takes one argument. The form (pred) passes no arguments 
>> to the function named 'pred. That sentence suggests two problems. I 
>> would be less sphinxian if this did not seem like homework.

> I don't think list comprehensions and higher order functions in Lisp are
> homework. Lisp homework usually is much more boring, e.g. something like
> this:

> http://www.cs.iit.edu/~cs480/LISPHW1.html
> http://babbage.cs.qc.edu/courses/cs300/Spring00/LISP_Homework_Solutions.html

This one's tad cooler:

http://www.cs.ucla.edu/classes/spring08/cs131/hw/hw5.html

-- 
The great peril of our existence lies in the fact that our diet consists
entirely of souls. -- Inuit saying
From: Kenny
Subject: Re: defun take-if, how to pass comparing function?
Date: 
Message-ID: <48b0041b$0$7333$607ed4bc@cv.net>
> thus spoke Frank Buss <··@frank-buss.de>:
> 
> 
>>Kenny wrote:
> 
> 
>>>(lambda (x) ..) takes one argument. The form (pred) passes no arguments 
>>>to the function named 'pred. That sentence suggests two problems. I 
>>>would be less sphinxian if this did not seem like homework.
> 
> 
>>I don't think list comprehensions and higher order functions in Lisp are
>>homework. Lisp homework usually is much more boring, 

<g>

The data points themselves are not as interesting as the slope: the 
tip-off is the graded transition in complexity from the working example 
to the one not suggesting the first was given and the second assigned as 
a well-crafted exercise requiring only a single new element. This in 
turn implies an excellent instructor inturn explaining the uncommon 
unboringness. Oh, cool, the grammar checker just melted down.

kt
---
http://www.theoryyalgebra.com/
From: Frank Buss
Subject: Re: defun take-if, how to pass comparing function?
Date: 
Message-ID: <zsgoox6b9m0m$.1daeiz9xw622.dlg@40tude.net>
defn noob wrote:

> (take-if 3 (> x 2) '(1 2 3 4 5 6 7 8 9))
> should return (3 4 5)

With this syntax it wouldn't work with functions, because the second
parameter is evaluated before passed to the function. If you use a macro,
you could write it like you've done (with the right commas etc.).

> (take-if 3 (lambda (x) (> x 2)) '(1 2 3 4 5))
> ; Evaluation aborted

This is the functional solution. Take a look at funcall to see how you can
call functions defined as parameters.

For some problems using higher order functions (functions which takes
functions) leads to nice short code:

http://www.frank-buss.de/lisp/functional.html

-- 
Frank Buss, ··@frank-buss.de
http://www.frank-buss.de, http://www.it4-systems.de
From: Pascal J. Bourguignon
Subject: Re: defun take-if, how to pass comparing function?
Date: 
Message-ID: <87vdxswo3b.fsf@hubble.informatimago.com>
defn noob <············@yahoo.se> writes:

> I am doing simple exercises do learn CL. I implemented take as so:
>
> (defun take (n lista)
>   (if (> n 0)
>       (cons (car lista) (take (- n 1) (cdr lista)))
>       '()))
>
> I want a function take-if that works like take but takes the first n
> element where x meets a condition pred.
>
> (defun take-if (n pred lista)
>   (if (> n 0)
>       (if (pred)
> 	  (cons (car lista) (take-if (- n 1) pred (cdr lista)))
> 	  (take-if (- n 1) pred (cdr lista)))
>       '()))
>
> so:
> (take-if 3 (> x 2) '(1 2 3 4 5 6 7 8 9))
> should return (3 4 5)
>
>
> (take-if 3 (lambda (x) (> x 2)) '(1 2 3 4 5))
> ; Evaluation aborted

No.   It doesn't just say "Evaluation aborted".  What does it really say?


-- 
__Pascal Bourguignon__                     http://www.informatimago.com/

This universe shipped by weight, not volume.  Some expansion may have
occurred during shipment.
From: verec
Subject: Re: defun take-if, how to pass comparing function?
Date: 
Message-ID: <48afb9e4$0$628$5a6aecb4@news.aaisp.net.uk>
On 2008-08-23 01:29:27 +0100, defn noob <············@yahoo.se> said:

> I am doing simple exercises do learn CL. I implemented take as so:
> 
> (defun take (n lista)
>   (if (> n 0)
>       (cons (car lista) (take (- n 1) (cdr lista)))
>       '()))
> 
> I want a function take-if that works like take but takes the first n
> element where x meets a condition pred.
> 
> (defun take-if (n pred lista)
>   (if (> n 0)
>       (if (pred)
> 	  (cons (car lista) (take-if (- n 1) pred (cdr lista)))
> 	  (take-if (- n 1) pred (cdr lista)))
>       '()))
> 
> so:
> (take-if 3 (> x 2) '(1 2 3 4 5 6 7 8 9))
> should return (3 4 5)
> 
> 
> (take-if 3 (lambda (x) (> x 2)) '(1 2 3 4 5))
> ; Evaluation aborted

(defun take-if (n pred list)
  (cond ((zerop n) nil)     ; <= 1
        ((null list) nil)   ; <= 2
        (t
         (if (and (>= n 1)  ; <= 3
                  (funcall pred (car list)))
             (cons (car list) (take-if (- n 1) pred (cdr list)))
           (take-if n pred (cdr list))))))

While
(take-if 3 #'(lambda (x) (> x 2)) '(1 2 3 4 5 6 7 8 9))   => (3 4 5)

the lines marked wuth ; <= x are edge cases

; <= 1
(take-if 1 #'(lambda (x) (> x 2)) '(1 2 3 4 5 6 7 8 9))   => (3)
; <= 2
(take-if 12 #'(lambda (x) (> x 2)) '(5 1))                => (5)
; <= 3
(take-if 1 #'(lambda (x) (> x 2)) '(1 2 3 4 5 6 7 8 9))   => (3)

Check whether there's any other edge case not accounted for :-)
--
JFB
From: William James
Subject: Re: defun take-if, how to pass comparing function?
Date: 
Message-ID: <3047e49b-2764-4ac6-9141-98c1d00255ad@d1g2000hsg.googlegroups.com>
On Aug 23, 2:19 am, verec <·····@mac.com> wrote:
> On 2008-08-23 01:29:27 +0100, defn noob <············@yahoo.se> said:
>
>
>
> > I am doing simple exercises do learn CL. I implemented take as so:
>
> > (defun take (n lista)
> >   (if (> n 0)
> >       (cons (car lista) (take (- n 1) (cdr lista)))
> >       '()))
>
> > I want a function take-if that works like take but takes the first n
> > element where x meets a condition pred.
>
> > (defun take-if (n pred lista)
> >   (if (> n 0)
> >       (if (pred)
> >      (cons (car lista) (take-if (- n 1) pred (cdr lista)))
> >      (take-if (- n 1) pred (cdr lista)))
> >       '()))
>
> > so:
> > (take-if 3 (> x 2) '(1 2 3 4 5 6 7 8 9))
> > should return (3 4 5)
>
> > (take-if 3 (lambda (x) (> x 2)) '(1 2 3 4 5))
> > ; Evaluation aborted
>
> (defun take-if (n pred list)
>   (cond ((zerop n) nil)     ; <= 1
>         ((null list) nil)   ; <= 2
>         (t
>          (if (and (>= n 1)  ; <= 3
>                   (funcall pred (car list)))
>              (cons (car list) (take-if (- n 1) pred (cdr list)))
>            (take-if n pred (cdr list))))))
>
> While
> (take-if 3 #'(lambda (x) (> x 2)) '(1 2 3 4 5 6 7 8 9))   => (3 4 5)

Ruby:

def take_if n, list
  list.select{|x| yield x}[0,n]
end
    ==>nil
take_if( 3, [1,2,3,4,5,6,7,8,9] ){|n| n > 3 }
    ==>[4, 5, 6]
From: André Thieme
Subject: Re: defun take-if, how to pass comparing function?
Date: 
Message-ID: <gffhkc$e9s$1@news.eternal-september.org>
William James schrieb:

> def take_if n, list
>   list.select{|x| yield x}[0,n]
> end

In Clojure:
(defn take-if [n f list] (take n (filter f list)))

That�s just one line compared to Rubys 3.
200% more LOC for Ruby :-(
Plus the Ruby code is 10% longer (55 chars vs. 50).


> take_if( 3, [1,2,3,4,5,6,7,8,9] ){|n| n > 3 }
>     ==>[4, 5, 6]

even this call is shorter in Lisp:
(take-if 3 #(> % 3) [1 2 3 4 5 6 7 8 9])
==> (4 5 6)


Now let�s try this and see how fast it runs:
take_if(10, 1..100000000) {|n| n > 15}
vs.
(take-if 10  #(> % 15) (range 9999999999999999999999999999999999))

The Clojure code takes far less than a millisecond to finish.


Andr�
-- 
Lisp is not dead. It�s just the URL that has changed:
http://clojure.org/