4 ms·
I think the point was that author was able to create a syntax for summation that had approximately the same shape as the math notation. I don't think I would a
by dreish 17y ago
I think the point was that author was able to create a syntax for summation that had approximately the same shape as the math notation.
I don't think I would argue that this is a very good example of macros (and yes, I wrote that before reading pg's comment ;), but solutions people have posted with other languages all have foreign symbols in them -- syntax for passing around blocks, or language-defined looping or list comprehension syntax, not ones they have chosen to suit their own needs. In this case, that's a virtue; you learn the language's syntax, and then you know how to recognize summation within any program in that language regardless of who wrote it, but in cases where the problem is more complicated and the native syntax for what you need to do more awkward, you really do want to create your own syntax.
Arguably that's a danger inherent in Lisp: it gives more opportunities to create needless new syntax, not just the kind of syntax that makes a program clearer and simpler.
If you wanted to extend destructuring in Python (that is, (a, b) = (1, 2)) to cover dictionaries, how would you do it? In a Lisp, it's done with macros. The core language usually doesn't start out with any destructuring at all. In Python, you can beg Guido and wait, or fork the project -- neither option is practical.
- tome 17y agoThat facility's already there. Any object is unpacked using its __iter__: >>> d = { 'key1': 'val1', 'key2': 'val2' } >>> (x,y) = d >>> (x,y) ('key2', 'key1') >>> (x,y) = d.items() >>> (x,y) (('key2', 'val2'), ('key1', 'val1')) >>> (x,y) = d.values() >>> (x,y) ('val2', 'val1')
- dreish 17y agoSorry, I should have given an example. I don't see how the above is ever likely to be useful, since the keys can be in any arbitrary order, but the fact that you can get something sequential out of a dictionary and revert back to tuple assignment is trivial. What I'd like to see you do in Python is this: >>> d = { 'key1': 'val1', 'key2': 'val2', 'key3': 'val3' } >>> { 'key1': x, 'key3': y } = d >>> (x,y) ('val1', 'val3') Nothing like this is built into the handful of special forms that Clojure starts out with, but roughly halfway through core.clj, it gets added to the language using the same macro facilities available to any Clojure programmer. If Python manages to be as powerful a language as Clojure without macros, you should have no trouble at all. user=> (def d {:key1 "val1", :key2 "val2", :key3 "val3"}) #'user/d user=> (let [{x :key1, y :key3} d] [x y]) ["val1" "val3"] (The order of key-value pairs is reversed to support :as, :or, and :keys, which let you do additional tricks while destructuring.)
- tome 17y agobut the fact that you can get something sequential out of a dictionary and revert back to tuple assignment is trivial. I disagree with this assertion. This functionality is not trivial and it wasn't in early Python versions -- certainly not before the introduction of __iter__! It's existence is testimony to the continuing evolution, and consistency of the Python language. Whether this is a good thing or not I suppose depends on your point of view. I imagine Lispers would see it as a black mark that we had to wait for Guido to implement it. Pythonistas on the other hand probably value the fact that it was well thought out and discussed via a PEP, and is universally implemented. Perhaps both are valid points of view. Your challenge is interesting because it's so easy to solve in Python that I can't imagine anyone except a Lisp programmer seeing anything in it to object to. In Python it is trivial to replicate the functionality albeit with a different syntax -- and syntax seems to be king for many Lisp fans. >>> def unpack(d, keys): ... return (d[key] for key in keys) ... >>> d = { 'key1': 'val1', 'key2': 'val2', 'key3': 'val3' } >>> >>> (x,y) = unpack(d, ['key1', 'key3']) >>> print (x,y) ('val1', 'val3') I like the Python version because I have to understand only two concepts to work out what's happening: Firstly there's a function call. Secondly the iterable result of the call is unpacked to a tuple. The merits of the Clojure version I'm not qualified to say, but is it really better in all regards than the Python equivalent? Even clarity, readability, comprehensibility?
- dreish 17y agoFirst of all, I certainly wasn't claiming that you couldn't look up more than one hash key on one line of code, using a function. My point is that you might reasonably want to extend the concept of destructuring further to cover dictionaries, and that macros allow you to extend the language in that way. Clarity, readability, and comprehensibility are three words that, in programming, mean pretty much the same thing as familiarity. To me, if I weren't looking at the definition of unpack, the above would look weird because I'd think of the Perl function unpack(), which does something very different. unpack(d, keys) above isn't something you'd even write in Clojure because it would be a synonym for (map d keys). Aside from that, it does seem very straightforward, if limited. Clojure does win on generality, because the Clojure version nests, covering sequential data structures at the same time: user=> (def d {:a {:a1 [1 2 3] :a2 4} :b 5}) #'user/d user=> (let [{{[_ _ x] :a1} :a, y :b} d] [x y]) [3 5] Hashes are the idiomatic general-purpose object in Clojure, so this sort of capability is actually useful in taking apart function arguments.