8 ms·
Sounds like idiomatic Clojure has more in common with Python than it does with Java. I'm finding that to be true as I teach myself Clojure. My background is an
by pixelmonkey 13y ago
Sounds like idiomatic Clojure has more in common with Python than it does with Java. I'm finding that to be true as I teach myself Clojure. My background is an ex-advanced-Java programmer who left that all behind and has built production systems in Python for the last ~5 years. I'm learning Clojure now because the Java ecosystem is important to me, but I simply refuse to use Java to interact with it :)
Lightweight data modeling is important and Java is truly terrible at this. I illustrated this in a gist about creating and iterating over a list and a map, and contrasting that to the equivalent Python: https://gist.github.com/amontalenti/8114359 https://gist.github.com/amontalenti/8114359
The author says about Scala: "Due to its highly detailed static type system, Scala attracts the kind of programmers that like to carefully categorize and enumerate all the possible data structures."
It turns out, this describes expert Java programmers very well, too -- so it's no surprise that Scala is a very popular language with Java programmers. I'm finding that Clojure is the more attractive language if your sensitivities lean toward the "simplicity" and "dynamism" camp. I was reading some Scala code being used in production at Twitter and found this marvel: https://twitter.com/amontalenti/status/410977749629546496 https://twitter.com/amontalenti/status/410977749629546496 -- you would simply never see anything like this in Clojure or Python codebases.
The point about multi-paradigm is interesting. It's very true that Clojure, unlike Python, does not support true multi-paradigm. Then again, Python does not support "true" functional programming. It's close, but no cigar, due to the lack of full-featured lambdas / blocks. If you have to pick one paradigm, functional is definitely the simpler and more essential one.
Illustration: imagine a variant of Python that forced all code to live in classes -- ick. But imagine a variant of Python without classes -- that's not so bad.
It's worth reading about Clojure's take on object-orientation-atop-functional using multimethods and hierarchies: http://clojure.org/multimethods http://clojure.org/multimethods
- cbp 13y agoIf I understand that scala code correctly it's just enumerating a multiple arity function manually. It's not that uncommon to see that in clojure for performance reaasons, clojure.core has plenty of examples as does the java-written compiler. It's a lot faster to enumerate the common arities than to use apply like: (defn f [& args] (apply g args)) And it usually just takes a couple of strokes in any decent text editor anyway.
- jadyoyster 13y agoYou can however use macros to generate the fixed argument count versions; I don't know if Scala is able to do that.
- adrianm 13y agoGreat points all around. I'll add one thing to your point - multimethods are a fantastic example of how Clojure allows you to structure programs in functional way that takes a programming feature (in this case polymorphic method dispatch based on the arguments at runtime) to the nth degree. In Java and many other languages that have polymorphic method dispatch - the dispatch value is usually the type of the object for whom the method is being called on. Functional languages like Haskell take a much more powerful and expressive approach to this and extend it to matching the dispatch values for the called function on the type or pattern matched value of any argument. Multimethods are essentially Clojure's take on this in a dynamic language. They allow the programmer to define a function that constructs the dispatch value however it wants - usually from the arguments given as input, in any order, on any condition. To illustrate, I'll give an example I showed my wife yesterday. She's writing a roguelike game in ClojureScript at the moment that you can play in the browser - naturally she needed a way to represent the game world and the players position as they move around. So, for illustration I'll omit the code for the world state, but she needed to bind event listeners for the keyboard to properly dispatch the proper movement logic. So the code she wrote looked like this: https://gist.github.com/aamedina/8114944 https://gist.github.com/aamedina/8114944 She came to me with this code with the following problem - how do I think she should organize it? Clearly the handling logic is going to be more complex than a single line per direction (:up, :down, :left, :right) could handle, she has to account for terrain differences, buildings, monsters, what have you. So I suggested using multimethods to accomplish this. This is what the multimethod solution I cooked up would look like in this case. https://gist.github.com/aamedina/8114949 https://gist.github.com/aamedina/8114949 Now she has room in those multimethods to handle the potentially complex logic needed to make those arrow keys move the character properly. But another effect of this is that it hides the underlying state mutation from the implementation. Now your move functions are pure and isolated from the coords atom, in addition to the fact that multimethods made the logic more organized, at the expense of a few more lines of code. edit: moved code to gist
- lispm 13y agoA simple CASE statement would be better. It would replace a complex machinery plus lots of character-level syntax complication. A typical case where a more complex construct does not help much. Generic functions were introduced into Lisp, to replace a complex message sending mechanism with a more functional notation.
- deleted 13y ago[deleted]
- malbertife 13y agoActually that is Java, not Clojure.
- profdemarco 13y agoThat's part of Clojure's implementation in Java and the alternative would be to use reflection (obviously a terrible idea). There is similar code in the Scala implementation for dealing with functions, case classes and tuples. The only difference is that the Clojure implementation reflects that it's dynamically typed. I'd even bet there's similar code in CPython.
- lmm 13y ago> It turns out, this describes expert Java programmers very well, too -- so it's no surprise that Scala is a very popular language with Java programmers. I'm finding that Clojure is the more attractive language if your sensitivities lean toward the "simplicity" and "dynamism" camp. I was reading some Scala code being used in production at Twitter and found this marvel: https://twitter.com/amontalenti/status/410977749629546496 https://twitter.com/amontalenti/status/410977749629546496 -- you would simply never see anything like this in Clojure or Python codebases. Well done, you found some bad code written in Scala. I can assure you I've seen far worse in Python.
- Bahamut 13y agoOut of curiosity, is that piece of code necessary? Is there no better way to condense that? I'm a beginner with Scala, so I have no clue on that front.
- lmm 13y agoWell, that code exists at all for compatibility with tuples, which are a misfeature from the early days of scala. The "right" way to solve the problem is with shapeless' HLists. With HList you could write a simple generic method that would work with a HList of any length. (If you don't need to join a bunch of hetrogenously-typed futures while preserving all their type distinctions then you could just use the method that takes a Seq, above in the file) (You could also generate exactly this code with macros, which were a new feature in scala 2.10; I imagine a newer version of the code will do that)
- saryant 13y agoThere are some similar ugly workarounds of that nature in Play's JSON macros. Quite ugly but also transparent to anyone not writing library code.
- smrtinsert 13y agoI'm surprised you can't map over tuple members and join. Should be a one liner, but I'm a scala newbie though. Tupled were an unnecessary choice here. Pointing to this kind of stuff as an example of scala shows a complete misunderstanding of the language quite honestly.
- CCs 13y agoPython: https://gist.github.com/amontalenti/8114383 https://gist.github.com/amontalenti/8114383 Java: https://gist.github.com/amontalenti/8114359 https://gist.github.com/amontalenti/8114359 Scala: https://gist.github.com/csoma/8115672 https://gist.github.com/csoma/8115672 C++11: https://gist.github.com/csoma/8115693 https://gist.github.com/csoma/8115693
- pixelmonkey 13y agoThanks for this. I also put together a Clojure example based on a starting point someone else shared on Github. Clojure: https://gist.github.com/amontalenti/8117294 https://gist.github.com/amontalenti/8117294
- CCs 13y agoIt is interesting to see small implementations like these - you can get a feel for a language in seconds. https://gist.github.com/wting/77c9742fa1169179235f https://gist.github.com/wting/77c9742fa1169179235f
- mnbvcxza 13y agoI believe you could easily get the Scala version to be just as short, in terms of lines, as the Clojure version.