(Clojure is simply my lisp of choice. This could be just as easily implemented in elisp, which does not have this built in.)
[edit] For those interested, here's an elisp version: https://gist.github.com/4430934
But everyone should get an opportunity to see what you can do with things like macros, how useful list comprehensions are in general, and how a homoiconic language can make the simple things slightly less intuitive but the hard things vastly more tractable. I certainly have no business in detracting from your enjoyment of Clojure, so please don't allow me to.
Instead of being snarky may I offer some constructive criticism:
1) You don't mention the Clojure `for` special form, which is a built in list comprehension. 2) There's a significant amount baked into Clojure's `for` special form. How does it compare to your macro? After reviewing the macro again I think you'll find there's some differing behaviors over when members of seqs are realized and bound between your implementation and that in clojure.core. 3) I think reflecting on what the real power here is: that you are able to dictate the hows and whys of evaluation at what time, and discussing that matter, can make more salient the power of LISPs.
Please do continue to enjoy what you are building and what you learn, and don't let the jaded musings of crotchety old men like me get in your way!
Having said that, there is probably some educational value in writing out what a special form would look like if it was not a special form, so in that regard, yes, this is interesting to look at.
No, not really:
http://stackoverflow.com/questions/310426/list-comprehension...
[(1..6),(4..6),(7..9)].comprehension { |a, b, c| a + b + c if a % 2 == 0 }
And if you go to extremes like https://gist.github.com/3356675 you can use Haskell-like syntax: [a + b | a <- ['n','p'..'t'], b <- %w[a i u e o]]
Ruby's blocks and method_missing are very powerful.However like the Ruby example this only works on a single list. Which reminds me that I keep meaning to write a port of CL loop in Perl using Devel::Declare.
ref: https://metacpan.org/module/List::Maker | https://metacpan.org/module/List::Gen | https://metacpan.org/module/Devel::Declare
First of all - ''this'' is NOT list comprehensions. Lisp has list comprehension, the sub-set of features that makes macros possible. Quote, back-quote, comma and grouping with parenthesis are parts of Lisp syntax to do it.
This is a meaningless generalization from a lisp programmer's perspective, just another macro.
Look at it carefully. This is the how confusion looks like. Thinking in terms of classes and methods prompts them to create artificial, unnecessary complications.
This is not hacking, this is exactly opposite.)
Notice how the blog didn't even mention Java once and is talking about Clojure and defmacro, still you managed to imagine the article, an argument and respond to it. What more, your response is on the lines of "The earth goes around the sun" -> "Hah. No".
> First of all - ''this'' is NOT list comprehensions
This is list comprehension as in the accepted definition of list comprehension.
> Lisp has list comprehension, the sub-set of features that makes macros possible. Quote, back-quote, comma and grouping with parenthesis are parts of Lisp syntax to do it.
List comprehension doesn't mean whatever you want it to mean.
http://en.wikipedia.org/wiki/List_comprehension#Common_Lisp
> Look at it carefully. This is the how confusion looks like.
Look at this comment carefully. If you ever wondered how empty vessels make most noise, this is how it looks like. Without pointing out anything in the article which is wrong or can be improved, or without even giving out unrelated examples(that would have been something), this comment has shit all over it over some delusional sense of lisp programmers superior to Java programmers. It might have been a bit acceptable if the comment would have posted a clever lisp solution, or the blog would have had anything to do with Java at all.
> Thinking in terms of classes and methods prompts them to create artificial, unnecessary complications.
And again, imagine arguments and respond to them. Where on earth TFA mentioned classes and methods?
Also, this fucking hippy culture of "classes suck; functional programming rockz; lolz" need to die. What makes it more irritating is 99.999% of the times, the person singing the praises of lisp, functional programming et al. and trashing Java(there is a very high correlation) is a fucking moron and can't code to save his life, in lisp or any other language. Do a 100,000 lines project in Haskell, come back and then tell me how classes suck and this functional programming project of yours is so much better. Even then, that will be just personal anecdote, but currently, it's just incoherent, incompetent rambling.
(define a 1)
`(1 ,a) ; this construction satisfies the definition of list comprehension
Everything else follows.Next time try to add pointers to Assembly language.
They're syntactic sugar for map and filter. Consider this python code:
[x**2 for x in range(100) if x % 2 == 1]
This is a list comprehension. It's equivalent (in 2.x) to the Python map(lambda x: x**2, filter(lambda x: x%2 == 1, range(100)))
(or in Clojure, (map #(* % %) (filter #(= 1 (mod % 2)) (range 100)))
(seems like cheating to use the odd? function))...so, equivalent to map and filter, just with better syntax.
Caveat: in 3.x, python's map and filter return generators, so the equivalent comprehension would be a generator comprehension instead--just the same thing as above but wrapped in parens and not square brackets--which would also return a generator.
This is the best I could come up with (in Emacs Lisp): https://gist.github.com/4356261 . It's rather hacky :D
Darius Bacon (abecedarius) came up with a beautiful alternative formulation that handles :while conditions seamlessly. Here's my port of his idea into Emacs Lisp: https://gist.github.com/4380866
I'd be very happy to see other versions :)
Eurgh, I hate the common Clojure habit (you see it in for, doseq, etc. loops, and in domonad, which is annoying in other ways) of abusing binding vectors to add in extra stuff that doesn't, in itself, have anything to do with binding names to values.
If you use a very slightly modified version of the macro defined at [1] (modified to use algo.monads), you can do list comprehensions like this:
> (monads/with-monad
monads/sequence-m
(mdo x <- [1 2 3]
y <- [3 4 5]
let added = (+ x y)
(monads/m-result [x y added])))
([1 3 4] [1 4 5] [1 5 6] [2 3 5] [2 4 6] [2 5 7] [3 3 6] [3 4 7] [3 5 8])
The "let added = (+ x y)" is an unnecessary flourish: it would have worked just as well to wrap what followed in (let [added (+ x y)] ...). Likewise (as against domonad), you can just use regular old if; no need for :if.1: https://bitbucket.org/kenko/macroparser/src/7a492ef941db38db...
I'm not familiar with the Clojure examples you mention, but it's interesting that Common Lisp provides directives like &rest for similar purposes.
I'm looking forward to exploring your blog.
http://www.iro.umontreal.ca/~latendre/publications/listCompF...