defun take-if, how to pass comparing function?

This is a discussion on defun take-if, how to pass comparing function? within the lisp forums in Programming Languages category; 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 ...

Go Back   Application Development Forum > Programming Languages > lisp

Object Mix

Register FAQ Calendar Search Today's Posts Mark Forums Read
  #1  
Old 08-22-2008, 08:29 PM
defn noob
Guest
 
Default defun take-if, how to pass comparing function?

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
Reply With Quote
  #2  
Old 08-22-2008, 08:39 PM
Frank Buss
Guest
 
Default Re: defun take-if, how to pass comparing function?

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, fb@frank-buss.de
http://www.frank-buss.de, http://www.it4-systems.de
Reply With Quote
  #3  
Old 08-22-2008, 08:51 PM
Pascal J. Bourguignon
Guest
 
Default Re: defun take-if, how to pass comparing function?

defn noob <circularfunc@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.
Reply With Quote
  #4  
Old 08-23-2008, 01:56 AM
Kenny
Guest
 
Default Re: defun take-if, how to pass comparing function?

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
Reply With Quote
  #5  
Old 08-23-2008, 02:15 AM
Frank Buss
Guest
 
Default Re: defun take-if, how to pass comparing function?

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/cs3...Solutions.html

--
Frank Buss, fb@frank-buss.de
http://www.frank-buss.de, http://www.it4-systems.de
Reply With Quote
  #6  
Old 08-23-2008, 03:10 AM
joswig@corporate-world.lisp.de
Guest
 
Default Re: defun take-if, how to pass comparing function?

On Aug 23, 8:15*am, Frank Buss <f...@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/cs3...mework_Solutio...
>
> --
> Frank Buss, f...@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/res...ew.php?id=1906


Reply With Quote
  #7  
Old 08-23-2008, 03:19 AM
verec
Guest
 
Default Re: defun take-if, how to pass comparing function?

On 2008-08-23 01:29:27 +0100, defn noob <circularfunc@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

Reply With Quote
  #8  
Old 08-23-2008, 07:37 AM
Stanisław Halik
Guest
 
Default Re: defun take-if, how to pass comparing function?

thus spoke Frank Buss <fb@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/cs3...Solutions.html


This one's tad cooler:

http://www.cs.ucla.edu/classes/sprin...31/hw/hw5.html

--
The great peril of our existence lies in the fact that our diet consists
entirely of souls. -- Inuit saying
Reply With Quote
  #9  
Old 08-23-2008, 08:34 AM
Kenny
Guest
 
Default Re: defun take-if, how to pass comparing function?


> thus spoke Frank Buss <fb@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/
Reply With Quote
  #10  
Old 09-16-2008, 05:02 AM
William James
Guest
 
Default Re: defun take-if, how to pass comparing function?

On Aug 23, 2:19 am, verec <ve...@mac.com> wrote:
> On 2008-08-23 01:29:27 +0100, defn noob <circularf...@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]
Reply With Quote
Reply


Thread Tools
Display Modes


All times are GMT -5. The time now is 01:36 AM.


Powered by vBulletin® Version 3.7.2
Copyright ©2000 - 2008, Jelsoft Enterprises Ltd.
Search Engine Optimization by vBSEO 3.2.0
vB Ad Management by =RedTyger=

In an effort to better serve ads to our visitors, cookies are used on objectmix.com. For more information, check out our Privacy Policy.