| Register | FAQ | Calendar | Search | Today's Posts | Mark Forums Read |
|
#1
| |||
| |||
| 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))) |
|
#2
| |||
| |||
| 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 macro http://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) vectors work too... (collect vector ((expt x 2)) (in x #(12 31 2 33)) (when (> x 20))) => #(961 1089) |
|
#3
| |||
| |||
| defn noob <circularfunc@yahoo.se> writes: > 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? Not sure exactly what a listcomphrehension is. But looking below, you need to be able to separate the syntactic concerns from the actual function or semantics of what you want to do. For new control structure, you generally want or need to use macros in lisp. Once you have the construct that you want, using standard lisp syntax, then you can worry about how to change the surface syntax. That will generally involve modifying the readtable and using reader macros. > 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] > >>> The standar way to do this in lisp would involve using one of the built-in macros, namely the loop or dolist construct: (loop for x in '(12 31 2 33) when (> x 20) collect (expt x 2)) (let ((result nil)) (dolist (x '(12 31 2 33) (nreverse result)) (when (> x 20) (push (expt x 2) result)))) Or alternatively, you could use one of the mapping constructs, but that is a bit trickier to manage the splicing since you don't necessarily want all values. (mapcan #'(lambda (x) (when (> x 20) (list (expt x 2)))) '(12 31 2 33)) So, it doesn't seem like you really need to add much of anything to the language. > [expr loop &optional cond] So, you could perhaps write a macro that takes the arguments that you specify. It might be more convenient to re-arrange the order perhaps, to take better advantage of the lambda list argument types. Remember not to get too hung up on the syntax of the language. You want to have an equivalent construct, even if it doesn't look the same. Otherwise why bother changing languages? > Could I perhaps make a macro [ that triggers another macro? > > (defmacro [ () > ((let listcomp (read until next ]) > (filter (cond) (mapcar expr loop))) -- Thomas A. Russ, USC/Information Sciences Institute |
|
#4
| |||
| |||
| defn noob <circularfunc@yahoo.se> writes: > 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? I'd recommend to abstain from trying to judge what's missing and what should be fixed on the language until you passed "noob" status. > In Python: > [x**2 for x in [12,31,2,33] if x > 20] Take a look at LOOP. > Could I perhaps make a macro [ that triggers another macro? > > (defmacro [ () > ((let listcomp (read until next ]) > (filter (cond) (mapcar expr loop))) This is syntactically so wrong that I suggest to spend some time actually learning the language before trying to extend it in non-trivial ways. I can recommend the book Practical Common Lisp which is even available online for free. -T. |
|
#5
| |||
| |||
| > (defmacro [ () > * * ((let listcomp (read until next ]) > * * * (filter (cond) (mapcar expr loop))) To do something like this, the thing you're looking for are reader macros. But beware, they are already quite advanced and far from normal macros... So maybe you should simplify your task for now and use a lispy syntax for your comprehensions instead of python syntax: (comprehend-or-whatever-name-you-choose (* x x) (for x '(12 31 2 33)) (if (> x 20))) But even this is quite difficult as there are a lot of cases to catch (with/without if/unless etc.), so you might as well find different quests for now =) I strongly recommend Graham's "On Lisp" (free download available on his website) for learning macros. Cheers, Benjamin |
|
#6
| |||
| |||
| 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? Yes, it has to be a macro, if you need it fast and if you want your own syntax, like used for list comprehensions in other languages like Haskell. A nice example is this one, which was presented at ILC2007: http://www.iro.umontreal.ca/~latendr...tCompFinal.pdf Maybe you should take a look at Liskell, too. Liskell is a new Lisp syntax frontend for Haskell, so I assume it implements list comprehensions and it might help to find a good Lisp-like syntax. -- Frank Buss, fb@frank-buss.de http://www.frank-buss.de, http://www.it4-systems.de |
|
#7
| |||
| |||
| In article <7fa79503-6d89-4dc0-bcac-12e327de7b66@m44g2000hsc.googlegroups.com>, Benjamin Teuber <beteub@web.de> wrote: > > (defmacro [ () > > * * ((let listcomp (read until next ]) > > * * * (filter (cond) (mapcar expr loop))) > > To do something like this, the thing you're looking for are reader > macros. But beware, they are already quite advanced and far from > normal macros... > So maybe you should simplify your task for now and use a lispy syntax > for your comprehensions instead of python syntax: > > (comprehend-or-whatever-name-you-choose (* x x) > (for x '(12 31 2 33)) > (if (> x 20))) > > But even this is quite difficult as there are a lot of cases to catch > (with/without if/unless etc.), so you might as well find different > quests for now =) > > I strongly recommend Graham's "On Lisp" (free download available on > his website) for learning macros. > > Cheers, > Benjamin Here is a very simple implementation (that I didn't write): (defmacro comp ((e &rest qs) l2) (if (null qs) `(cons ,e ,l2) (let ((q1 (car qs)) (q (cdr qs))) (if (not (eq (cadr q1) '<-)) `(if ,q1 (comp (,e . ,q) ,l2) ,l2) (let ((v (car q1)) (l1 (third q1)) (h (gensym "H-")) (us (gensym "US-")) (us1 (gensym "US1-"))) `(labels ((,h (,us) (if (null ,us) ,l2 (let ((,v (car ,us)) (,us1 (cdr ,us))) (comp (,e . ,q) (,h ,us1)))))) (,h ,l1))))))) (defun open-bracket (stream ch) (do ((l nil) (c (read stream t nil t) (read stream t nil t))) ((eq c '|]|) `(comp ,(reverse l) ())) (push c l))) (defun closing-bracket (stream ch) '|]|) (set-macro-character #\[ #'open-bracket) (set-macro-character #\] #'closing-bracket) Then you can write code like this: (let ((xs '(1 2 3 4 5 6 7 8))) [x (x <- xs) (oddp x)]) or this (with an ugly append, I know): (defun qsort (ax) (and ax (let ((a (car ax)) (x (cdr ax))) (append (qsort [y (y <- x) (< y a)]) (list a) (qsort [y (y <- x) (>= y a)]))))) Now, homework: how does the above macro work? -- http://lispm.dyndns.org/ |
|
#8
| |||
| |||
| On 2008-08-22 23:16:27 +0100, defn noob <circularfunc@yahoo.se> said: > 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))) Before reaching for lisp macro guru status, maybe you might want to consider a plain old function? (defun retain (pred transform list) (mapcan #'(lambda(x) (when (funcall pred x) (list (funcall transform x)))) list)) CL-USER 57 > (retain #'(lambda(x) (> x 20)) #'(lambda(x) (* x x)) '(12 31 2 33)) (961 1089) Macro-ising and getting rid of the five letter repeated noise left as an exrecise :-) -- JFB |
|
#9
| |||
| |||
| 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 |
|
#10
| |||
| |||
| 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 |
![]() |
| Thread Tools | |
| Display Modes | |
In an effort to better serve ads to our visitors, cookies are used on objectmix.com. For more information, check out our Privacy Policy.