7 ms·
Problems with Lisp
- burke 18y agoIt's worth noting that Clojure has native support for hashes via the {} syntax. (http://clojure.org http://clojure.org)
- pmjordan 18y agoAnd hashtable lookups are possible by just function-calling the table itself with the key: => ({ :foo 1 :bar 2 } :foo) 1 the common pattern of defaulting to a value if the key isn't found is easy too: => ({ :foo 1 :bar 2 } :baz 4) 4 The above is a hash map, #{ ... } creates a hash set which otherwise has similar semantics. Sets, being function-callable, can be used directly for checking if something is one of a bunch of values: (if (#{301 302 303 307} response-code) ; we've been redirected Maps and sets (you also have sorted maps and sets and a compact struct-map, all of which have identical semantics as the hash variants where appropriate) can additionally be used with most functions accepting a seq (list) or can be converted to a list explicitly using the seq function. Basically, maps and sets really are first-class citizens in clojure. Some of the flexibility is down to the fact that Clojure is a Lisp-1: these features are therefore hard to replicate in CL. (and yes, hash tables also bothered me somewhat in CL, altough other things probably bothered me more)
- whacked_new 18y agoSomething I find strange about hashes in Clojure, is that you can access them using the key as a function. So instead of ({ :foo 1 :bar 2 } :foo) ;; => 1 You get the equivalent by doing (:foo { :foo 1 :bar 2 }) ;; => 1 For default values: (:baz { :foo 1 :bar 2 } 3) ;; => 3 I vaguely remember this is because keys act as functions, and hashes act as functions as well. Out of habit and similarity to other languages, I never use the key-first notation, nor can I see where it is better to use it.
- tokipin 18y agoit's likely for usage in higher-order functions. i haven't used clojure but i assume you can do something like this: (map :foo hashofhashes) which would get the element :foo of every hash in hashofhashes
- pmjordan 18y agoThat's another good point, although the alternative isn't much longer: (map #(% :foo) hashofhashes) or if % has a chance of being nil: (map #(get % :foo) hashofhashes)
- pmjordan 18y agoYep, the funcall semantics of symbols and keywords are to forward the symbol and key itself along with the arguments to the get function. I do sometimes use this notation, mostly when: - the map could be nil. (get nil :foo) and (:foo nil) will return nil, but (nil :foo) will throw an exception. - dealing with struct-maps, where the key can effectively be seen as an accessor function. (cf structs in CL) - (rarely) when the expression evaluating to the map is long and complex. A keyword in the function position (a) makes it clear that what follows must be a map or set and (b) you don't have to start counting parens.
- jrockway 18y agoClojure definitely has nice data structures. Does anyone do this sort of hash-table-as-function thing in Scheme?
- jrockway 18y agoMy article was actually a response to all of the "CL sucks, I'm switching to Clojure" articles I've read this week. While Clojure is certainly a good language, I think people are "switching" to it from CL due to hype, rather than their deep understanding of the problems with CL. Clojure gives you a few nice features, like immutable data structures, "nicer" reader syntax, and JVM compatibility. In exchange, you give up CLOS in favor of Java's broken object model. All I'm saying is that I don't think the popular community is really considering CL's advantages before switching, they are only considering the disadvantages. If you are going to consider disadvantages, it's important to keep in mind that Clojure has them too. (Another often-cited reason for switching to Clojure is Java's libraries. In my experience working with Java, its libraries are pretty bad. Read the URLConnection class that comes with Java 6. It is clear that the API designer has no idea what OOP is, and it's clear that those implementing the library had no idea how to program. CL libraries, I've found, are usually better-done.) But with that in mind, I really like Clojure. I have the occasional client that insists on JVM applications, and Clojure is significantly less painful than pure Java (or JRuby, or Scala). But it is not my first choice when the JVM is not a requirement.
- weavejester 18y agoClojure provides several ways of interfacing with Java's object model, but generally this is just for compatibility purposes. The equivalent to CLOS in Clojure would be multimethods and hierarchies.
- newt0311 18y agoThe problem is not the complexity of the api but how verbose it is. Having to type (setf (gethash "foo" *hash*) "OH HAI") just for something as trivial as "hash['foo'] = "OH HAI"" is really too much work and a significant disincentive to using hash tables.
- jimbokun 18y agoIn Arc that's (= (*hash* "foo") "OH HAI")
- KirinDave 18y agoAnd in PLT Scheme it's (hash-set! *hash* "foo" "OH HAI")
- KirinDave 18y agoSetf is the generic form (and it's pretty cool how setf works). There are more succinct ways of putting it. But you need to remember that functional languages discourage that kind of mutable state. It should be no surprise that some things (like assignment) are more awkward in that environment. It's a tradeoff.
- newt0311 18y agoYes but lisp is not a functional language and (to my incomplete knowledge of CL) setf is the only way to modify the hash table. Thus, people have to use that form if they want to use hash tables.
- pmjordan 18y agoIn fairness you could define a function that did it for you: (defun assoc (table key val) (setf (gethash key table) val) table) or something like that. (this is from memory, hope it's right) You can then let it take a variable number of arguments to make it even more concise. (yes, I've stolen the assoc semantics from Clojure, minus the pure functional aspect)
- Hexstream 18y agoTitle should be "Perceived problems with hash-tables in Common Lisp"... It's true that it would be interesting to have native syntax for hash-tables so you could read and dump them like you can lists and arrays and other stuff. Surprisingly the article doesn't even mention that which is the only real problem with CL's hashtables, aside from the inability to define arbitrary lookup mechanisms beyond eq, eql, equal and equalp...
- silentbicycle 18y agoHaving such a cumbersome syntax for hash tables is just as real a problem as the verbosity some Lisp programmers hold against e.g. Java. One solution could be a read macro that translates into the (setf (gethash ...)) form. Lisp read macros are usually prefix, though, and [key]hash is awkward. OTOH, adding suffix read macros (maybe only of the form symbol[... values], e.g. hash[# key] or hash[: key], with brackets and char(s) at the beginning to represent which suffix read macro. Or, making the hash a function: (hashname key) to get, (hashname key newval) to set.
- jrockway 18y ago> Title should be "Perceived problems with hash-tables in Common Lisp"... Good idea. Title changed :) I decided not to bring up the printed representation, since other languages don't do much better. Perl will print either the keys and values with no spaces between them (by default), or something like "5/8" in scalar context, or "HASH(0x123456)" if it's a reference. No better than CL, and nobody complains about this :)
- lgriffith 18y agoThe issue is that there is no one solution for all problems and all contexts. ANY given language was written in response to a given set of problems in a given set of contexts. Change one thing to be outside that domain and the fit is less good. Change almost everything and the fit is a misfit. For example: a 5 lb slege hammer is a very good tool for breaking rocks. Now fix a Rolex Watch with it. Its not so good of a tool, is it? The answer is understand the problem and its context. Then select the tool that fits good enough (YMMV). Otherwise you will soon find yourself in a world of hurt and still not have a good solution to your problem. I am sure Lisp has a problem set and a context set for which its a good match. Though I haven't found it yet but then I really haven't looked. The tools I use are good enough for the problems and contexts I have encountered in over 40 years of software development. Thus I have no reason to hammer my head against the rubber wall of Lisp as well as approximately 900 other languages.
- Retric 18y agoLisp is the best language for generating HTML, XML, writing compilers, or parsers. PS: Lisp is more a family of languages that share features than it is a specific language.
- chollida1 18y ago> , writing compilers, or parsers. I think the OCaml guys and the Haskell guys(Parsec) might take exception to this. See: http://flint.cs.yale.edu/cs421/case-for-ml.html http://flint.cs.yale.edu/cs421/case-for-ml.html http://www.ffconsultancy.com/ocaml/benefits/parsing.html http://www.ffconsultancy.com/ocaml/benefits/parsing.html It's not that CL is bad for writing compilers or parsers (I've written a few parsers using it), its just that blanket statements like "Lisp is the best language for ..." isn't always going to be true.
- Retric 18y agoSome things come down to personal preference, but I don't think OCaml's static type system is more useful than Lisp's approach for parsers / compilers. Granted if your building avionics then type safety is important, but in the more normal case it's just not that useful. Haskell is a pure functional language which is great for maintaining systems but I don't think it's a real benefit when writing them. If you want to write Lisp as a functional Language you can but when it's useful to break that mold you can. PS: There is probably a better language out there for this stuff, but I don't know of it.
- vikram 18y agoLisp has support for {} syntax for hashes. It's just not built in. Use a reader macro.
- gruseom 18y agonickb posted this article a couple of hours earlier: http://news.ycombinator.com/item?id=449240 http://news.ycombinator.com/item?id=449240 The duplicate wasn't detected even though the urls, after submission, are identical. It turns out there's a bug (a corner case, really) in how duplicates are detected. Probably nickb put this in the Submit field: http://blog.jrock.us/articles/Problems with Lisp.pod while jawngee used this: http://blog.jrock.us/articles/Problems%20with%20Lisp.pod If you resubmit with the first string you get taken to nickb's submission, while the second takes you to jawngee's. On another note, how many μStallmans of insensitivity would it take to notify pg of this triviality the day after the birth of his first child?
- scott_s 18y agoμStallmans? I love it. Your concept, or did you steal it?
- gruseom 18y agoAlan Kay famously said "Arrogance in computer science is measured in nanodijkstras." (http://www.youtube.com/watch?v=s7ROTJKkhuI http://www.youtube.com/watch?v=s7ROTJKkhuI). To which someone wittily answered, "And microkays".
- deleted 18y ago[deleted]