7 ms·
Clojure by Example (2015)
- phrygian 5y agoNice short examples in simple language. Scrolling down does pollute the browser history though.
- didibus 5y ago> Clojure doesn't provide built-in function for exponential operation It does actually: (Math/pow 2 3) ;;=> 8
- mapgrep 5y ago“Math” here is short for “java.lang.Math” though. Technically that’s interop rather than Clojure per se. /pedantic
- Fellshard 5y agoIf you remove the Java SDK from Clojure's foundation, you're losing a lot of its power. The interop is part of that foundation.
- mapgrep 5y agoFor sure, but “Clojure doesn't provide built-in function for exponential operation” is still an objectively true assertion. If your point is that it’s wrong in spirit, I totally agree, and I think this is yet another example of the limits of this “cheat sheet” approach. If you’re coming from another language, the concept of easy, well integrated interop with a host language platform would be fairly foreign, so the importance of an available Java method, and the fact that such methods are frequently used as core parts of the language, would be totally lost on you.
- Fellshard 5y agoThink it might just be quibbling on the nature of 'built-in' at that point.
- mapgrep 5y agoWell yes hence the “/pedantic” tag. I was quibbling with someone who went out of their way to “correct” a true fact. Quibbling with quibbling if you will. Sort of like you’re doing. But hey they started it ;)
- didibus 5y agoI think for Math/ it's a bit more fuzzy, because it doesn't need to be aliased explicitly, it's always available to use as it is automatically imported as Math. And this is then consistent in ClojureScript as well.
- jffry 5y agoThe very next sentence of the article points out that you can leverage Clojure's interop to invoke Math.pow(), but that's still limited to casting its arguments down to java.lang.Double and suffering the limits therein If you instead used the library org.clojure/math.numeric-tower [1] you can get much more precise answers, for example # start a repl with an extra dep $ clj -Sdeps '{:deps {org.clojure/math.numeric-tower {:mvn/version "0.0.4"}}}' user=> (require 'clojure.math.numeric-tower) nil user=> (Math/pow 33 33) 1.2911004008776103E50 user=> (type *1) java.lang.Double user=> (clojure.math.numeric-tower/expt 33 33) 129110040087761027839616029934664535539337183380513N user=> (type *1) clojure.lang.BigInt [1] https://github.com/clojure/math.numeric-tower https://github.com/clojure/math.numeric-tower
- didibus 5y ago> The very next sentence of the article points out that you can leverage Clojure's interop to invoke Math.pow() Hum, ok, to my defense it's not the very next sentence, it's much later at the very end when talking about Method invocation, so I hadn't read that far. +1 for linking to the numeric tower though
- jffry 5y agoMy apologies. I searched for Math/pow, saw that the sentence there started with "Clojure doesn't", and missed that we were looking at two different parts of the document :)
- dig1 5y agoYou need to be familiar with Java types and differences between them (Integer, BigInteger) and how Math.pow() behaves with different types. This is more up to Java, rather than Clojure. No need to pull the library for this, Clojure already has (biginteger) for that: user=> (.pow (biginteger 33) 33) 129110040087761027839616029934664535539337183380513
- kazinator 5y agoDidn't Clojure use the N suffix for big integers at one point? I don't see one on that output.
- Oreb 5y ago`Math/pow` is not a function. If it were, you would be able to do things like this: (map (partial Math/pow 2) [0 1 2 3])
- dig1 5y ago"Math/pow" is actually a function on JVM level. Clojure functions are objects with special callable method. This will work: (map (partial #(Math/pow %1 %2) 2) [0 1 2 3])
- ilikehurdles 5y agoI love the content, but I hate when pages hijack my back button by placing page headings in my history as I scroll.
- amp108 5y ago> I don't like reading thick O'Reilly books when I start learning new programming languages. Rather, I like starting by writing small and dirty code. Virtually every O'Reilly book starts out with small (and sometimes dirty) code examples.
- mapgrep 5y agoLearning a new language by mapping constructs from another language you know better is certainly expedient. But the trade off is you short change yourself on learning core philosophical beliefs underpinning the design of the language. Understanding these poorly means you will not exploit the language very well and arguably should just stick with the prior language. Clojure more than most languages is built around some unconventional philosophical beliefs. So for example “reduce” becomes more than just another sequence function; in clojure it is an important way to build up a result in the absence of mutable variables (which in another language you could use to build up a result within an arbitrary type of loop). You really don’t get that from reading this cheat sheet. But if you took some time to read a slower introduction this will be made clear (“reduce” is prominent in Clojure for the Brave and True for example). Similarly recursion becomes much more important in clojure due this same constraint. As a lisp, clojure offers the opportunity to use macros, which come with tremendous power but also some important gotchas. You won’t get much here on when to use and not use macros, just a quick walkthrough of defmacro and friends. I could go on. Clojure’s powerful concurrency primitives, its a-la-carte approach to polymorphism and inheritance, its emphasis on plain maps — all these types of things warrant a deeper rethinking of how you solve programming problems which you’re not going to get by just diving in (rushing in really) to some coding. I’m not trying to knock this guide, it’s fine, but it does show the limits of the very approach it celebrates. It’s fine if you’re jumping from say python to ruby or Java to C# but Clojure would be near the bottom of the list of languages to learn this way.
- avtar 5y agoAre there any other resources that you'd recommend to people coming from languages like Python or JavaScript? I'm assuming 'Clojure for the Brave and True'?
- zdkl 5y agoI second the Brave and True book to get your feet wet and add this website to get a better grasp on where/what/how to use the different elements of Clojure, with examples. Especially the "see also" section which will point you to functions you may not have heard of otherwise. https://clojuredocs.org/ https://clojuredocs.org/
- blunte 5y agoThe language isn't what's difficult to grasp or what needs more explanation. What's missing is current complete examples with the library choices and configuration all worked out.
- jetti 5y agoI wholeheartedly agree. There are so many different ways to set up a project in Clojure that it can be a little overwhelming. There is boot, leiningen and deps.edn for managing dependencies as well as project structure. Then with ClojureScript there is shadow-cljs as well as improvements made with ClojureScript embracing the Javascript tooling by handing off the output of the compiler to a JS bundler.
- Folcon 5y agoI'm not sure if this is enough, but I wrote these [0][1] a while ago and if they're not to your taste, I do admit to a fairly offbeat writing style, there's also Luminus[2] and re-frame[3]. They may not be complete enough for your tastes? I definitely can sympathise with the ecosystem being complex to get into =)... Take Fathom which I walk through a small fraction of in [0] and [1], there's a lot there. It's being actively worked on and there's a lot of docs to go through. That said Clojure's communities are pretty friendly, you can get pretty far by just finding some example projects, tinkering with them and asking questions =)... - [0]: https://folcon.github.io/post/fulcro-basics/2020-05-12-Fulcro-via-re-frame/ https://folcon.github.io/post/fulcro-basics/2020-05-12-Fulcr... - [1]: https://folcon.github.io/post/fulcro-basics/2020-05-26-Sprinkling-in-some-server-side/ https://folcon.github.io/post/fulcro-basics/2020-05-26-Sprin... - [2]: https://luminusweb.com/docs/guestbook https://luminusweb.com/docs/guestbook - [3]: https://purelyfunctional.tv/guide/re-frame-building-blocks/ https://purelyfunctional.tv/guide/re-frame-building-blocks/
- jetti 5y agoThere are a few things I would like to see added as I have found them very useful in day to day work with Clojure(Script). cond-> and cond->> which takes an expression and then threads it through test/form pairs without short circuiting by stopping on the first test that returns true. I have used this a lot when conditionally adding to maps. Something like this: (let [base-map {:id "123"} name (function-that-could-return-nil) address (another-function-that-could-return-nil)] (cond-> base-map (some? name) (assoc :name name) (some? address) (assoc :address address))) If name and address are nil then I will still have the base-map. I also use some-> and some->> a lot as well. some-> and some->> operate similar to -> and ->> respectively but the difference is that there is a nil check before subsequent form. It will prevent nil results to keep being passed and can help alleviate NullPointerExceptions. As for maps, I recommend adding assoc-in, dissoc, update and update-in. assoc-in allows adding nesting to a map. I could do (assoc-in {} [:base :value] "test") which would result in a map that looks like {:base {:value "test"}}. dissoc removes a key from a map. update allows you to "update" a map by passing a key and function where the function has an argument that is the old argument. An example of that is (update {:name "James" :age 26} :age inc) which will increase the value of :age by 1. update-in allows you to do the same as update but in a nested structure
- fulafel 5y agoI see this kind of map update code usually written using merge, like this (ignoring DRY itch for now) (merge base-map (when name {:name name} (when address {:address address}) Or to avoid repeating field names, just form one map to be merged like {:name (function-that-may-return nil) :address (function-2)} and filter out nils from the map before merging that with-base-map. I guess with cond-> you have the advantage that you can do arbitrary map transformations, not just additions, so maybe this is just a case of nitpicking a strawman example - but doing only additions is a common case too.
- jetti 5y agoYea I used to do the merge and when as well. I'm not sure if there is an idiomatic way to do it but I personally prefer the threading style as it is "prettier".
- pjmlp 5y agoQuite good indeed.
- dang 5y agoOne past thread: Show HN: Clojure by Example - https://news.ycombinator.com/item?id=9692281 https://news.ycombinator.com/item?id=9692281 - June 2015 (35 comments)
- truth_seeker 5y agoThis is my way of learning too. I certainly dont have a patience to read the docs, official guide before i start. Just hacking directly through repl and getting to know primitive data types, constructs and most commonly needed APIs functions is the most practical way IMHO. Of most of the books written on clojure i really like "Living Clojure" by Carin Meier. Throughout this book, she will give you the feeling that she is sitting beside you and you pair programming with a senior clojure developer. She goes very elegantly into each topic through actual examples and necessary commentary. Highly recommend this book :- https://www.oreilly.com/library/view/living-clojure/9781491909270/ https://www.oreilly.com/library/view/living-clojure/97814919...
- missingstep1 5y agoAnother clojure tutorial is (*) by Mark Volkmann http://java.ociweb.com/mark/clojure/article.html http://java.ociweb.com/mark/clojure/article.html
- nisa 5y agoPersonally I've had great success working slowly with an open babashka repl through the tutorials from aphyr: https://aphyr.com/tags/Clojure-from-the-ground-up https://aphyr.com/tags/Clojure-from-the-ground-up - everything else didn't really stick for me, but I probably didn't invest enough time. Especially the first few articles helped a lot to clear up misconceptions for a newbie to lisp. I remember reading the linked article but it didn't worked for me.
- didibus 5y agoThe aphyr series I think is the best one for a quick intro to Clojure.