Listcomprehension-macro? Macros with args inside macro-name?

This is a discussion on Listcomprehension-macro? Macros with args inside macro-name? within the lisp forums in Programming Languages category; In article <6410dbf9-a288-4e70-8589-9dac442b9ff7 @ m73g2000hsh.googlegroups.com>, Marco Antoniotti <marcoxa @ gmail.com> wrote: > On Aug 23, 9:50*am, Grant Rettke <gret...@gmail.com> wrote: > > On Aug 22, 5:16*pm, defn noob <circularf...@yahoo.se> wrote: > > > > > I am trying to learn lisp macros and I generally find > > > listcomprehensions to be elegant and they dont exist in lisp. > > > This has to be a macro right? Cant be a function? > > > > For inspiration here is one option for list comprehensions in Scheme: http://srfi.schemers.org/srfi-42/srfi-42.html > > > > Or PLT Scheme in particular: http://docs.plt-scheme.org/reference/for.html > ...

Go Back   Application Development Forum > Programming Languages > lisp

Object Mix

Register FAQ Calendar Search Today's Posts Mark Forums Read
Reply

 

LinkBack Thread Tools Display Modes
  #11  
Old 08-23-2008, 11:29 AM
Rainer Joswig
Guest
 
Default Re: Listcomprehension-macro? Macros with args inside macro-name?

In article
<6410dbf9-a288-4e70-8589-9dac442b9ff7@m73g2000hsh.googlegroups.com>,
Marco Antoniotti <marcoxa@gmail.com> wrote:

> On Aug 23, 9:50*am, Grant Rettke <gret...@gmail.com> wrote:
> > On Aug 22, 5:16*pm, defn noob <circularf...@yahoo.se> wrote:
> >
> > > I am trying to learn lisp macros and I generally find
> > > listcomprehensions to be elegant and they dont exist in lisp.
> > > This has to be a macro right? Cant be a function?

> >
> > For inspiration here is one option for list comprehensions in Scheme:http://srfi.schemers.org/srfi-42/srfi-42.html
> >
> > Or PLT Scheme in particular:http://docs.plt-scheme.org/reference/for.html

>
> Vintage 2001. Inspiration: SETL
>
> http://groups.google.com/group/comp....461d383f8f7e32
>
> ping me for the code.
>
> Cheers
> --
> Marco



How about NESL?

http://www-2.cs.cmu.edu/~scandal/nesl.html

http://www.cs.cmu.edu/~scandal/nesl/...ml#lightweight

RJMBP:neslseq joswig$ cmucl
CMU Common Lisp Snapshot 2008-07 (19E), running on RJMBP.local
With core: /usr/local/lib/cmucl/lib/lisp.core
Dumped on: Sat, 2008-06-28 13:31:54+02:00 on macmini
See <http://www.cons.org/cmucl/> for support information.
Loaded subsystems:
Python 1.1, target Intel x86
CLOS based on Gerd's PCL 2004/04/14 03:32:47
CLX X Library Telent CLX 0.7.3 + CMUCL mods, based on MIT R5.02
Hemlock 3.5

....

* (nesl)

% NESL version Sequential 1.0 (June 18, 1995) %

% Use (nesl) when an error aborts you out of the interpreter. %
% Type help; for a list of the top level commands. %

[Nesl] {a + 1: a in [2, 3, 4]};
it = [3, 4, 5] : [int]

[Nesl]

--
http://lispm.dyndns.org/
Reply With Quote
  #12  
Old 08-24-2008, 10:25 AM
Marco Antoniotti
Guest
 
Default Re: Listcomprehension-macro? Macros with args inside macro-name?

On Aug 23, 11:29*am, Rainer Joswig <jos...@lisp.de> wrote:
> In article
> <6410dbf9-a288-4e70-8589-9dac442b9...@m73g2000hsh.googlegroups.com>,
> *Marco Antoniotti <marc...@gmail.com> wrote:
>
>
>
> > On Aug 23, 9:50*am, Grant Rettke <gret...@gmail.com> wrote:
> > > On Aug 22, 5:16*pm, defn noob <circularf...@yahoo.se> wrote:

>
> > > > I am trying to learn lisp macros and I generally find
> > > > listcomprehensions to be elegant and they dont exist in lisp.
> > > > This has to be a macro right? Cant be a function?

>
> > > For inspiration here is one option for list comprehensions in Scheme:http://srfi.schemers.org/srfi-42/srfi-42.html

>
> > > Or PLT Scheme in particular:http://docs.plt-scheme.org/reference/for.html

>
> > Vintage 2001. *Inspiration: SETL

>
> >http://groups.google.com/group/comp....m/thread/e84f2...

>
> > ping me for the code.

>
> > Cheers
> > --
> > Marco

>
> How about NESL?
>
> http://www-2.cs.cmu.edu/~scandal/nesl.html
>
> http://www.cs.cmu.edu/~scandal/nesl/...ml#lightweight
>
> RJMBP:neslseq joswig$ cmucl
> CMU Common Lisp Snapshot 2008-07 (19E), running on RJMBP.local
> With core: /usr/local/lib/cmucl/lib/lisp.core
> Dumped on: Sat, 2008-06-28 13:31:54+02:00 on macmini
> See <http://www.cons.org/cmucl/> for support information.
> Loaded subsystems:
> * * Python 1.1, target Intel x86
> * * CLOS based on Gerd's PCL 2004/04/14 03:32:47
> * * CLX X Library Telent CLX 0.7.3 + CMUCL mods, based on MIT R5.02
> * * Hemlock 3.5
>
> ...
>
> * (nesl)
>
> % NESL version Sequential 1.0 (June 18, 1995) %
>
> % Use (nesl) when an error aborts you out of the interpreter. %
> % Type help; for a list of the top level commands. %
>
> [Nesl] {a + 1: a in [2, 3, 4]};
> it = [3, 4, 5] : [int]
>
> [Nesl]
>
> --http://lispm.dyndns.org/


SETL is much older. As an aside the first certified Ada compiler (for
Ada 83) was written in SETL.

My little library can be loaded in a running CL, and can be used
without the readtable hacks.

Cheers
--
Marco

Reply With Quote
  #13  
Old 08-24-2008, 11:22 AM
DeverLite
Guest
 
Default Re: Listcomprehension-macro? Macros with args inside macro-name?

On Aug 22, 5:16*pm, defn noob <circularf...@yahoo.se> wrote:
> I am trying to learn lisp macros and I generally find
> listcomprehensions to be elegant and they dont exist in lisp.
> This has to be a macro right? Cant be a function?
>
> But how would I get started when it needs the arguments inside its
> name?
>
> In Python:
>
> >>> [x**2 for x in [12,31,2,33] if x > 20]

> [961, 1089]
>
> [expr loop &optional cond]
>
> Could I perhaps make a macro [ that triggers another macro?
>
> (defmacro [ ()
> * * ((let listcomp (read until next ])
> * * * (filter (cond) (mapcar expr loop)))


Nobody has yet mentioned the Lisp series package: http://series.sourceforge..net/.

I think this does what you're looking for... and a little bit more.
But I agree with the other comments: get more comfortable with lisp's
syntax and learn how to think in lisp before trying to make macro's
and change the syntax around.
Reply With Quote
  #14  
Old 09-16-2008, 04:48 AM
William James
Guest
 
Default Re: Listcomprehension-macro? Macros with args inside macro-name?

On Aug 22, 5:47 pm, David Golden <david.gol...@oceanfree.net> wrote:
> defn noob wrote:
> > I am trying to learn lisp macros and I generally find
> > listcomprehensions to be elegant and they dont exist in lisp.
> > This has to be a macro right? Cant be a function?

>
> You might want to look at the COLLECT macrohttp://user.it.uu.se/~svenolof/Collect/
>
> > [x**2 for x in [12,31,2,33] if x > 20]
> > [961, 1089]

>
> (collect list ((expt x 2)) (in x '(12 31 2 33)) (when (> x 20)))
> => (961 1089)


Ruby:
[12,31,2,33].select{|n| n>20}.map{|n| n**2}
==>[961, 1089]


Reply With Quote
  #15  
Old 09-16-2008, 04:50 AM
Pascal J. Bourguignon
Guest
 
Default Re: Listcomprehension-macro? Macros with args inside macro-name?

William James <w_a_x_man@yahoo.com> writes:

> On Aug 22, 5:47 pm, David Golden <david.gol...@oceanfree.net> wrote:
>> defn noob wrote:
>> > I am trying to learn lisp macros and I generally find
>> > listcomprehensions to be elegant and they dont exist in lisp.
>> > This has to be a macro right? Cant be a function?

>>
>> You might want to look at the COLLECT macrohttp://user.it.uu.se/~svenolof/Collect/
>>
>> > [x**2 for x in [12,31,2,33] if x > 20]
>> > [961, 1089]

>>
>> (collect list ((expt x 2)) (in x '(12 31 2 33)) (when (> x 20)))
>> => (961 1089)

>
> Ruby:
> [12,31,2,33].select{|n| n>20}.map{|n| n**2}
> ==>[961, 1089]



Ruby:
irb(main):009:0> x=33331 ; if (x == ( ( x / 3 ) * 3 )) then k else :bad end
:bad

Lisp:
C/USER[1]> (let ((x 33331)) (if (= x (* (/ x 3) 3)) k :bad))
:OK

Come back when your language know how to compute.

--
__Pascal Bourguignon__
Reply With Quote
  #16  
Old 09-16-2008, 02:57 PM
namekuseijin
Guest
 
Default Re: Listcomprehension-macro? Macros with args inside macro-name?

On Aug 22, 7:16*pm, defn noob <circularf...@yahoo.se> wrote:
> I am trying to learn lisp macros and I generally find
> listcomprehensions to be elegant and they dont exist in lisp.
> This has to be a macro right? Cant be a function?
>
> But how would I get started when it needs the arguments inside its
> name?
>
> In Python:
>
> >>> [x**2 for x in [12,31,2,33] if x > 20]

> [961, 1089]


I like my own Scheme idiom

(define (sqr n) (* n n))

((all sqr '(12 31 2 33) (lambda (x) (> x 20))) '() cons)

; could be macroized for getting rid of (lambda (x) (> x 20)) but is
pretty good and flexible already

;;;; given:

; fold list ls with initial result r and reducer f
(define (fold ls r f)
(if (null? ls) r
(fold (cdr ls) (f (car ls) r) f)))

; returns an iterator from from to to, optionally incremented by step
(define (range from to . step)
(let* ((step (if (null? step) 1 (car step)))
(inc (if (> from to)
(lambda (n) (- n step))
(lambda (n) (+ n step))))
(> (if (> from to) < >)))
(lambda (init f)
(let lp ((i from) (r init))
(if (> i to) r
(lp (inc i) (f i r)))))))

; very useful: filtered operation! Collects result of op if ?
(define (filtered ? op) (lambda (i r) (if (? i) (op i r) r)))

; fantastic idiom for comprehensions in Scheme!
; final is the final form of the collected items, like, all squared!
; in-range can be either a list or a (range from to) call
; given is the condition items in the list have to obey. Optional
(define (all final in-range . given)
(lambda (ini doit)
(let ((reducer (if (null? given)
(lambda (i r) (doit (final i) r))
(lambda (i r)
((filtered (car given) (lambda (i r) (doit
(final i) r)))
i r)))))
(if (procedure? in-range)
(in-range ini reducer)
(fold in-range ini reducer)))))

; exs:

((all (lambda (i) (* 2 i)) (range 1 10) odd?) '() cons)
;=> (18 14 10 6 2)

; non-filtered
((all sqr (range 1 10)) '() cons)
;=> (100 81 64 49 36 25 16 9 4 1)

; reverse
((all sqr (range 10 1)) '() cons)
;=> (1 4 9 16 25 36 49 64 81 100)

; prints 1 9 25
((all sqr '(1 2 3 4 5) odd?) #f (lambda (i r) (display i)(newline)r))
Reply With Quote
  #17  
Old 09-16-2008, 03:19 PM
joswig@corporate-world.lisp.de
Guest
 
Default Re: Listcomprehension-macro? Macros with args inside macro-name?

On Sep 16, 8:57*pm, namekuseijin <namekusei...@gmail.com> wrote:
> On Aug 22, 7:16*pm, defn noob <circularf...@yahoo.se> wrote:
>
> > I am trying to learn lisp macros and I generally find
> > listcomprehensions to be elegant and they dont exist in lisp.
> > This has to be a macro right? Cant be a function?

>
> > But how would I get started when it needs the arguments inside its
> > name?

>
> > In Python:

>
> > >>> [x**2 for x in [12,31,2,33] if x > 20]

> > [961, 1089]

>
> I like my own Scheme idiom
>
> (define (sqr n) (* n n))
>
> ((all sqr '(12 31 2 33) (lambda (x) (> x 20))) '() cons)
>
> ; could be macroized for getting rid of (lambda (x) (> x 20)) but is
> pretty good and flexible already
>
> ;;;; given:
>
> ; fold list ls with initial result r and reducer f
> (define (fold ls r f)
> * (if (null? ls) r
> * * * (fold (cdr ls) (f (car ls) r) f)))
>
> ; returns an iterator from from to to, optionally incremented by step
> (define (range from to . step)
> * (let* ((step (if (null? step) 1 (car step)))
> * * * * *(inc (if (> from to)
> * * * * * * * * *(lambda (n) (- n step))
> * * * * * * * * *(lambda (n) (+ n step))))
> * * * * (> (if (> from to) < >)))
> * * (lambda (init f)
> * * * (let lp ((i from) (r init))
> * * * * (if (> i to) r
> * * * * * * (lp (inc i) (f i r)))))))
>
> ; very useful: filtered operation! *Collects result of op if ?
> (define (filtered ? op) (lambda (i r) (if (? i) (op i r) r)))
>
> ; fantastic idiom for comprehensions in Scheme!
> ; final is the final form of the collected items, like, all squared!
> ; in-range can be either a list or a (range from to) call
> ; given is the condition items in the list have to obey. *Optional
> (define (all final in-range . given)
> * (lambda (ini doit)
> * * (let ((reducer (if (null? given)
> * * * * * * * * * * * *(lambda (i r) (doit (finali) r))
> * * * * * * * * * * * *(lambda (i r)
> * * * * * * * * * * * * *((filtered (car given)(lambda (i r) (doit
> (final i) r)))
> * * * * * * * * * * * * * i r)))))
> * * * (if (procedure? in-range)
> * * * * * (in-range ini reducer)
> * * * * * (fold in-range ini reducer)))))
>
> ; exs:
>
> ((all (lambda (i) (* 2 i)) (range 1 10) odd?) '() cons)
> ;=> (18 14 10 6 2)
>
> ; non-filtered
> ((all sqr (range 1 10)) '() cons)
> ;=> (100 81 64 49 36 25 16 9 4 1)
>
> ; reverse
> ((all sqr (range 10 1)) '() cons)
> ;=> (1 4 9 16 25 36 49 64 81 100)
>
> ; prints 1 9 25
> ((all sqr '(1 2 3 4 5) odd?) #f (lambda (i r) (display i)(newline)r))


That's nicely obfuscated write-only code implementing a strange custom
iteration construct
with the results in reverse order!



Reply With Quote
  #18  
Old 09-16-2008, 03:38 PM
namekuseijin
Guest
 
Default Re: Listcomprehension-macro? Macros with args inside macro-name?

On Sep 16, 4:19*pm, "jos...@corporate-world.lisp.de" <jos...@corporate-
world.lisp.de> wrote:
> On Sep 16, 8:57*pm, namekuseijin <namekusei...@gmail.com> wrote:
>
>
>
> > On Aug 22, 7:16*pm, defn noob <circularf...@yahoo.se> wrote:

>
> > > I am trying to learn lisp macros and I generally find
> > > listcomprehensions to be elegant and they dont exist in lisp.
> > > This has to be a macro right? Cant be a function?

>
> > > But how would I get started when it needs the arguments inside its
> > > name?

>
> > > In Python:

>
> > > >>> [x**2 for x in [12,31,2,33] if x > 20]
> > > [961, 1089]

>
> > I like my own Scheme idiom

>
> > (define (sqr n) (* n n))

>
> > ((all sqr '(12 31 2 33) (lambda (x) (> x 20))) '() cons)

>
> > ; could be macroized for getting rid of (lambda (x) (> x 20)) but is
> > pretty good and flexible already

>
> > ;;;; given:

>
> > ; fold list ls with initial result r and reducer f
> > (define (fold ls r f)
> > * (if (null? ls) r
> > * * * (fold (cdr ls) (f (car ls) r) f)))

>
> > ; returns an iterator from from to to, optionally incremented by step
> > (define (range from to . step)
> > * (let* ((step (if (null? step) 1 (car step)))
> > * * * * *(inc (if (> from to)
> > * * * * * * * * *(lambda (n) (- n step))
> > * * * * * * * * *(lambda (n) (+ n step))))
> > * * * * (> (if (> from to) < >)))
> > * * (lambda (init f)
> > * * * (let lp ((i from) (r init))
> > * * * * (if (> i to) r
> > * * * * * * (lp (inc i) (f i r)))))))

>
> > ; very useful: filtered operation! *Collects result of op if ?
> > (define (filtered ? op) (lambda (i r) (if (? i) (op i r) r)))

>
> > ; fantastic idiom for comprehensions in Scheme!
> > ; final is the final form of the collected items, like, all squared!
> > ; in-range can be either a list or a (range from to) call
> > ; given is the condition items in the list have to obey. *Optional
> > (define (all final in-range . given)
> > * (lambda (ini doit)
> > * * (let ((reducer (if (null? given)
> > * * * * * * * * * * * *(lambda (i r) (doit (final i) r))
> > * * * * * * * * * * * *(lambda (i r)
> > * * * * * * * * * * * * *((filtered (car given) (lambda (i r) (doit
> > (final i) r)))
> > * * * * * * * * * * * * * i r)))))
> > * * * (if (procedure? in-range)
> > * * * * * (in-range ini reducer)
> > * * * * * (fold in-range ini reducer)))))

>
> > ; exs:

>
> > ((all (lambda (i) (* 2 i)) (range 1 10) odd?) '() cons)
> > ;=> (18 14 10 6 2)

>
> > ; non-filtered
> > ((all sqr (range 1 10)) '() cons)
> > ;=> (100 81 64 49 36 25 16 9 4 1)

>
> > ; reverse
> > ((all sqr (range 10 1)) '() cons)
> > ;=> (1 4 9 16 25 36 49 64 81 100)

>
> > ; prints 1 9 25
> > ((all sqr '(1 2 3 4 5) odd?) #f (lambda (i r) (display i)(newline)r))

>
> That's nicely obfuscated write-only code implementing a strange custom
> iteration construct
> with the results in reverse order!


You can always do:
(reverse ((all sqr '(12 31 2 33) (lambda (x) (> x 20))) '() cons))

and it can be used in a multitude of ways, not simply to return a
list:
((all sqr '(12 31 2 33) (lambda (x) (> x 20))) 0 +)
((all sqr '(12 31 2 33) (lambda (x) (and (> x 20) (odd? x))) 1 *)

Order is not important in many applications.

I don't think it's write-only, nor obfuscated, but then again, I'm the
father of the child. :P I'm used to writing these from scratch when
I'm not with my personal libs around, so I guess they're not that
complicated...

The important thing to have in mind is that I wanted a fold without
lists, then I got range, which returns an iterator for the range.
Then all either uses range or fold depending on the in-range
ardument. all itself returns the iterator, so that you may apply the
operation and initializer you want. That's applicative programming at
its best, I guess...
Reply With Quote
  #19  
Old 09-16-2008, 03:56 PM
joswig@corporate-world.lisp.de
Guest
 
Default Re: Listcomprehension-macro? Macros with args inside macro-name?

On 16 Sep., 21:38, namekuseijin <namekusei...@gmail.com> wrote:
> On Sep 16, 4:19*pm, "jos...@corporate-world.lisp.de" <jos...@corporate-
>
>
>
> world.lisp.de> wrote:
> > On Sep 16, 8:57*pm, namekuseijin <namekusei...@gmail.com> wrote:

>
> > > On Aug 22, 7:16*pm, defn noob <circularf...@yahoo.se> wrote:

>
> > > > I am trying to learn lisp macros and I generally find
> > > > listcomprehensions to be elegant and they dont exist in lisp.
> > > > This has to be a macro right? Cant be a function?

>
> > > > But how would I get started when it needs the arguments inside its
> > > > name?

>
> > > > In Python:

>
> > > > >>> [x**2 for x in [12,31,2,33] if x > 20]
> > > > [961, 1089]

>
> > > I like my own Scheme idiom

>
> > > (define (sqr n) (* n n))

>
> > > ((all sqr '(12 31 2 33) (lambda (x) (> x 20))) '() cons)

>
> > > ; could be macroized for getting rid of (lambda (x) (> x 20)) but is
> > > pretty good and flexible already

>
> > > ;;;; given:

>
> > > ; fold list ls with initial result r and reducer f
> > > (define (fold ls r f)
> > > * (if (null? ls) r
> > > * * * (fold (cdr ls) (f (car ls) r) f)))

>
> > > ; returns an iterator from from to to, optionally incremented by step
> > > (define (range from to . step)
> > > * (let* ((step (if (null? step) 1 (car step)))
> > > * * * * *(inc (if (> from to)
> > > * * * * * * * * *(lambda (n) (- n step))
> > > * * * * * * * * *(lambda (n) (+ n step))))
> > > * * * * (> (if (> from to) < >)))
> > > * * (lambda (init f)
> > > * * * (let lp ((i from) (r init))
> > > * * * * (if (> i to) r
> > > * * * * * * (lp (inc i) (f i r)))))))

>
> > > ; very useful: filtered operation! *Collects result of op if ?
> > > (define (filtered ? op) (lambda (i r) (if (? i) (op i r) r)))

>
> > > ; fantastic idiom for comprehensions in Scheme!
> > > ; final is the final form of the collected items, like, all squared!
> > > ; in-range can be either a list or a (range from to) call
> > > ; given is the condition items in the list have to obey. *Optional
> > > (define (all final in-range . given)
> > > * (lambda (ini doit)
> > > * * (let ((reducer (if (null? given)
> > > * * * * * * * * * * * *(lambda (i r) (doit (final i) r))
> > > * * * * * * * * * * * *(lambda (i r)
> > > * * * * * * * * * * * * *((filtered (car given) (lambda (i r) (doit
> > > (final i) r)))
> > > * * * * * * * * * * * * * i r)))))
> > > * * * (if (procedure? in-range)
> > > * * * * * (in-range ini reducer)
> > > * * * * * (fold in-range ini reducer)))))

>
> > > ; exs:

>
> > > ((all (lambda (i) (* 2 i)) (range 1 10) odd?) '() cons)
> > > ;=> (18 14 10 6 2)

>
> > > ; non-filtered
> > > ((all sqr (range 1 10)) '() cons)
> > > ;=> (100 81 64 49 36 25 16 9 4 1)

>
> > > ; reverse
> > > ((all sqr (range 10 1)) '() cons)
> > > ;=> (1 4 9 16 25 36 49 64 81 100)

>
> > > ; prints 1 9 25
> > > ((all sqr '(1 2 3 4 5) odd?) #f (lambda (i r) (display i)(newline)r))

>
> > That's nicely obfuscated write-only code implementing a strange custom
> > iteration construct
> > with the results in reverse order!

>
> You can always do:
> (reverse ((all sqr '(12 31 2 33) (lambda (x) (> x 20))) '() cons))


Sure, if you return a list. But if I input (1 2 3) into some
machine squaring them, I expect (1 4 9) to come out.

Personally I either use small functional building blocks
which do one thing: remove, reverse, map, reduce and so on
or I use something that is declarative like LOOP.

So either:

(mapcar #'sqr (remove-if-not (lambda (x) (> x 20)) '(12 31 2 33)))

or

(loop for i in '(12 31 2 33)
when (> i 20) collect (sqr i))

>
> and it can be used in a multitude of ways, not simply to return a
> list:


That makes it worse. It should do one thing right or do
multiple things but be descriptive. From looking
at the forms I would never guess what it does.

> ((all sqr '(12 31 2 33) (lambda (x) (> x 20))) 0 +)
> ((all sqr '(12 31 2 33) (lambda (x) (and (> x 20) (odd? x))) 1 *)
>
> Order is not important in many applications.


Haha. Right, that's the Scheme way.
>
> I don't think it's write-only, nor obfuscated, but then again, I'm the
> father of the child. :P *I'm used to writing these from scratch when
> I'm not with my personal libs around, so I guess they're not that
> complicated...
>
> The important thing to have in mind is that I wanted a fold without
> lists, then I got range, which returns an iterator for the range.
> Then all either uses range or fold depending on the in-range
> ardument. *all itself returns the iterator, so that you may apply the
> operation and initializer you want. *That's applicative programming at
> its best, I guess...


I think its applicative programming how it should not be used:

* the user interface is confused and adhoc
* the code is debugger-resistent
* code using that is not self-descriptive
* there is no simple model behind it (say like streams in SICP)

You can make it worse, though. By rewriting it as a set of macros.



Reply With Quote
  #20  
Old 09-16-2008, 04:38 PM
namekuseijin
Guest
 
Default Re: Listcomprehension-macro? Macros with args inside macro-name?

On Sep 16, 4:56*pm, "jos...@corporate-world.lisp.de" <jos...@corporate-
world.lisp.de> wrote:
> On 16 Sep., 21:38, namekuseijin <namekusei...@gmail.com> wrote:
>
>
>
> > On Sep 16, 4:19*pm, "jos...@corporate-world.lisp.de" <jos...@corporate-

>
> > world.lisp.de> wrote:
> > > On Sep 16, 8:57*pm, namekuseijin <namekusei...@gmail.com> wrote:

>
> > > > On Aug 22, 7:16*pm, defn noob <circularf...@yahoo.se> wrote:

>
> > > > > I am trying to learn lisp macros and I generally find
> > > > > listcomprehensions to be elegant and they dont exist in lisp.
> > > > > This has to be a macro right? Cant be a function?

>
> > > > > But how would I get started when it needs the arguments inside its
> > > > > name?

>
> > > > > In Python:

>
> > > > > >>> [x**2 for x in [12,31,2,33] if x > 20]
> > > > > [961, 1089]

>
> > > > I like my own Scheme idiom

>
> > > > (define (sqr n) (* n n))

>
> > > > ((all sqr '(12 31 2 33) (lambda (x) (> x 20))) '() cons)

>
> > > > ; could be macroized for getting rid of (lambda (x) (> x 20)) but is
> > > > pretty good and flexible already

>
> > > > ;;;; given:

>
> > > > ; fold list ls with initial result r and reducer f
> > > > (define (fold ls r f)
> > > > * (if (null? ls) r
> > > > * * * (fold (cdr ls) (f (car ls) r) f)))

>
> > > > ; returns an iterator from from to to, optionally incremented by step
> > > > (define (range from to . step)
> > > > * (let* ((step (if (null? step) 1 (car step)))
> > > > * * * * *(inc (if (> from to)
> > > > * * * * * * * * *(lambda (n) (- n step))
> > > > * * * * * * * * *(lambda (n) (+ n step))))
> > > > * * * * (> (if (> from to) < >)))
> > > > * * (lambda (init f)
> > > > * * * (let lp ((i from) (r init))
> > > > * * * * (if (> i to) r
> > > > * * * * * * (lp (inc i) (f i r)))))))

>
> > > > ; very useful: filtered operation! *Collects result of op if ?
> > > > (define (filtered ? op) (lambda (i r) (if (? i) (op i r) r)))

>
> > > > ; fantastic idiom for comprehensions in Scheme!
> > > > ; final is the final form of the collected items, like, all squared!
> > > > ; in-range can be either a list or a (range from to) call
> > > > ; given is the condition items in the list have to obey. *Optional
> > > > (define (all final in-range . given)
> > > > * (lambda (ini doit)
> > > > * * (let ((reducer (if (null? given)
> > > > * * * * * * * * * * * *(lambda (i r) (doit (final i) r))
> > > > * * * * * * * * * * * *(lambda (i r)
> > > > * * * * * * * * * * * * *((filtered (car given) (lambda (i r) (doit
> > > > (final i) r)))
> > > > * * * * * * * * * * * * * i r)))))
> > > > * * * (if (procedure? in-range)
> > > > * * * * * (in-range ini reducer)
> > > > * * * * * (fold in-range ini reducer)))))

>
> > > > ; exs:

>
> > > > ((all (lambda (i) (* 2 i)) (range 1 10) odd?) '() cons)
> > > > ;=> (18 14 10 6 2)

>
> > > > ; non-filtered
> > > > ((all sqr (range 1 10)) '() cons)
> > > > ;=> (100 81 64 49 36 25 16 9 4 1)

>
> > > > ; reverse
> > > > ((all sqr (range 10 1)) '() cons)
> > > > ;=> (1 4 9 16 25 36 49 64 81 100)

>
> > > > ; prints 1 9 25
> > > > ((all sqr '(1 2 3 4 5) odd?) #f (lambda (i r) (display i)(newline)r))

>
> > > That's nicely obfuscated write-only code implementing a strange custom
> > > iteration construct
> > > with the results in reverse order!

>


> > You can always do:
> > (reverse ((all sqr '(12 31 2 33) (lambda (x) (> x 20))) '() cons))

>
> Sure, if you return a list.


That's what you're doing by '() cons at the end.

> But if I input (1 2 3) into some
> machine squaring them, I expect (1 4 9) to come out.


Right, it works in reverse order. You could probably do normal order
at the expense of a more complex implementation and reliance on
mutation.

My main purpose was eliminating slow list processing from my coding,
relying primarily on the iterator-building range. Thus, when I need
some specific order, I simply invert the terms to range. I range over
vectors and strings as well.

Though I also give small lists a chance by permitting them in the
input. Reversing the output list may be more efficient, since you're
likely filtering elements out.

> Personally I either use small functional building blocks
> which do one thing: remove, reverse, map, reduce and so on
> or I use something that is declarative like LOOP.
>
> So either:
>
> (mapcar #'sqr (remove-if-not (lambda (x) (> x 20)) '(12 31 2 33)))


In that small list argument, it's not evident, but mapping over large
sequences sucks. That's one of the reasons I decided for range.

> (loop for i in '(12 31 2 33) when (> i 20) collect (sqr i))


Then, what you do with the collected data? Run some function over it
to produce a final result, right?
((all sqr '(12 31 2 33) (lambda (x) (> x 20))) init function)

Done, without producing intermediary lists or anything. It's also
almost the same written size as the macroed code above.

> > and it can be used in a multitude of ways, not simply to return a
> > list:

>
> That makes it worse.


This coming from a CLisper!

> It should do one thing right or do
> multiple things but be descriptive.


ah, lack of keywords... no problem when the interface is always the
same: reducers are always of the form (lambda (i r) ...) where i is
the current item from the iterator, r the current result and reducer
itself produces the next result to be fed recursively.

> * the user interface is confused and adhoc


It's not adhoc, like I said above: all and range return an iterator
and receive 2 arguments -- an initial value for the reducer and the
reducer. That's all.

It's always (iterator init f) and it's result is always passed around
as the r argument and as the final value. It's the same as fold/
reduce, except for the lack of a sequence/list argument.

You can also freely ignore the result, though, and then you have a
simple imperative construct, like in the print example.

> * the code is debugger-resistent


There's nothing to debug there. It's perfect!

> * code using that is not self-descriptive


Hmm, perhaps you should break out of CL's loops and have a look at
more applicative programming?

> * there is no simple model behind it (say like streams in SICP)


It looks pretty simple and consistent to me.

> You can make it worse, though. By rewriting it as a set of macros.


Not rewriting a set of macros, but simply wrapping it behind a macro.
Like:
(all (sqr x) (x in (range 1 100)) (and (> x 20) (odd? x)))

Which would equaly return an iterator.

> From looking
> at the forms I would never guess what it does.


Probably you should give Scheme another chance.

> > ((all sqr '(12 31 2 33) (lambda (x) (> x 20))) 0 +)
> > ((all sqr '(12 31 2 33) (lambda (x) (and (> x 20) (odd? x))) 1 *)

>
> > Order is not important in many applications.

>
> Haha. Right, that's the Scheme way.


That's functional programming way.
Reply With Quote
Reply


Thread Tools
Display Modes


All times are GMT -5. The time now is 02:03 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.