8 ms·
Clojure is the language where LISP clicked for me. Can't recommend it enough, it's got all of it - immutable datastructures, convenient data literals, simple an
by keymone 9y ago
Clojure is the language where LISP clicked for me. Can't recommend it enough, it's got all of it - immutable datastructures, convenient data literals, simple and composable concurrency primitives, very thin interface to host VM.
Just put enough effort to get beyond that "omg parenthesis" barrier and it will be a delight. It's like that Half-life joke: there are two kinds of people, those that finished Half-life many times and those that never got off the train (which as somebody will probably point out, is a variation on another joke, but you get the idea).
totally unaffiliated: https://www.braveclojure.com/clojure-for-the-brave-and-true/ https://www.braveclojure.com/clojure-for-the-brave-and-true/
- cle 9y agoI've learned to love the parentheses, because they embody what is so nice about lisps (and particularly Clojure)--inside the parentheses is a little nugget of functionality that generally stands on its own. No syntactic tricks, the only "trick" is the macro system, but it's so straightforward that I'm not sure I'd call it a "trick". The other immediate barrier is when Clojure barfs an ugly stack trace. I've heard that 1.9 will address that with core.spec, but I haven't explored it yet.
- agumonkey 9y agohmm sexy idea to have spec help for stacktrace. I expect something cute like elm error messages. About the parens, it's true it's one great thing, every construct has a value [1]. It's funny because You hear about object orientation where things are uncoupled and standalone yet the language isn't this way. Lisp has this, it's the incarnation of its own idea. But it looks silly if you're in it for the syntactic appeal. [1] Although I often wish for a helper thing when evaluating the body of, say a let to grab the bindings instead of saying "unknown var a in (inc a)". This is lisp in general
- DigitalJack 9y agostack traces still suck as far as I've seen on the 1.9 alpha branch. And while clojure spec is pretty neat, the barge-load of information it dumps on a spec failure is overwhelming. That said, the info it dumps is in the form of clojure data structures. In my own programs, I've added code to refine this output to something useable, but it's particular to my project and I don't think generally useful. There are other projects to aid in this fashion too. Expound is one that takes inspiration from Elm, and Inspectable is intended to help at the repl by launching a gui for exploring Specs and failures. I've tried both, but couldn't get inspectable to work in my environment, and expound isn't meant to handle the error I've been dealing with, so I can't speak to either.
- phyrex 9y agoExpound recently made my life a lot better by cutting through one of those ridiculous spec errors and telling me exactly what was wrong! I was really impressed.
- bbrinck 9y ago"expound isn't meant to handle the error I've been dealing with" If you have some time, would you be willing to expand on this? I'm curious to learn more about your error. I'm the author of Expound so I'd like to make it more useful (or, at least, understand the limits of a library like Expound).
- Nekorosu 9y agoClojure is more than Lisp and less than Lisp. I love it for the "more" part.
- deleted 9y ago[deleted]
- arximboldi 9y agoThere are many things to love in Clojure, like core.async, the lispyness, etc. But for me, their biggest breakthrough is with no doubt the data-structures. Clojure default of immutable hash maps and vectors was really bold. They had to innovate by giving a twist to Bagwell's great research on data-structures, and they managed to build what in my opinion are the first set of general data-structures suitable of representing traditional hierarchical object-tree data-models immutably, at the scale of large interactive software. Without these, the single-atom architecture that now is popular as ever with Redux, Elm, etc. would not be possible. The flourishing of functional programming for interactive software that followed shows to me that the biggest impediment before was not the lack of functional ways of expressing interactions (the Haskell people have devoted a lot of notable effort in the FRP camp). Instead, just having efficient data-structures to write persistent document models, escaping the rigidity of lists and rb-trees, allows you to write big interactive sofware in a functional manner even with the most dumb abstractions (which is a good thing, KISS!) and even stupid language (JavaScript!). This has inspired me to work on a generic implementation in C++, which also has experimental Python and Guile bindings: https://sinusoid.es/immer/ https://sinusoid.es/immer/ https://github.com/arximboldi/immer/ https://github.com/arximboldi/immer/ In the past I also did some other work on bringing Clojure Transducers to C++ (https://www.youtube.com/watch?v=vohGJjGxtJQ&t=1614s https://www.youtube.com/watch?v=vohGJjGxtJQ&t=1614s) but I know consider it a much less important effort---without the data-structures the other parts of Clojure feel almost like just sugar. EDIT1 -- Sorry for the shameless plug ;) EDIT2 -- Grammar
- tome 9y agoDo you know of a good resource for reading about their data-structures, especially anything Haskell doesn't have?
- DigitalJack 9y agoAny book on clojure and website too will go over them. They are fundamental to using clojure. I don't know enough about haskell to say what it does or doesn't have in relation to clojure. However, it's not simply the data structures, but how the language is built to interact with them from a programmers perspective. From a user interface to the language point of view, I find the ways of interacting with maps to be very nice. In particular the dual purpose of "keywords" to serve both as a good index/key in said hash maps, but also as callable look up function for the same key in a hash map leads to simplified code. This, coupled with the extremely high usage of those maps in typical clojure code, makes a big difference. To expand on that a little, "keywords" are symbols that begin with a colon, which I believe is the same as common lisp. :for :example :this :is :a :sentence :of :keywords. They are commonly used as the key in a map. Which has a literal syntax like (def map1 {:a 1 :b 2 :c "taco"}). To pull a value out, you can evaluate (:c map1) which will return "taco". They are hash maps based on work by Philip Bagwell, and I think a lot of languages have versions of this now. At least scheme and Common Lisp do. But I don't believe they have the nice literal syntax and interaction syntax. Many Lisp traditionalists are bothered by the use of curly braces for maps and square brackets for vectors, however I'm a fan. Without this bit of syntax, you have to add verbosity to the language to differentiate defining a map from doing a lookup, etc. For resources, Clojure for the Brave and True is pretty popular. Also the online community is quite friendly, although I have noticed some trends toward "the one true way" of doing things that puts me off a little.
- _t0du 9y agoI keep hearing this sentiment, moreso than I've ever seen for any other language. Once you "get into" Clojure, you're both A.) Extremely productive with it, and B.) in love with Clojure. How does it hold up for those of us that really love static typing and compilers?
- keymone 9y agothe static typing part - yeah, you just have to try and let go. there is typed.clojure for gradual typing though last time i checked it was quite slow. clojure.spec is a great attempt at bringing some discipline and provides quite a bit more than your usual typing system can do, though not entirely on compilation level. as for compiler part - you're in for a treat. clojure is a compiled language - everything compiles down to jvm bytecode. the surprise part is that due to homoiconicity you get a compiler that's happy to let you hook into particular pieces of your code and (since code is literally represented as usual clojure data structures - lists/maps/vectors/etc) modify it on the fly before compiling. you basically define `f(code) -> other_code` - the ultimate metaprogramming.
- christophilus 9y agoI love static typing. I really dislike almost every dynamic language I've ever worked with. But Clojure is currently my favorite language. I've done C#, F#, Go, JS, Ruby, Dart, C, C++, dabbled in Haskell, OCaml, purescript, D, Nim... (I like programming.) Anyway, once I dove into Clojure, I couldn't go back to any other language. I do wish it was more general purpose (not so slow to boot, had a decent native / non JVM, non JS target.)
- taylodl 9y agoYou should check out Ferret: http://ferret-lang.org http://ferret-lang.org. It compiles to C++11. I haven't tried it myself yet, so I don't know its limitations.