Live data from Hacker News

Clojure and the technology adoption curve

blog.juxt.pro

61–65 of 65 posts

Re: Clojure and the technology adoption curve

#61
post #51
post #37

Earlier quoted context omitted.

multi-methods at least are isa?-based. This implies that they obey ad-hoc hierarchies created via derive as well as traditional java inheritance hierarchies. protocols are little more than open-ended interfaces (i.e. I can extend them at run-time to my things and to other things).

Just a slight addendum: Clojure multimethods can resolve to a concrete method implementation based on any function of their parameters. So, in addition to single dispatch based on class (a la Java), you could also dispatch based on the classes of multiple parameters or on the value of the field 3 objects deep.

kinda. The dispatch is on a single value and isa? isn't mapped over that single value if it happens to be a collection. This means you can dispatch on multiple concrete values in a collection or the isa? hierarchies of a single thing, but you don't get to isa? everything in the collection (unless you do it yourself over some limited set of things you care about; like you said, method dispatch is over ANY function).

This means that you can do something like

    (defmulti cares-about-a-and-c 
      "multimethod that cares about the first and third args" 
      (fn [a b c] [a c]))
    
    (defmethod cares-about-a-and-c [:alpha :gamma]
      [a b c]
      (prn "got :alpha and :gamma"))
    
    (defmethod cares-about-a-and-c [1 3]
      [a b c]
      (prn "got 1 and 3"))
but the following won't really work how you want it to:

    (defmethod cares-about-a-and-c [String String]
      [a b c]
      (prn "Got two things that match (isa? String)"))

   
    (cares-about-a-and-c "foo" nil "bar") ;; doesn't call our last method
You could, however, define something based on class and not isa? via your dispatch function:

    (defmulti cares-about-class-of-a-and-c
      ""
      (fn [a b c] (mapv class [a c])))

    (defmethod cares-about-class-of-a-and-c [String String]
      [a _ c]
      (println "Got the strings: " a " and " c))

Re: Clojure and the technology adoption curve

#62
post #60

Earlier quoted context omitted.

The tradeoff you're referring to is summarized "Powerful but doesn't provide much." JavaScript comes to mind. This is not the case with Clojure. Most macros are basic and straightforward. Their power is, of course, unparalleled in other languages feature sets. With great power comes great responsibility, eh? And you don't have to use macros. Not that much is implemented in macros. I think you have some valid insights…

> Not that much is implemented in macros. And this is exactly what is wrong with Clojure and its community. An unexplainable lack of ability to embrace macros and all the power they can bring. I could never understand a single anti-macro argument, they are all too detached from the reality.

Is it really lack of ability to embrace, or a desire for simplicity of understanding? (which is also reflected in working with plain data structures in all kinds of libs). I think core.async is a great use of macros and suggests the Clojure community has ability to use it where it makes sense.

Re: Clojure and the technology adoption curve

#63
post #47

It is a myth that you have to be a genius programmer to pick up Lisp dialects like Clojure. I think it's the opposite: the cognitive load of more complex languages that are "easier to learn" than Clojure (like Scala or even Java itself, for instance), a complexity I consider accidental and not essential to whatever problem you are solving, is more difficult. The hard part of Clojure really boils down to one thing: yo…

For myself, there are a couple things that make Clojure difficult. I believe they all stem in part from the language being simple. First, there seems to be at least two ways to do things: the verbose way and the succinct way. This creates more things beginners have to memorize. Second, so many :keywords. Presumably some function/macro needed to be made more flexible and/or more succinct for certain circumstances so t…

Well I think you're absolutely right! There was a post not too long ago about creating "friendlier Clojure" that was all about addressing this problem. I find that I write the code first with pure "intellectual will" until all my tests pass. Then I go back and try to simplify, pull out functions into smaller functions and remove more complex logic.

As far as syntax highlighting is concerned, I find that using emacs helps a lot here. This is my `emacs.d` config.

https://github.com/nickbauman/emacs-dot-dee

This allows structural navigation for Clojure code. Good luck.

Re: Clojure and the technology adoption curve

#64
post #60

Earlier quoted context omitted.

> Not that much is implemented in macros. And this is exactly what is wrong with Clojure and its community. An unexplainable lack of ability to embrace macros and all the power they can bring. I could never understand a single anti-macro argument, they are all too detached from the reality.

Is it really lack of ability to embrace, or a desire for simplicity of understanding? (which is also reflected in working with plain data structures in all kinds of libs). I think core.async is a great use of macros and suggests the Clojure community has ability to use it where it makes sense.

Nothing can improve simplicity and readability more than macros. They make sense most of the time, almost always, not just in some edge cases.

Re: Clojure and the technology adoption curve

#65

Earlier quoted context omitted.

Traverse a hashmap, remove all strings with an even key string size and sort it by the last character in the string, then add the string size to the integer (here you have a list of integers) and sum the product of the numbers at index 0 and n-1, 1 and n-2, ... Compare the the code size in Java and Clojure. If that is not enough, do the same thing but start with java objects (and their clojure equivalent: a hashmap)…

I'd love to see some example code for doing this. I'm trying to implement it in Kotlin and am curious how it would compare.

  (def mymap {"asd" 1 "qwe" 2 "rtz" 3 "foo" 4 "bar" 5 "quz" 6 "bnm" 7})

  (let [ints (->> (filter (comp odd? count key)  mymap)
                                   (sort-by (comp int last first))
                                   (map (fn [[s i]]
                                          (+ (count s) i))))]
                     (reduce + 0 (map * ints (reverse ints))))
Gives me 341
Post reply on HN