11 ms·
Try Clojure – An interactive tutorial in the browser
- shivekkhurana 5y agoslightly offtopic: My company (Meta Blocks), and my last company (Status) are hiring for Clojure roles. Please reach out to me if you are considering a switch.
- asicsp 5y agoLooks good. Is there a way to go back to previous step? Also, please use "Show HN" for own submissions like this project (see https://news.ycombinator.com/showhn.html https://news.ycombinator.com/showhn.html for details).
- elias94 5y agoTry (prev-step) in the REPL. Probably I need to add an help with some commands. Forgot Show HN. Now I cannot edit the title anymore
- agumonkey 5y agoQuite timely, someone was asking about newcomers troubles learning clojure and this will probably help a lot :)
- forlorn 5y agoDo I need to have a somewhat decent knowledge of Java to plunge into Clojure right away?
- Fellshard 5y agoMostly for understanding any stack traces you might see while running the code, I'd say. Other than that, you can use the bulk of the core language without needing a deep level of Java knowledge. Those bits of Java you may touch can be used as 'incantations' until you learn more.
- eyelidlessness 5y agoMostly only for interop, which unfortunately includes the language itself. Normal usage you shouldn’t have to care. But if you get internal stack traces you’re gonna be learning about the various Map implementations etc, all of which are defined in Java. Significantly easier to trace than machine code though!
- NightMKoder 5y agoJava the language? Very likely not. As proof - a majority of Clojure runs in JavaScript without any code changes (via ClojureScript). That said exceptions tend to look like Java classes, so you’ll definitely see Java bits. Java the JVM? You _probably_ don’t need to know it to get started, but you’ll have to get familiar with JVM deployment, dependency management, packaging, JVM memory settings, etc if you want to run something outside your dev machine. Getting to 90% here is pretty easy, but the last 10% (to me at least) tends to feel a lot more difficult that other languages. As a small pro-tip: use jstack. I wish every language came with a jstack. It just dumps the stack traces of all threads of a program by pid.
- eyelidlessness 5y agoMy experience with ClojureScript is you absolutely have to know the host environment because you will encounter type errors and the maintainers have negative interest in making them clear to users (as in flatly refused offers to contribute changes to make those errors easier to understand).
- futharkshill 5y agoThere is nothing worse than library or language maintainers who do not understand that "pure" error messages are absolute hell. If 99.99 % of the time a user should simply write x instead of y, the message should absolutely state that if possible.
- pmohun 5y agothis was a lot of fun. thanks for sharing!
- gengstrand 5y agoI started playing around with Clojure back in 2014 by implementing a rudimentary polyglot persistent news feed microservice. That microservice used Ring which sits on top of Jetty. I blogged about that implementation at https://glennengstrand.info/software/architecture/oss/clojure https://glennengstrand.info/software/architecture/oss/clojur... which is my personal blog. Last year, I re-evaluated Clojure with a feature identical microservice. This time, I integrated with Donkey which sits on top of Vert.x and https://glennengstrand.info/software/architecture/microservice/clojure/vertx https://glennengstrand.info/software/architecture/microservi... is where I blogged about that implementation. I put each of these implementations in a load test lab where I collect then analyze the performance data for comparison purposes. Those two blogs include the performance results. It is hard for Clojure to compete with other tech stacks, primarily because each method call in Clojure goes through Java reflection which is pretty slow. There is a way to prevent the use of Java reflection in Clojure but then the Clojure code doesn't end up looking very Lisp like. The usual advise is to use type hints very sparingly like in hot spots in the code. I still like Clojure, though.
- gleenn 5y agoClojure absolutely does not reflect on every call, and no it does require type hinting every argument to every function to get that speed. Especially after Clojure 1.8 came out, huge performance gains were had by inlining far more direct function calls. You can achieve near Java performance on most code, especially if you are okay sacrificing the immutable data structures and lazy sequences. I think this is what makes Clojure shine: you get a beautiful, functional, immutable, easy to understand world, and mostly it is extremely performant, and if it's not, you can have a few functions wrapping uglier but more performant bits, and Java interop is also extremely easy if you want to drop another level down. All the Java tooling for analyzing stack traces and bottlenecks works pretty well if you need to chase performance issues too. And my god it's going to be a lot faster than a lot of Ruby and Python etc apps. I say that with love as long term Rails programmer.
- thom 5y agoYou do still need to use type hints to achieve best performance, especially in numerical code. That said, even if I’m doing primitive math and using arrays in Clojure for performance sensitive code, it’s still a nicer experience than other JVM languages for me.
- Jeaye 5y agoFor the site author, thanks for this tool! Clojure has changed the way I program and I've been using it for 6 years now. Anything to help more people get into Clojure is much appreciated, especially if it's REPL-oriented. For some feedback, you might consider using Let's Encrypt for setting up free TLS certs, or hosting on Github Pages to get it automatically. With just HTTP, my browser (and many others) will show a scary warning telling me not to use the site.
- silcoon 5y agoThanks! https://tryclojure.org/ https://tryclojure.org/ is working correctly. I'm figuring out why Netlify is not redirecting automatically.
- dotancohen 5y agoFor the record, http:// http:// is redirecting to https:// https:// for me currently. $ date -u Tue 22 Feb 2022 09:12:56 UTC
- samatman 5y agoAre you certain that's not a client-side redirect a la Https Everywhere?
- dotancohen 5y agoI'm not using Https Everywhere, but just to check I tried with curl and get a 301 redirect: $ curl -v http://tryclojure.org/ 2>&1 | grep "HTTP\|location" > GET / HTTP/1.1 < HTTP/1.1 301 Moved Permanently < location: https://tryclojure.org/ I doubt that anything smart on the network is redirecting: $ dig a tryclojure.org tryclojure.org. 12 IN A 206.189.50.215 tryclojure.org. 12 IN A 18.192.76.182
- silcoon 5y agoNetlify took a bit to get the certificate but now is redirecting correctly! Thanks
- pjmlp 5y agoQuite nice tutorial, well done.
- simongray 5y agoAnother interactive tutorial for Clojure: https://www.maria.cloud/ https://www.maria.cloud/
- buzzwords 5y agoI would love to work with clojure. I thought there were opportunities for to work on a clojure project in my previous company. But I was told that no one likes to work on these products hence why they moving away from clojure and rewriting everything in java or scala. I wish I could tell you exactly why they hated it, I never got an answer. Speaking to some of the individuals, they thought it came down to tooling, no career benefits and some people really missed types.
- simongray 5y agoThe tooling is actually great, but kind of hard to discover if you're a beginner. The clojure.org website isn't very beginner-friendly, unfortunately. Types... I find most people missing static type checking are really reliant on a certain way of programming which isn't applicable to Clojure, e.g. write code, look for red squiggly lines, fix type signatures, compile, wait, fix the bugs the compiler tells you about. Clojure is much more exploratory in the way that you are always connected to a live system (like other Lisps) plus most of your functions are small and pure, making their logic self-contained and simple to deal with in isolation.
- yakshaving_jgt 5y ago> Types... I find most people missing static type checking are really reliant on a certain way of programming which isn't applicable to Clojure, e.g. write code, look for red squiggly lines, fix type signatures, compile, wait, fix the bugs the compiler tells you about. I use a repl in Haskell just as much as I used a repl in Clojure. The development experience is also somewhat similar if we're talking in terms of what you described here. In Clojure, you also fix the bugs the compiler tells you about, except the compiler in this case is one you partially implement yourself with a test suite. > plus most of your functions are small and pure, making their logic self-contained and simple to deal with in isolation. This is hardly exclusive to Clojure.
- simongray 5y agoMaybe I wasn't describing you then.
- jetti 5y agoI have been using Clojure professionally for the last 2.5 years, after doing 9 years of C#, and really enjoy it. I recently got a Windows laptop and was interested in ClojureCLR. It has a ways to go in terms of coming close to tooling of JVM and ClojureScript. David Miller has done an amazing job at keeping the project going and I hope I can give back to that community
- bumblebritches5 5y ago
- drikerf 5y agoThanks for making this. Hope it helps people discover the joy of Clojure :)! I've built my SaaS in Clojure and ClojureScript and really enjoy working with it every day since 2019!
- deleted 5y ago[deleted]
- klavik 5y agoAwesome job. I have also made another Clojure interactive tutorial which is more advanced, even showcases how to use React with ClojureScript. It is available in https://orgpad.com/s/clojure-tutorial https://orgpad.com/s/clojure-tutorial and I have made a video about it in https://youtu.be/lJxvKNjRdu8 https://youtu.be/lJxvKNjRdu8.
- silcoon 5y agoThanks mate, really good material!
- geokon 5y agoI was always wondering why something like this doesn't exist already! This is really great. Would it be possible to add `add-libs` from `tools.deps.alpha`? https://insideclojure.org/2018/05/04/add-lib/ https://insideclojure.org/2018/05/04/add-lib/ Then you could add libraries at runtime directly from the REPL You could then pair it with a pastbin and share/run code snippets (with some URL shortener). Could you imagine the possibilities for bug reports for instance? :D You could reproducibly demo bugs (well and features as well)
- klavik 5y agoCheck out https://klipse-embed.herokuapp.com/edit.php https://klipse-embed.herokuapp.com/edit.php.
- Borkdude 5y agoThis environment is running with SCI (https://github.com/babashka/sci https://github.com/babashka/sci) and only in the browser. What you describe might be more suitable for an environment like replit: https://replit.com/new/clojure https://replit.com/new/clojure. SCI can be combined with Reagent, etc for online tutorials as well, or to build web apps, like you can see here: https://babashka.org/scittle/ https://babashka.org/scittle/
- geokon 5y agoWhen it comes to specifically dynamically loading external libraries - is there a reason SCI can't incorporate `add-libs`? I mean clearly some libraries wouldn't load and will break (like if it's using Java code or something), but I imagine it could work for a large subset of code. I get there are a few ways to have a REPL in the browser, but it seems a bit primitive if you can't get any libraries in (short of copy pasting namespaces). I understand babashka includes some internally - so it makes it at least suitable for a subset of tasks. But I think this dynamic library loader is a more flexible solution (or I'm overlooking some technical hurdle here)
- Borkdude 5y agoIf you are running SCI on the JVM, then yes, it can do this, but this environment is running purely in your browser, no JVM back-end.
- activitypea 5y agoFuming because it wouldn't let me continue unless I typed "Hello, world!" without the comma. Jokes (?) aside, great job! I love that the input is an actual `input`, and not a `contenteditable`, big win for accessibility!
- globular-toast 5y agoLooks good but it absolutely needs matching paren highlighting. Having to count parens manually will put a lot of people off.
- hessammehr 5y ago=>(map inc) function(b){return function(){function c(k,t){t=a.g?a.g(t):a.call(null,t);return b.h?b.h(k,t):b.call(null,k,t)}function d(k){return b.g?b.g(k):b.call(null,k)}function e(){return b.s?b.s():b.call(null)}var f=null,g=function(){function k(w,u,B){var p=null;if(2<arguments.length){p=0;for(var I=Array(arguments.length-2);p<I.length;)I[p]=arguments[p+2],++p;p=new gc(I,0,null)}return t.call(this,w,u,p)}function t(w,u,B){u=hc.i(a,u,B);return b.h?b.h(w,u):b.call(null,w,u)}k.o=2;k.u= function(w){var u=r(w);w=v(w);var B=r(w);w=xe(w);return t(u,B,w)};k.j=t;return k}();f=function(k,t,w){switch(arguments.length){case 0:return e.call(this);case 1:return d.call(this,k);case 2:return c.call(this,k,t);default:var u=null;if(2<arguments.length){u=0;for(var B=Array(arguments.length-2);u<B.length;)B[u]=arguments[u+2],++u;u=new gc(B,0,null)}return g.j(k,t,u)}throw Error(\"Invalid arity: \"+arguments.length);};f.o=2;f.u=g.u;f.s=e;f.g=d;f.h=c;f.j=g.j;return f}()} The output is correct as far as I can tell but that's some pretty hairy Javascript right there. Edit: Formatted code.
- christophilus 5y agoI mean, peek under the covers at any minified code, and it’s a total mess. Minification tends to do that.
- ajdegol 5y agoclojurescript used to go through the Google Closure compiler, maybe it still does?
- tekacs 5y agoIt still does, yes, :)
- dgb23 5y agoThat's returning a transducer which is hairy implementation wise regardless of compilation.
- ltultraweight 5y agoTransducers are awesome! They are so elegant. If one is interested in transducers I liked Ben Sless's intro: https://bsless.github.io/transducers-intro/ https://bsless.github.io/transducers-intro/ or in video "workshop form" https://www.youtube.com/watch?v=1sC71eb9Ox0 https://www.youtube.com/watch?v=1sC71eb9Ox0
- gavinray 5y agoHow do people who write Clojure deal with lack of type checking? And auto-complete when it comes to Java library interop? I tried Clojure, to build a tool on top of a popular Java library that I was new to. And compared to other JVM languages it was not good because there was no type-checking or intellisense/autocomplete popups for the methods.
- dack 5y agoI've found "cider" for emacs to be a really good clojure IDE and repl. The workflow is a bit different from Java - I find that I am looking up documentation within my editor more often (which explains the arguments and return values), and then trying out little snippets locally using the extremely powerful repl. You slowly build up your program from smaller programs that you have tested to work, so by the time you run the whole thing, you only have a couple typos/issues. I think the other key to working with clojure is to set up your program as a set of transforms on simple data structures as much as possible such that complex class interactions aren't used much, and that cuts down on the need for great intellisense and static typing. Ymmv, of course, but I've found this way of working more productive than when I was working in Java.
- tharne 5y ago> How do people who write Clojure deal with lack of type checking? The short answer is that you don't. Rich Hickey, the creator of clojure, made the language *very* opinionated by design. And one of the strong options is that folks should be aiming for simplicity in their code, checking their code as they go along using the repl in real time. Dynamic typing makes it much easier to do this. Whether or not this is a good approach (I happen to like it) is up for debate (and likely a matter of taste too), however that's at least some of the rationale at a high-level. To really enjoy using clojure, you have to do things the way the language wants you to. If you try to bring your java style workflow into clojure, it's not going to be a lot of fun.
- simongray 5y ago> there was no type-checking (...) intellisense/autocomplete popups for the methods. First of all, yes there is. Maybe your editor didn't support it, but e.g. IntelliJ IDEA with the Cursive plugin does. Secondly: https://www.youtube.com/watch?v=aSEQfqNYNAc https://www.youtube.com/watch?v=aSEQfqNYNAc
- maicro 5y agoNot sure I "get" Clojure yet, but I appreciate the effort and will poke at it further. One piece of feedback - "Range of N" should clarify that "range" is generating N numbers starting at 0, so N won't actually be included ("0 to N exclusive"). I know this is fairly common for most programming languages, but "So (range 5) will return numbers from 0 to 5." is still ambiguous enough that I think it should be clarified. Also can't copy the text from the instructions or REPL (at least in Vivaldi on Windows 10). edit: I'm not a huge fan of the "multiples of 11" algorithm ("100" and "11" never actually show up in the expression...), so I ended up with this abomination which I think strongly reiterates that I don't get Clojure yet...: > (let [multiplier 11 limit 100] (map (fn [n] (if (> limit (* n multiplier)) (* n multiplier))) (range 1 (/ limit multiplier)))) (11 22 33 44 55 66 77 88 99) The conditional is probably not needed, but I was curious how they worked... Also glad that range accepts a float for the second value, as I forgot to wrap that in "int" (and "Math/round" didn't seem to work). And yeah, tested and this works just as well for at least the basic version: > (let [multiplier 11 limit 100] (map (fn [n] (* n multiplier)) (range 1 (/ limit multiplier))))
- tharne 5y agoFor those interested in Clojure in general, the Clojurians Slack is an amazing resource. Great community, and extremely helpful to folks getting started. https://clojurians.slack.com/ https://clojurians.slack.com/
- actuallyalys 5y agoPart of what makes it a helpful is that core team members, library developers, and other highly experienced Clojurists often jump in to answer questions. As a maintainer of some Clojure projects, I try to follow their example and give back.
- LandR 5y agoIT's worth knowing that this is you typing into a REPL, that when you are actually doign REPL driven development you almost never type directly into the REPL in Clojure. ALmost all editors I've seen allows you to send code to the REPL from your editor, and get the results in line in your editor. Typing into the REPL would be bad practice.
- iamcreasy 5y agoCan I use Clojure instead of Scheme when working through SICP?
- skyde 5y agoyou could but the more advanced part will not work. For example for some chapter SICP assume you can use code as data.
- kaliszad 5y agoMy colleague at OrgPad did an interactive Clojure tutorial utilizing Klipse https://github.com/viebel/klipse https://github.com/viebel/klipse by Yehonathan Sharvit @viebel embedded inside OrgPage cells. The OrgPage can be found here: https://orgpad.com/s/iByMMbKLBnq https://orgpad.com/s/iByMMbKLBnq and here is a commented walk through as a video: https://www.youtube.com/watch?v=lJxvKNjRdu8 https://www.youtube.com/watch?v=lJxvKNjRdu8
- JJseiko 5y agoThanks for this! I just finished the tutorial and really enjoyed it! Found myself hoping for more. Maybe a small series that would teach one the necessary basics of Clojure so one could actually do a real project in it afterwards. That would be awesome :)
- elias94 5y agoRead Clojure Distilled and try to complete all the Clojure Koans. 1. https://yogthos.net/ClojureDistilled.html https://yogthos.net/ClojureDistilled.html 2. http://clojurekoans.com/ http://clojurekoans.com/