Hacker News new | past | comments | ask | show | jobs | submit login

Don't take it harsh, but if it takes all this for this simple theoretical problem, imagine for a real world problem. In my opinion, a pure iterative approach is really simpler:

(pseudo-code) :

<code> myset = {}

foreach c in mystring: if myset[c]: myset[c] += 1 else: myset[c] = 1

myset.sort(fn x,y: myset[x] < myset[y])

</code>

As I said, it's all about opinion (and I know there are million ways to simplify that or make it different, i.e. myset.get() or whatever), but I find the imperative approach way easier to gasp at first glance.

Compare that to:

(let [a (sort str) b (partition-by identity a) c (map (juxt first count) a)] (sort-by second > c))

First, I don't really like a,b,c as name variable (to be fair, myset and mystring are terrible too). Second, I find there are so many extra step to resolve this simple problem.. we need: partition-by, we need identity, we need juxt (wtf is juxt?). Third, wtf are first, count and second..?

I know high-level function are kewl, and working with lists are even cooler and using all of this in a 4 lines in a pretty clean way is again even cool-cooler. However, when I read this, even if there are less lines than the imperative way, it still takes more time to understand what the code is doing.




Sorry, but I think we'll have to agree that this just depends on background. I can figure out what the second is doing significantly quicker than the first.

When I think about this problem, my mind immediately thinks "well, I want to take all the characters, group them into buckets, one per letter, and then count how many are in each bucket." I don't think "I want to make an empty map, starting with each character mapping to zero, iterate over every character and increment an associated counter in the map, and then read out the counters at the end." If I have to write the second -- because my language has bad list libraries or no higher-order-functions -- I have to "translate" the first into the second in my head.

The Clojure code expresses the computation in exactly the same way it lives in my head. The imperative code expresses that like a computer does it, and to even understand it I have to "step through" it in my head a little bit to make sure the computer is doing the right thing.


I totally get this argument. I also think it's an old-dog-new-tricks problem more than anything else. Things like "foreach", "in", "myset[c]" are part of our existing vocabulary and things like "let", "partition-by", "identity", "map", "juxt" are not (and also, "wtf are first, count, and second..?" is pretty dramatic if you ask me - these are just what they sound like and not at all confusing). You have to learn a new vocabulary to be effective in these languages - maybe the size of the vocabulary is bigger, or the scope of each "word" is larger, but we deal with abstraction all the time; you have to trust that a method or a syntax feature does what the documentation says it does (or read the code for it yourself) regardless of the language.


well, you take more time because you are not used to it. It is a bit like Linq in C#, at first it looks very foreign but if you use it for a while you start replacing classical loops with this list based constructs. At the very least, it is a good way to get another perspective.




Consider applying for YC's Spring batch! Applications are open till Feb 11.

Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: