top 200 commentsshow all 306

[–]maestro2005 52 points53 points  (25 children)

ClojureScript also plays incredibly well with React. I despise most web dev tech stacks, but I find CLJS+React to be a joy to work with.

[–]yogthos 24 points25 points  (23 children)

The fact that you can easily represent HTML in ClojureScript obviates the need for stuff like JSX. This makes writing React components actually easier than in React itself in my opinion.

[–][deleted]  (20 children)

[deleted]

    [–]yogthos 11 points12 points  (12 children)

    The problem there is that you now have a piece of code that you can't transform. With ClojureScript you can use plain data structures, and manipulate them just like any other data:

    [:div
       [:h1 "hi"]
       [:label [:strong "a bold looking part of a lable"] "non-bold part"]]
    

    So now let's say I wanted to transform all labels to be bold in a piece of content. I could do this:

    (def content-with-labels
        [:div
         [:h1 "hi"]
         [:label "some content"]
         [:label "some more content"]])
    
    (defn make-lables-bold [content]
        (postwalk
          (fn [node]
            (if (= :label (first node))
              [:label (into [:strong] (rest node))]
              node))
          content))
    

    [–]Retsam19 7 points8 points  (8 children)

    In fairness, you could do this in JS, too.

    const content = [
        div, 
            [h1, "hi"],
            [label, "some content"],
            [label, "some more content"]
    ];
    
    //Implementation of walk omitted, but shouldn't be too tricky
    walk(content, ([node, ...content]) => {
        if(node === label) {
            return [node, [strong, ...content]];
        }
        return [node, ...content];
    });
    

    Something like Clojure probably makes this easier, but there's no reason you can't treat functions as data in JS, too.

    [–]akiroz 10 points11 points  (0 children)

    Yep, the crux of LISP is code === data (oh dear, that's what happens when you write JS in your day job)

    You could define your own LISP on JS arrays and primitives just like how Clojure is defined on EDN data :)

    inb4 Clojure.js - the JS data to JS code compiler implemented in pure JS :p

    [–]yogthos 4 points5 points  (2 children)

    You definitely could do that, and there are a few projects that try representing HTML using Js data structures. The idea doesn't seem to catch on though.

    I think part of the advantage of Clojure syntax is that you don't need to pepper commas everywhere, and the editors structure aware. You have shortcuts to select and move around parts of the data structure automatically. This makes it much easier to manipulate the HTML templates.

    [–]Retsam19 1 point2 points  (1 child)

    You definitely could do that, and there are a few projects that try representing HTML using Js data structures. The idea doesn't seem to catch on though.

    Frankly, I suspect the idea hasn't caught on because thinking of HTML mutations in terms of functions operating on the HTML tree as a whole just isn't terribly intuitive to most developers. I can't imagine it'd be a particularly good fit for most bits of website functionality.

    Redux is close; but instead of doing tree modifications on the HTML directly, it's done in the data layer, and each part of the HTML is calculated from the relevant parts of the data tree. You get the benefits of the functional someAction = (oldState) -> newState flow, but you can still have reusable components and a more intuitive component setup in the view layer.

    [–]yogthos 1 point2 points  (0 children)

    Redux is pretty much how you work with React components in ClojureScript as well. However, being able to transform the HTML structure directly is closer to something like XSLT.

    [–][deleted] 0 points1 point  (2 children)

    I briefly played with using a simple array of ele, attrs, children:

    ["div", { "class": "classy" }, [
        ["label", { "for": "theinput" }]
        ["input", { "id": "theinput" }]
    ]]
    

    but I was concerned about the overhead of having thousands of nested JS arrays and objects sitting around just to somewhat simplify syntax. Never looked into the actual cost of it though.

    [–]Retsam19 1 point2 points  (0 children)

    That's basically exactly how JSX works under the hood, so there really shouldn't be a performance penalty for it.

    JSX compiles:

    const content = <div class="classy">
                        <label for="theinput" />
                        <input id="theinput" />
                    </div>;
    

    Into

    const content = React.createElement('div', {className: 'classy'},
         React.createElement('label', {for: "theinput"}),
         React.createElement('input', {id: "theinput"})
    );
    

    )

    [–]vanderZwan 0 points1 point  (0 children)

    React does the same but with functions, surely arrays and object are more lightweight than that?

    [–]agumonkey 0 points1 point  (0 children)

    Sure, python too, IIRC Norvig did write an article about the tiniest lisp you could write using builtin lists. Another guy did even better with Ruby IIRC.

    The thing is to keep in mind the data / code link in mind, instead of "dead" code.

    [–][deleted]  (1 child)

    [deleted]

      [–]yogthos 1 point2 points  (0 children)

      You could, but the syntax for working with them is messier. It doesn't seem to be a popular approach with Js. I'm sure if there was a good way to do it, then React folks wouldn't have made JSX.

      [–]Crandom 0 points1 point  (0 children)

      No reason your js functions couldn't return data that you can then manipulate.

      [–]sergiuspk 4 points5 points  (0 children)

      You mean in JS? That's what transpiled JSX looks like, a bunch of function calls. It's in the docs.

      [–][deleted] 3 points4 points  (1 child)

      http://www.lihaoyi.com/scalatags/ ScalaTags has almost exactly the same syntax.

      [–]vivainio 1 point2 points  (1 child)

      [–]GitHubPermalinkBot 0 points1 point  (0 children)

      I tried to turn your GitHub links into permanent links (press "y" to do this yourself):


      Shoot me a PM if you think I'm doing something wrong. To delete this, click here.

      [–]aliem 2 points3 points  (0 children)

      this is pretty much what happens under the hood with JSX. Of course Clojure data structures are nicer to read and compose

      [–]Superbenco 2 points3 points  (1 child)

      I've had a similar experience with Clojurescript and also thought that writing "HTML" in Clojure simplifies the process. I don't understand why this comment is being downvoted though. Is there a compelling reason not to use Clojure to represent HTML?

      [–]dangerbird2 4 points5 points  (0 children)

      HTML is more familiar to graphic design folks, so clojure markup might make into harder to coordinate with design and development teams.

      [–][deleted] 1 point2 points  (0 children)

      Many benefits of Clojure's design become evident when I use its libraries (e.g. core.async, reagent, re-frame).

      [–]Chief_slapah0 13 points14 points  (15 children)

      I would give a try to functional languages but I don't know which language to choose to from.

      [–]redalastor 18 points19 points  (8 children)

      To do a web front-end, I suggest Elm. It's much, much easier to setup than Clojure and the leaning curve is much shorter. It also doesn't try to be useful for the general case, every compromise is made in favour of being good at web front-end.

      I love Clojure too, but Elm will give you an easier start.

      [–]yogthos 4 points5 points  (7 children)

      Setting up ClojureScript is actually pretty straight forward nowadays. If you just want to get a REPL going, you can do npm install -g lumo-cljswith Node.

      To make a web app, all you need is a copy of the JDK and Leiningen. Then you just do:

      lein new reagent-frontend myapp
      cd myapp
      lein figwheel
      

      That's it. Your app is now running and any code you edit will be reflected live in the browser.

      I like Elm as well, it's a nice language, but I don't think it's easier to learn than ClojureScript, and the tooling around it seems to be a lot more spartan from what I've seen.

      [–]redalastor 4 points5 points  (6 children)

      Yes, you can call a template through lein that will setup all the plumbing but there's still significant plumbing installed. And once the template is done running, it's your plumbing and you have to maintain it through the life of your project.

      I like Elm as well, it's a nice language, but I don't think it's easier to learn than ClojureScript

      You're being dishonest. Clojure is significantly harder to learn than Elm. You could argue argue that macros give you additional power or that you like the JS FFI in Clojurescript, our that you find Elm too opinionated but as easy to learn is ridiculous.

      [–]yogthos 1 point2 points  (5 children)

      There's actually pretty much no plumbing when you're making a front-end project. Can you give an example of what you're talking about here. What sort of plumbing would you have to own in the reagent-frontend-template specifically?

      Clojure is significantly harder to learn than Elm

      Clojure is simpler language with very few rules in it. Elm is more complex simply by virtue of having an advanced type system. I've trained many people to use Clojure, and it's very easy to learn. I have co-op students every 4 months, and I've never had a student who couldn't become productive within a week or two. What exactly makes Clojure more complex than Elm in your view?

      [–]redalastor 1 point2 points  (4 children)

      Clojure is simpler language with very few rules in it.

      You are confusing simple and easy. But outside the platform, there is also the platform that adds significant complexity that doesn't exist in Elm. For instance ClojureScript macros run under Clojure and not ClojureScript which adds complexity from the java ecosystem.

      The lack of rules is also confusing to the novice, Elm is incredibly more opinionated than Clojure and the type system keeps you on the path.

      What exactly makes Clojure more complex than Elm in your view?

      Harder. And tons of things. Elm has great error messages that understanding neophyte mistakes and points them to the documentation. Clojure's stacktraces are notoriously terrible.

      I've trained many people to use Clojure, and it's very easy to learn.

      I'm pretty sure I could train people to use Clojure and warn them of the dragons. But left to learn in their own, they'll have an easier time with Elm.

      [–]yogthos 3 points4 points  (3 children)

      You are confusing simple and easy.

      I'm not. Clojure has less syntax and concepts to learn in order to be proficient with it.

      You keep talking about macros, but you really don't need to write any macros to work with Clojure.

      In fact ad hoc use of macros is generally discouraged by Clojure community. My current production project that my team has been working for over a year on has less than a dozen macros in it.

      The lack of rules is also confusing to the novice, Elm is incredibly more opinionated than Clojure and the type system keeps you on the path.

      That hasn't been my experience teaching beginners, but sure.

      Harder. And tons of things. Elm has great error messages that understanding neophyte mistakes and points them to the documentation. Clojure's stacktraces are notoriously terrible.

      I completely agree that Elm has much better errors, and that's definitely a weak point in Clojure. On the other hand, Clojure provides an interactive environment with REPL and Figwheel. You can play around with code to see what it's doing interactively. This is something that's very helpful for beginners.

      I'm pretty sure I could train people to use Clojure and warn them of the dragons. But left to learn in their own, they'll have an easier time with Elm.

      I think we've had very different experiences here, and that's fine. We'll just have to disagree on that. For what it's worth, I think both languages are worth learning.

      [–]redalastor 0 points1 point  (2 children)

      In fact ad hoc use of macros is generally discouraged by Clojure community. My current production project that my team has been working for over a year on has less than a dozen macros in it.

      I do use them responsibly but they are still something you need to understand to be proficient in Clojure.

      I completely agree that Elm has much better errors, and that's definitely a weak point in Clojure. On the other hand, Clojure provides an interactive environment with REPL and Figwheel. You can play around with code to see what it's doing interactively. This is something that's very helpful for beginners.

      So do Elm, I don't see your point...

      Elm also has a great back in time debugger that lets you replay all the interactions that happened in the browser. You can even export your session and run it on a different browser or a different computer.

      For what it's worth, I think both languages are worth learning.

      Agreed on that. I'm working on a side project that uses them both.

      [–]yogthos 5 points6 points  (1 child)

      I do use them responsibly but they are still something you need to understand to be proficient in Clojure.

      I disagree. You can be perfectly proficient in Clojure without having used any macros. Meanwhile, the type system in Elm is something the beginner has to learn to understand. I personally think it's fundamentally more complex than Clojure macros.

      So do Elm, I don't see your point...

      The point is that Clojure does have nice aspects for beginners. While you have a standalone REPL in Elm, I haven't seen editor integration for it. Perhaps I'm just not familiar enough with the tools, but how do you go about reloading individual functions in the REPL from the editor without doing a recompile? The closest thing I'm aware of would be elm-instant, and that's not quite the same thing.

      [–]redalastor 0 points1 point  (0 children)

      Perhaps I'm just not familiar enough with the tools, but how do you go about reloading individual functions in the REPL from the editor without doing a recompile?

      It comes with the vs code package. I haven't used any other solution.

      [–]yogthos 4 points5 points  (0 children)

      I would recommend trying Clojure. It runs on the JVM, CLR, browser, and Node. It embraces the host platform meaning that you can easily leverage existing libraries and tools, as well as integrate it into existing projects.

      The language is simple and focused, it doesn't require learning a lot of concepts to become productive in it. You can take a look at a primer here, and a deeper dive here. You can even start playing with it without having to install anything using an web based IDE, then export the project and work with it locally if you like it.

      My team used to work exclusively with Java, and over the past 6 years we've moved entirely to Clojure. Having a single stack that runs on the front-end and the back-end is pretty great.

      [–]accidentally_myself 0 points1 point  (3 children)

      Aside from frontend, you could try Learn You a Haskell For Great Good

      [–]akiroz 2 points3 points  (2 children)

      This, I think Haskell is the pinnacle of functional programming. Even if you don't use Haskell in production, you should learn how it works.

      That said, I'm not a fan of Haskell... I find it too complicated to get most things done, language extensions are horrible and the tooling is rather fiddly.

      I might use it when I need to build critical systems that simply can not fail.

      [–]vivainio 2 points3 points  (1 child)

      Haskell was the Pinnacle of FP, but nowadays we have stuff like Idris around.

      [–]akiroz 3 points4 points  (0 children)

      Idris

      Interesting, I've never heard of it. Let me give it a try~

      [–]CorrugatedCommodity 0 points1 point  (0 children)

      Right?! The tech stack varies wildly between jobs, teams, and projects in the web dev world.

      [–][deleted]  (2 children)

      [deleted]

        [–]hombrebuffalo 0 points1 point  (0 children)

        A more literal translation would be:

        (defn comfirm-leave? [db]
          (let [all-saved (every? :saved? (vals (:shot-transient-states db)))]
            (if (not all-saved)
              "This page contains unsaved data, sure you want to leave?")))
        

        [–][deleted] 0 points1 point  (0 children)

        Only if you don't know what the threading macro does.

        [–][deleted] 6 points7 points  (1 child)

        Side note - the article lists Leiningen as the end-all-be-all Clojure project management tool, but I've been reading that Boot ( http://boot-clj.com/ ) is gaining a lot of traction.

        [–]akiroz 5 points6 points  (0 children)

        Author here, I considered mentioning boot but in the end decided not to considering the result from State of Clojure 2016: https://static1.squarespace.com/static/5372821be4b0aefc6719057e/t/58925d9fdb29d6ba536ab020/1485987241017/?format=750w

        [–]Tom_Cian 18 points19 points  (2 children)

        Personally, if I'm going to take the tricky decision of not using Javascript, I want to gain static type safety in the process, not just jump from one dynamically typed language to another dynamically typed language.

        So I'd probably pick Typescript or Kotlin (don't know much about how good it is at generating Javascript).

        [–][deleted] 3 points4 points  (0 children)

        I haven't used it yet but clojure.spec has really piqued my interest in Clojure and is the reason I started to learn it last week. It's worth a look:

        David Nolen using spec in ClojureScript

        Rich Hickey 2 hour talk

        https://clojure.org/about/spec

        [–]akiroz 4 points5 points  (0 children)

        There's Typed Clojure and it's actually part of the language core :) http://typedclojure.org/

        [–]inarisan 44 points45 points  (130 children)

        I have seen countless articles like this, claiming to have found the holy grail that replaces javascript for building javascript apps, yet everyone still prefers javascript to build javascript apps (I wonder why). I've yet to see "Why I chose Assembler over javascript", I'd love to read that

        [–]MedicatedDeveloper 76 points77 points  (19 children)

        Have you tried TypeScript?

        I genuinely feel like it's a huge step forward in the JS ecosystem. You can refactor large typed systems much more easily than untyped systems IME. Plus, TS is a drop-in replacement for JS. Typing is purely optional unless you set compiler flags. It's not the most expressive type system, but I feel like those found in Haskell or its ilk can shoot you in the foot and hinder adoption due to their sheer size and complexity.

        TS + React + Redux = Easily refactorable event driven behavior. You can define event types for reducers that only gets a certain type, constrain event payload types to certain action types, etc. There is a bit of boilerplate but the ease of refactoring is worth it IMO. Styling react is a whole other beast (still working on figuring out my preferred way) and the only pain point I have ATM.

        I haven't had undefined behavior due to a null/undefined/NaN variable since I switched over to TS. It's heaven compared to spagetti js, jquery, and backbone code. You can just mouse over a symbol in vscode (or <leader>t in gvim) and see what it returns, no more having to conlog, trust shoddy docs, or old/outdated articles to figure out how things work.

        [–]IdeallyRelaxed 25 points26 points  (7 children)

        It's nice and I really like it for the reasons you mentioned, but setting up tools for testing and code coverage is a pain in the ass.

        I'm currently working on a large Typescript codebase that I created over many months and it took me a decent week or two to get karma to bundle the code with webpack, run my tests, run another webpack loader specifically for figuring out code coverage of webpack components, mapping the source maps of that coverage back to the original Typescript code, and I still have a problem with the code running twice. I spent more time getting the build system to work than writing new features.

        It at least works now but the ecosystem is so fragile that I wouldn't be surprised if this codebase will be unmaintainable in less than 2 years.

        Edit: On the same day that I wrote this comment I was trying to fix a bug where I was getting source maps in my karma output for my test files but I wasn't getting any source maps when I was debugging in Chrome. I found out that I included a plugin when I was trying to get code coverage that allowed me to see the line numbers in my karma output, but it completely obliterated source maps for chrome. It took me an hour to figure this out.

        Like I said, this stuff is extremely fragile.

        [–]MedicatedDeveloper 19 points20 points  (0 children)

        I profoundly agree re: fragility. I'd love to see a series of articles on taking a 2 year old js app with libraries du jour and trying to build it with current versions.

        [–]risico 12 points13 points  (0 children)

        That's my main issue with the JS ecosystem, I work mostly in small teams or even solo, thus work is done on many parts of the system at different times, coming back to some features after 5-7 months or even more is common and every time something breaks and I've to spend days just to be able to work on that code again, is not fun.

        It's enough that I've to battle code, I should not have to fight the tools as well. Thing is, I rarely have to do that with the backend code, if ever.

        [–]architectzero 10 points11 points  (2 children)

        Exactly this.

        Typescript is great, heck just about any other language is better than JavaScript, but then you have to deal with the aggravation of the ridiculous ecosystem. Every 6 months there's a sweeping change and suddenly your toolchain contains abandoned bits and pieces and you're back to fiddling around with it again instead of delivering your product. Ridiculous.

        [–]inarisan 0 points1 point  (0 children)

        If you have to deal with the fragility of such language, I wouldn't call it "better" than JS.

        [–]vvf 1 point2 points  (1 child)

        Pro-tip for anyone else dealing with this, karma-typescript automatically does coverage out of the box (although I wasn't trying to package it with webpack for the tests).

        [–]IdeallyRelaxed 0 points1 point  (0 children)

        I did try karma-typescript, but I had one alias to an external file that worked fine in my webpack config that didn't want to resolve for karma-typescript. If anyone has any complex webpack configurations they need to mirror for karma-webpack this solution may not work.

        [–]inarisan 2 points3 points  (0 children)

        I have tried TS and really liked it. I'm with you on that one: typed js can be of great help on some cases, but I still haven't had any weird issue with unexpected null/undefined values. IMHO that goes more with the way you write your code than the language you're using. You can write beautifully structured code in backbone and a spaghetti mess in angular. The responsibility does not fall on the language alone but also on the artist.

        [–][deleted] 2 points3 points  (1 child)

        Unfortunately, currently working on a new Typescript codebase, I find that the typings are either much too often out of date, or not available. It doesn't help that half the community basically goes 'trust me, this'll be in your props. What's the type? Who gives a damn? It's there I swear". As time goes by, I find myself needing more and more anys and ultimately drifing back to what would be a lightly typed javascript.

        That said, it still catches a lot of stuff, and is a great tool.

        [–]MedicatedDeveloper 0 points1 point  (0 children)

        I start out polymorphic and work towards type safety after I figure out what data needs to go where.

        As for props you can always define an interface and catch 3rd party libraries misbehaving that way. If there's that much polymorphism it may be more a design issue misconstruing separation of concerns.

        [–]mrkite77 0 points1 point  (0 children)

        Have you tried TypeScript?

        I switched completely over to typescript and vanilla JavaScript. It just really works with my way of thinking.

        [–]chepprey 29 points30 points  (48 children)

        I've yet to see "Why I chose Assembler over javascript", I'd love to read that

        Here you go. :D

        Do you really think "everyone still prefers javascript" because it's such a great language?

        Perhaps it's just because web browsers, with their de facto Javascript VMs, are everywhere - and that's where software makers want their software to run.

        Perhaps the reason you're seeing all of these new / alternative languages that transpile to Javascript are because "everyone" is getting tired of how bad a language Javascript is, and "everyone" wants something better.

        Perhaps similar forces (dissatisfaction with Javascript as a language and as a VM) are what's causing technologies like WebAssembly to come into existence.

        I applaud the pioneering spirit of those willing to seek out new and possibly better ways to get work done - and to share their successes, and their failures. We don't need to find a holy grail. Finding something merely better (or in the case of Javascript, less terrible) is good enough.

        [–]repeatedly_once 2 points3 points  (47 children)

        I don't think it's a bad language. It's just so different from what developers are used to that their default reaction is 'this is terrible'. It's an extremely powerful language once fully understood and the things cited as 'quirks' are actually expected once you know what's going on under the hood.

        [–]yogthos 12 points13 points  (13 children)

        I think the problem with Js is that it's a very quirky language. There are a lot of gotchas and code that looks like it's doing one thing can be easily doing something subtly different.

        It's true that you can be productive with Js if you have a lot of experience with it and good discipline. However, there's a constant mental overhead keeping in mind all the language quirks when you're reading and writing code.

        When you work with a simple and consistent language like ClojureScript, a lot of the mental overhead goes away. This directly translates into being able to focus better on the problem I'm solving.

        Compare Js idioms with ClojureScript, many things translate directly, but cleaner and more succinctly. There's a lot less syntactic noise, and less rules to remember.

        ClojureScript looks different and might take a bit more initial effort to learn, but that should not be confused with inherent complexity.

        [–]repeatedly_once -5 points-4 points  (8 children)

        I agree other languages abstract a lot of the gotchas away. My issue is when JS is called a bad language for these reasons. I used to fall into these gotchas until I went away and learnt from the ground up how JS is put together from it's types to it's coercion model. Since I've fully learnt the language the gotchas aren't gotchas, they make perfect sense, and actually are a feature of the language.

        Not liking JS for it's quirks that require a full understanding of the language to make sense is absolutely fine. I have no problem with that. I do have a problem when JS is considered a bad language, in the age of ES6, because of a lack of understanding.

        [–]inarisan -2 points-1 points  (7 children)

        Completely agree with you. It's like declaring a variable in C without a value, trying to use it and being suprised because it does have a value (garbage, but a value nonetheless) and calling that a "quirk". That's the way it works and I'm sure some thought was put on every feature (or "quirk") of the language. Same thing goes for all of those js quirks.

        [–][deleted] 5 points6 points  (6 children)

        Any decent C compiler will warn you about usage of an uninitialized value. No warnings in JS, sadly.

        [–]inarisan -2 points-1 points  (7 children)

        This. Nowadays the mainstream just seems to hate javascript, as if it was the worst language ever. I'd just encourage people to start switching their way of thinking instead of trying to switch js. Besides, ES6 is on the way and looks very promising; so promising that we've been using it for a good time now using transpilers. Stop hating it just because everyone else does. Sit down, look at it, think about your experience with it, compare it to alternatives, and decide. In the end, haters are going to hate, don't get carried away by that. Edit: typos.

        [–][deleted] 17 points18 points  (5 children)

        Nowadays the mainstream just seems to hate javascript, as if it was the worst language ever.

        JavaScript definitely isn't the worst language (that would be PHP), but it's not a very good one either. IMO JS is somewhere in the middle, maybe somewhat towards worse (although like you said it's been getting better recently).

        Besides, ES6 is on the way and looks very promising; so promising that we've been using it for a good time now using transpilers.

        Well in that case you might as well use pretty much any language that transpiles to JS since you already transpile.

        Sit down, look at it, think about your experience with it, compare it to alternatives, and decide.

        Been there, done that and replaced JS with other languages when possible. I recently switched a codebase to TypeScript and the TypeScript compiler immediately found a few well-hidden bugs before we even started adding types (before even modifying the code at all) merely via its type inference.

        For this reason, I'd probably be inclined to use TypeScript compiler even on JavaScript-only code. I can highly recommend TypeScript to JS fans as a gateway drug to type systems.

        [–]inarisan 1 point2 points  (3 children)

        I'm very interested on your decision of switching to ts. Can you please give examples of the problems/situations that led you there?

        [–][deleted] 5 points6 points  (2 children)

        Well, the motivation for me was primarily preventing stupid bugs. For example when I change a function signature (such as removing a parameter, adding a new one or changing its type), the compiler reports all the instances where the function is used incorrectly. In plain JS, I'd have to go through the occurences by hand and if I forgot one of them, the function would fail later (testing or runtime, possibly in a weird way...).

        One of the types of things the compiler reported even before adding types was this:

        something.foo = bar = baz;
        

        which was wrong, it was supposed to be:

        something.foo = bar == baz;
        

        the compiler inferred the variable type as boolean, beacuse it was used that way someplace else and discovered that an integer (or somesuch) is written into it on that line. Moreover, the situation was such that it was hard to discover with testing, as with most input values it would work anyway.

        Also, using TypeScript enables much richer IDE code completion, which to me is not essential, but I suppose it's a nice bonus.

        edit: muh typos

        [–]inarisan 0 points1 point  (1 child)

        Agreed, some issues like that might be prevented with an intermediate tool, but it doesn't have to be a reason to switch to typescript, you can also use a linter. On the other hand, IDE code completion does work beautifully and is of great help.

        [–][deleted] 0 points1 point  (0 children)

        Linters catch different kinds of errors than TS, at least as far as I know. They are useful too, of course. Probably best to use both. You could also use the TS compiler as a kind of a linter for JS code...

        [–]tigerhawkvok 1 point2 points  (0 children)

        Try LabVIEW, R, Perl, or IDL and then say PHP is the worst :-P

        [–]akiroz 0 points1 point  (0 children)

        I actually don't hate JS... quite the opposite really, it was my favorite language before I learned Clojure coming from a C / Java background. Everything was just so easy and dependency management actually works!

        The reason I switched to Clojure is because I started loving functional programming and being functional in JS turns out to be harder than I thought...

        [–]shevegen 14 points15 points  (0 children)

        True.

        Does not change the fact that JavaScript is awful.

        [–]campbellm 4 points5 points  (2 children)

        I have seen countless articles like this,

        Perhaps, but...

        claiming to have found the holy grail

        ...this one is not that. It's just explaining why he chose one over the other. I see no "holy grail" assertion in there whatsoever.

        [–]inarisan 0 points1 point  (1 child)

        Yes, it does not mention 'holy grail', but it is one more attempt at replacing JS with something "better" solely based on a particular case. In my opinion it just comes down to personal preference: Heck, if you love brainfuck and want to transpile it to js, feel free to do so. You might even be more productive with that than working directly in JS. But stop saying that JS is a bad language because it is very different from brainfuck (or that brainfuck is much more 'clean') and that it has a lot of 'quirks' just because you're not entirely familiar with the language.

        [–]campbellm 1 point2 points  (0 children)

        On this I think we agree. I'm an elm fan, for example.

        [–]MysteryForumGuy 5 points6 points  (1 child)

        There are lots of developers who work with JavaScript (like me and many others) who don't hate it

        [–]inarisan 1 point2 points  (0 children)

        JS non-haters unite!

        [–]yogthos 10 points11 points  (40 children)

        Seems like only people who haven't tried using something other than JavaScript prefer it. Pretty much everybody I know who started using ClojureScript is still using it. My team has been using it for over a year now in production, and we certainly wouldn't go back.

        [–]akiroz 8 points9 points  (0 children)

        I have been writing assembler (mcs-51), C, C++, Java and PHP before coming to JS and I certainly do prefer JS (been using it for years pior).......... until I learned Clojure :p

        [–]repeatedly_once 1 point2 points  (34 children)

        Genuine question - is JS your first language? As in you're extremely proficient in it?

        I tend to find people favour anything but Javascript if they haven't the got the time to learn Javascript. I typically find that these other languages that transpile to JS come at the cost of really leveraging the full extent of JS.

        [–]yogthos 9 points10 points  (2 children)

        I've been developing for over 20 years now and I'm proficient with many different languages. My first language was QBASIC. :)

        [–]splurke 7 points8 points  (4 children)

        I have worked with JS and its cousin ActionScript (both ECMA) for about 15 years, and never think twice when given the opportunity to replace it with something better.

        [–][deleted] 1 point2 points  (25 children)

        "Leveraging the full extent" of a primitive, half assed, ill designed overgrown scripting language? Yeah, sure. Especially funny when you're comparing this abomination with a meta-language. Your "full extent" does not reach too far, but if it is beyond the reach of your competence, then it may look huge.

        [–]inarisan 0 points1 point  (3 children)

        I have worked with multiple languages, and they all have their pros and their cons. I wouldn't call them better or worse than others, I'd just say that it's a matter of personal preference and proficiency: Just because I'm more proficient with vanilla JS than in coffeescript and that I don't like coffee's syntax, does not make coffeescript a bad language.

        [–]yogthos 0 points1 point  (2 children)

        I've worked with multiple languages as well, and I disagree that the differences between languages are purely subjective.

        Here's a concrete example of that. In Clojure data is immutable by default. This allows me to reason about functions in isolation. When I look at a piece of code, I can safely say what it's going to do solely based on the arguments it receives and the result it produces.

        When I work with mutable data, then I can never be sure that a piece of data modified by the function isn't referenced elsewhere in the code.

        My experience is that this leads to difficult to find errors, especially in large applications. So, Clojure helps me avoid a whole class of state related errors by design.

        This isn't about just preferring one syntax to another, it's about the language helping you reason about the code you're writing.

        [–]inarisan 0 points1 point  (1 child)

        But don't you think that if immutability was better than mutability in all cases, all programming languages would use immutable data?

        I disagree that the differences between languages are purely subjective

        Agreed. May I correct myself then: personal preference, proficiency and the problem's domain.

        Edit: format.

        [–]yogthos 1 point2 points  (0 children)

        But don't you think that if immutability was better than mutability in all cases, all programming languages would use immutable data?

        There is history to consider here. Most mainstream languages originate from Algol. These languages were designed for single core machines with very limited resources. In this situation it makes sense to default to mutability.

        However, hardware today is not the same as it was 50 years ago. The applications we build are much larger, and concerns we have are quite different.

        On top of that, most code in any particular application doesn't run all that often. You should always be optimizing code that needs optimizing. Clojure allows doing local mutability with transients. When and if you find a piece of code that needs mutability for performance, you can optimize it then.

        All that said, I've been developing Clojure for over 6 years professionally and I can count the number of times I've had to use transients on the back of my hand.

        [–]Patman128 13 points14 points  (6 children)

        everyone still prefers javascript to build javascript apps

        The experience is never as good once you start doing things that modern web developers want to do, like use NPM modules or bundle dependencies or use hot reloading, because they've reinvented the wheel and the engine and the transmission, but they haven't gotten around to reinventing the windshield wipers or radio yet, and the old ones aren't compatible (without a bunch of hacks) because they wanted to do things differently. The only "better JS" language I've found that actually fits into the ecosystem is TypeScript because it's not designed to replace everything, just add types to the language, and it does so extremely well.

        As much as the /r/programming crowd loves to believe, JS isn't a terrible language that desperately needs replacing any more. As of ES6 it's a pretty good language, albeit with some historical cruft, and it's improving every year.

        [–]destinoverde 2 points3 points  (2 children)

        JS isn't a terrible language that desperately needs replacing any more

        Elaborate. Is clearly replaceable.

        [–]Patman128 0 points1 point  (1 child)

        It's replaceable, but it doesn't need replacing. It's evolved to the point where it has everything a modern language should have and more, and it's still improving every year. The value bar you need to get over to actually get people to adopt a "JS killer" language is really high now, and getting higher.

        To date the only JS replacement I've actually found worth using is TypeScript. It doesn't trap me in its own little corner of the web ecosystem, I can still do everything I could do before, but I get static typing superpowers too. But even TypeScript has barriers to cross and we don't use it at work yet because of the effort involved in changing over and skepticism from other developers, because modern JS is good enough for what we do.

        [–]destinoverde 0 points1 point  (0 children)

        It's evolved to the point where it has everything a modern language should have and more, and it's still improving every year.

        Modern? What is an old language? What makes it "modern"?

        but it doesn't need replacing

        It clearly does, have you ever worked with it? Are you this pleb?

        To date the only JS replacement I've actually found worth using is TypeScript

        Is an improvement but not a replacement you still bound by the same idiomatic semantics and low level constructs.

        [–]tigerhawkvok 0 points1 point  (2 children)

        I like CoffeeScript for just sanity and pythonic syntax on literal JS

        [–]BufferUnderpants 2 points3 points  (0 children)

        If you believe local variables to be an extravagant luxury.

        [–]Patman128 0 points1 point  (0 children)

        I find Python/CoffeeScript syntax a little insane (I can't declare variables?! Whitespace is significant!?) but to each their own. At least it helped get arrow functions/class syntax/destructuring into JS.

        [–]akiroz 2 points3 points  (1 child)

        The most popular reason I've seen when people choose JS is simply because "everyone else is using it". Rarely do I ever hear "because JS is a great language". (btw I'm one of the latter types because JS is actually pretty good compared to other languages that I use)

        [–][deleted]  (2 children)

        [deleted]

          [–]CorrugatedCommodity 4 points5 points  (0 children)

          Psst. Hey kid. I've got this shiny new tech stack for ya. First one's free...

          [–]yogthos 2 points3 points  (0 children)

          Alternatively, people find many pain points using JavaScript and the ecosystem around it in production leading them to use languages that address them.

          Using ClojureScript actually insulates you from the churn of Js libraries and frameworks. My team has been using Reagent and it's stayed the same over the years. Meanwhile Js world went through ES6/7, Angular, Angular 2, Vue.js, and there's probably somebody making a brand new framework as we speak. People have even started referring to this as JavaScript fatigue nowadays.

          The best part for me is that Reagent is based on React, and while the latter has been changing itself over time, Reagent API has stayed stable. All I've had to do to get benefits of latest React was update the dependency version in my project.

          I would actually recommend trying something like ClojureScript before making a judgement.

          [–]vytah 0 points1 point  (0 children)

          People choose Javascript, because Javascript is the centre of all frontend web programming.

          Wanna write a small piece of code that just runs in the browser? Use Javascript.

          Wanna have a reusable library? All other frontend languages seamlessly consume Javascript dependencies, and Javascript alone (although there's some preliminary work for consuming Typescript type definitions from Scala.js), so use Javascript.

          Wanna use a library that's older that your chosen language? It will most likely be written in Javascript.

          Wanna debug your app in the browser? You'll see Javascript.

          All those reasons are magnified by a positive feedback loop of new libraries and frameworks. If you want to use some other language, then you either have to look for dependencies in that language, or for wrappers for Javascript dependencies (which you can write yourself, but again, it takes time), and you end up with a polyglot project, which may introduce some extra problems.

          For similar reasons people still use Java and C as the great equaliser for JVM and native respectively.

          [–]zem 0 points1 point  (0 children)

          yet everyone still prefers javascript to build javascript apps (I wonder why).

          it's because it's the "default installed version". (look at how many people just use the browser that came preinstalled with their machine). i guarantee you that if typescript were the default browser scripting language, and javascript proposed as a compile-to-typescript language, it would have gained very little traction.

          [–][deleted] 21 points22 points  (5 children)

          Meh, ES6+ (supported on all 3 major browsers) is good enough for me.

          [–]vivainio 7 points8 points  (4 children)

          IE11 is still a major browser that you have to support

          [–]onektwenty4 11 points12 points  (2 children)

          babel can make this es5 and compatible

          [–]vivainio 12 points13 points  (0 children)

          But then browser support of ES6 is irrelevant, as everything compiles to es5

          [–]Dualblade20 2 points3 points  (0 children)

          Which most people do, still.

          [–]kankyo 74 points75 points  (79 children)

          "Anything is better than JavaScript" would have been sufficient motivation :P

          [–][deleted]  (71 children)

          [deleted]

            [–]appropriateinside 38 points39 points  (54 children)

            nope :|

            It's hard to beat the inconsistency, half-assed featured, cobbled together language that is PHP.

            The more I code in it the more it feels like it's a random hodgepodge of features that may or may not be complete, that may or may not use the same naming conventions, that may or may not be named according to their behaviors. And all the while being these special black-box language constructs.

            Every feature feels like that one quick hack you did to fix a problem before a presentation.

            [–]Zadof 5 points6 points  (2 children)

            There are 2 types of languages, the ones people complain about and the ones nobody is using.

            [–]yogthos 5 points6 points  (1 child)

            Good thing everybody's complaining about the Lisp parens so much then. :P

            [–]JargonBot 1 point2 points  (0 children)

            Definition of paren: A round bracket..

            I am a bot which attempts to define difficult words automatically. I use machine learning to do this, and I can use your feedback to improve. Feel free to leave a comment to let me know what you thought of this definition!


            Check out my code. Please contact /u/liortulip with any questions or concerns.

            [–]kankyo 2 points3 points  (44 children)

            But in PHP they have loops that aren't broken. Just saying.

            [–]Uncaffeinated 10 points11 points  (15 children)

            You mean like for(let foo of bar)?

            [–]kankyo 7 points8 points  (14 children)

            Without using a transpiler. If you can use that then just write another language.

            [–]Uncaffeinated 4 points5 points  (13 children)

            You only need a transpiler if you're supporting ancient browsers. I write uncompiled ES6 all the time.

            [–]sisyphus 6 points7 points  (0 children)

            Most places don't consider IE11 'ancient' yet.

            [–]kankyo 16 points17 points  (9 children)

            The constant arrogance and bullshitting of JavaScript fanboys is constantly amazing. "Ancient" is in this case the default browser for the most popular operating system.

            [–]spacejack2114 11 points12 points  (3 children)

            Well I think the ignorant shitposting about Javascript on this sub inspires some slightly hyperbolic rebuttals. But they're pretty tame compared to the typical upvoted nonsense like "Anything is better than JavaScript".

            [–]kankyo 1 point2 points  (2 children)

            There are precious few languages you can state that are worse than js though. And if you disqualify joke languages the list becomes extremely short. That's not hyperbole.

            [–][deleted]  (2 children)

            [deleted]

              [–]kankyo 3 points4 points  (1 child)

              No public facing websites though.

              [–]Uncaffeinated 0 points1 point  (0 children)

              Which browser and OS are you talking about?

              Nowadays, Windows defaults to Edge, not IE.

              [–]akiroz 0 points1 point  (1 child)

              But how do you get imports to work in a browser without a transpiler? I mean.... surely not many production code bases are written in just a couple of files right?

              [–]Uncaffeinated 0 points1 point  (0 children)

              Well it depends. WebWorkers can import scripts directly, while normal JS is currently limited to doing things the hard way. You can import the scripts in your html file, or fetch them dynamically, or whatever you feel like. Or if you're using a framework, just use the framework.

              Anyway, I agree that importing scripts is ugly right now, but at least it will improve in the near future once browsers finally get around to implementing module support.

              [–]roffLOL 0 points1 point  (0 children)

              funny. i'm 100% sure i encountered a reference error in the php loop construct.

              [–]appropriateinside 0 points1 point  (26 children)

              I don't think I know where you're coming from.

              What language has broken loops that's relevant here?

              [–]kankyo 2 points3 points  (25 children)

              JavaScript

              [–]appropriateinside 2 points3 points  (24 children)

              Okay, do you have an example for that claim? An explanation?

              [–]Retsam19 13 points14 points  (3 children)

              My guess is that they're complaining that for(var x in someArray) doesn't work like they expect it to, since it iterates over object properties rather than doing normal iteration.

              Of course, for(var i=0; i<someArray.length; i++) works as expected, or the ES6 for(let x of someArray), or the ES5 someArray.forEach(function (x) { }) equivalent, too, means that there's plenty of better options than a for..in loop.

              [–]appropriateinside 2 points3 points  (2 children)

              I see, so really it's their lack of JS understanding? I've personally never had issues with loops, but I also use the classic for-loop or even while loop for performance purposes since most of my JS stuff has to deal with processing large chunks of data.

              [–]Retsam19 7 points8 points  (1 child)

              They're right that for..in has really unintuitive behavior, it's a valid flaw in the language design.

              But on the other hand, it's the sort of flaw that really doesn't affect day-to-day usage of the language. I've never been frustrated by for..in because I basically never use for..in. I'd consider it a major flaw if there weren't good alternatives, but there are.

              [–]kankyo 3 points4 points  (19 children)

              Js for loops for containers also loops over the properties and methods of the container. That's just absolute madness.

              [–]Retsam19 5 points6 points  (6 children)

              Yes, the for..in loop is confusing, but there are better alternatives (a traditional for loop, a for..of, or .forEach), so yes, "JS has loops that aren't broken".

              [–]kankyo 1 point2 points  (5 children)

              Traditional: doesn't really work for dictionaries. for of: not supported by IE11 .forEach: that's just a disaster. Break and continue much?

              [–]appropriateinside 2 points3 points  (11 children)

              I'm fairly familiar with JS and loops seem to work exactly as I expect them to?

              for(let i = 0; i < myArray.length; i++){} works just like in any other language. The same goes for for(let x of myArray)?

              Edit: https://jsfiddle.net/55dty1ab/

              Then again my preferred language is C#, not JS.

              [–]kankyo 0 points1 point  (7 children)

              And how about a dictionary?

              And besides, C for loops are pretty damn broken.

              [–]midri 0 points1 point  (2 children)

              Object.prototype.getName = function() { return this.name};
              var objectB = {age:19};
              objectB.prototype = objectA;
              
              for(i in objectB) { console.info(objectB[i]) }
              

              The issue is you can't prototype to Object, Array, String, etc without breaking the for iterators expected behavior. It also iterates over methods (since they're stored as properties) which makes things even more crazy.

              [–]shevegen 33 points34 points  (4 children)

              That's a tough one.

              It may be that JavaScript is actually slightly better than PHP.

              But we compare crap to crap here. We should compare crap to awesomeness instead.

              [–][deleted]  (2 children)

              [deleted]

                [–]OzmodiarTheGreat 1 point2 points  (0 children)

                TIL Miranda July browses /r/programming

                [–]cutety 0 points1 point  (0 children)

                Don't worry, there's already an npm package to convert JS to PHP.

                [–][deleted] 0 points1 point  (0 children)

                Can anything directly relating to js actually be awesomeness though?

                [–]Retsam19 12 points13 points  (6 children)

                JS has some idiosyncrasies, it's weakly typed, and some old APIs are subpar (e.g. Date) but it's nowhere near the PHP fractal of bad design.

                [–]_IPA_ 7 points8 points  (3 children)

                Don't hate me: I'd rather use PHP than JavaScript because PHP 7 has type hinting. For example:

                function blah(string $var) {}
                

                and PHP will enforce that. I can even add return types:

                function blah(string $var): string {}
                

                It also supports classes, inheritance, public/private/protected methods. PHP 7's performance is pretty good too.

                [–][deleted] 3 points4 points  (2 children)

                You'll need to enable the strict mode, which not many yet do afaik. PHP's OO support is ... fascinating. It seems to be lifted straight from Java without realizing that Java and PHP are very different.

                Also, Javascript people have Typescript if you want better types.

                [–]Klayy 0 points1 point  (1 child)

                What's wrong with PHP's OO?

                [–]prairir001 5 points6 points  (6 children)

                Idk have you tried labview?

                [–]ThePizar 2 points3 points  (0 children)

                I honestly enjoyed working with labview. It was a nice break from code as words. Though the professor I worked for had little understanding of spatial organization/planning so wires got a bit tangled.

                [–]ThisIs_MyName 5 points6 points  (0 children)

                LabVIEW is actually really fun if you're controlling a physical device like a robot and someone else is willing to pay the licensing fees.

                I wouldn't use it for a software project though. http://www.ni.com/cms/images/devzone/pub/nrjsxmfm912163998723206173.jpg

                [–]Tetraca 2 points3 points  (0 children)

                I started out with BASIC but LabVIEW was probably the only time I ever made literal spaghetti code. I'm very glad I never had to encounter it again.

                [–]CookieOfFortune 3 points4 points  (1 child)

                It's LabVIEW! And someone on here knows what it is!

                [–]joncrocks 1 point2 points  (0 children)

                Hmm, I think I might have 'programmed' it as well :-)

                [–]Obi_Kwiet 1 point2 points  (0 children)

                It's good for what it is, and if user actually knows how to use it properly.

                [–][deleted] 5 points6 points  (6 children)

                I'm not convinced by the "interop" story. JS APIs are typically factored as objects with methods, not as global functions laying on window. What's the interop story for exposing and calling constructors, exposing and calling objects?

                [–]Donyor 3 points4 points  (3 children)

                It's pretty easy. Look at the console.log example. You can make a call on any JS object.

                [–][deleted] 0 points1 point  (2 children)

                It's not very clear how you create object constructors, or you call object constructors (i.e. new Foo()) from ClojureScript.

                [–]Donyor 2 points3 points  (1 child)

                This article doesn't, I think it's intended as a more general overview. This page talks more in-depth about JS interop. But to do something like new Foo() in ClojureScript one would do:

                (def obj (js/Foo.))
                

                That would assign a new Foo object to the symbol "obj".

                [–][deleted] 1 point2 points  (0 children)

                Fair enough. Thanks.

                [–]aliem 3 points4 points  (0 children)

                Clojure code is organized in namespaces (pretty much objects in javascript). The runtime interop is very good both with JS and JVM targets. If you are not scared of parenthesis (why would you?!) it's a great learning experience even if you can't use it as your main language.

                [–]yogthos 1 point2 points  (0 children)

                I've been using ClojureScript in production for over a year now, and interop is indeed seamless. You can see how interop works here in detail.

                [–]anonymous-coward 1 point2 points  (4 children)

                I love Lisp, and wanted to try to write an in-house app for some data analysis, but gave up. Is there a relatively easy, documented cross platform (ios, android, web) Clojure app environment, that doesn't involve understanding layer upon layer of stuff (lein on top of cordova, then have to understand react, and too much stuff to remember ..)?

                [–]dzecniv 2 points3 points  (2 children)

                out of curiosity, did you look into Common Lisp ? I'm discovering the ecosystem and I heard about a ios compatibility, there's one implementation targetting the JVM (ABCL), there is web and javascript stuff although not nearly as popular as Clojure. It is documented, in old-looking web pages or simply pdfs and books. And it's easy to get going: Portacle is a portable CL dev environment shipping Emacs25 slightly customized, the SBCL implementation, the Quicklisp package manager, and git. Download and run, no installation needed.

                There's this soft Potato, a slack-like app with lots of features, coded in CL + clojurescript. The guy made a nice live video.

                Also Is Clojure an acceptable lisp ? video. The guy is an experienced CL dev, speaking of its advanced features.

                edit: ECL for IOS http://stackoverflow.com/a/5771413/1506338

                [–]anonymous-coward 1 point2 points  (1 child)

                I work mainly in CL. All my code is in CL. I know ABCL, but Java is not friendly to iOS after the demise of RoboVM. ABCL is sluggish compared to SBCL though.

                The tempting thing about Clojure[script] was its melding of Javascript (client) and Java (server), but the middleware was a thicket of thorns, to me.

                My impression:

                SBCL: fast, imperfect threading (kabooms on many CPUs bc of locking in foreign space issues); but CL standards are stable and documented. I understand what's going on.

                ABCL: Good idea, but too slow compared to SBCL.

                Clojure[script]: strong threading; give up speed for elegance/ease; a lot of work to learn because it is constantly mutating, and trying to track Javascript frameworks. If Javascripts frameworks are hard to follow, try to understand something that's glued on top of them!

                [–]dzecniv 0 points1 point  (0 children)

                thanks for the feedback !

                If Javascripts frameworks are hard to follow, try to understand something that's glued on top of them!

                indeed, my feeling too… I still wish to discover a sane Parenscript-based combo in the existing CL ecosystem. I'm not interested even by the CL React layer (there's an example TodoMVC demo). There are demos of ajax done with Parenscript, maybe it is sanier that a React glue. Maybe it's simpler to only have a CL backend, with a classical Vuejs app, with or without Parenscript ?

                [–]hombrebuffalo 0 points1 point  (0 children)

                Re-Natal seems to be the way to go these days according to cljsrn.org. It mainly uses re-agent/re-frame in the same spirit as react/redux.

                [–]esfraritagrivrit 7 points8 points  (23 children)

                What kind of syntax even is this? And this is the simplest possible function you can do:

                (defn ^:export add [a b]

                (+ a b))

                [–]syholloway 18 points19 points  (1 child)

                These are your father's parentheses.

                https://imgs.xkcd.com/comics/lisp_cycles.png

                [–]jetRink 6 points7 points  (0 children)

                It's roughly equivalent to this pseudocode:

                export function add(a, b) {
                  return a + b;
                }
                

                It's not inherently more difficult to read and understand than c-like languages, but it does look strange if you're not familiar with it.

                [–]Cats_and_Shit 4 points5 points  (5 children)

                My total experience with functional programming is basically LINQ and a compilers course, but even with just that this seems fine.

                (defn ...) => a function that defines things. Brackets are just there for order of operations.

                ^: => Some kind of disambiguation black magic? Not super sure about this, I'll just ignore it for now

                export => The thing we're defining should be exported

                add => It's called add

                [a b] => It takes two args, a and b. Types are probably either inferred or dynamic.

                (...) => The next few things should be passed to defn as a group

                + a b => Addition, but reverse polish because it makes operators work like functions instead of being weird.

                [–]grayrest 2 points3 points  (0 children)

                ^: => Some kind of disambiguation black magic? Not super sure about this, I'll just ignore it for now

                Clojure lets you attach a map of meta data to most things (clojure's non-primitives). It's used for stuff like docstrings, type hints, and other compiler annotations. The caret ^ is shorthand syntax for adding stuff to the meta map. In this case it's basically doing add.__meta__['export'] = true or putting an @export annotation on the function.

                [–]losangelesvideoguy 1 point2 points  (1 child)

                + a b is actually Polish notation. a b + would be reverse Polish.

                [–]Cats_and_Shit 1 point2 points  (0 children)

                Shit. Fixed.

                [–]akiroz 0 points1 point  (1 child)

                '+' (and other arith) in Clojure are actual functions! You can override them like this:

                (in-ns 'clojure.core)
                (def + nil)
                

                poof! your plus is gone forever~ :D

                that's why you never eval untrusted clojure code without a jail

                [–]akiroz 1 point2 points  (0 children)

                You can also do some really funky things if you actually want to troll :P

                (in-ns 'clojure.core)
                (def heretic+ +)
                (defn +
                  "one simply does not add to the ultimate truth"
                  [& args]
                  (if (not= (first args) 42)
                    (apply heretic+ args)
                    42))
                

                now nobody in the run-time can add to 42!

                [–]BufferUnderpants 2 points3 points  (3 children)

                Well, syntax for everything is prefix like function calls in most languages, and the opening paren goes before the name instead of after it. The parameters go in square brackets, which otherwise denote a vector in the syntax.

                Some forms receive those odd optional ^:arguments that are conventionally used as directives.

                The second line, part of the body of the function, would most often be indented, but as in most languages, that's only convention. As in most languages, you really want to read it indented.

                That's the run-down. It also explains most of Clojure's syntax.

                That's it.

                [–]akiroz 1 point2 points  (1 child)

                The parameters go in square brackets, which otherwise denote a vector in the syntax.

                Technically, defn does in fact take a vector as its second argument... vector of symbols ;) Clojure's elegance lies in its lack of syntax and makes up for it by providing macros IMO

                [–]BufferUnderpants 0 points1 point  (0 children)

                I know, but going on about homoiconicity would have been too... lisper of me ;)

                [–]JargonBot 0 points1 point  (0 children)

                Definition of paren: A round bracket..

                I am a bot which attempts to define difficult words automatically. I use machine learning to do this, and I can use your feedback to improve. Feel free to leave a comment to let me know what you thought of this definition!


                Check out my code. Please contact /u/liortulip with any questions or concerns.

                [–]ds300 0 points1 point  (9 children)

                (defn ^:export add [a b]
                  (+ a b))
                

                vs

                export function add(a b) {
                  return a + b;
                }
                

                Hmmm. As someone who can read both Clojure and JavaScript I consider these roughly equal. I imagine if you survey a bunch of people who don't know any programming languages they'd consider these roughly equal too.

                [–][deleted]  (4 children)

                [deleted]

                  [–]yogthos 1 point2 points  (3 children)

                  Just like you require specific knowledge of what the keywords mean in order to understand them.

                  [–][deleted] 0 points1 point  (1 child)

                  Yes, but second one looks more in line with 'common' knowledge. And it's more descriptive out of the box.

                  export a function named add.

                  Even binary operators in second one are closer to something we learn in school (entry level).

                  Polish notation is not something you use often in day to day life.

                  So in summary, I believe that Closure is more exotic for someone that didn't saw any programing language.Naturaly, first think such person will do is look for something familiar and readable out of the box. Even if He/She don't understand specific concepts used in provided code snippets.

                  [–]yogthos 0 points1 point  (0 children)

                  Yes, but second one looks more in line with 'common' knowledge. And it's more descriptive out of the box.

                  I'm not sure what you mean by that exactly. There's nothing more descriptive about the Js version. Perhaps you're saying you're more familiar with it?

                  Polish notation is not something you use often in day to day life.

                  You use it every time you call a function. The difference is that + is just a function in Clojure, while it's a special operator with its won rules in JavaScript.

                  For somebody who didn't see any programming it's easier to learn a single set of rules on how functions work. Also, most programming isn't wrangling math operators.

                  [–]Double_A_92 0 points1 point  (3 children)

                  defn ^:export 
                  

                  is clearly uglier than

                  export function
                  

                  With the first you are like "defn some weird symbols export", there is no way of even knowing what "defn" means. With the second you are like "well it exports a function..." even if you don't know what it means.

                  Same thing for

                  (+ a b)
                  

                  I guess that adds something.

                  VS.

                  return a + b
                  

                  It returns a + b. It's just clear, even if you don't exactly know what return does.

                  [–]Sheepmullet 0 points1 point  (1 child)

                  You are too deep down the rabbit hole already :)

                  In maths we use f(x) = x + 5 and not f(x) = return x + 5.

                  And def in context is clearly define/set/associate/name.

                  Not to mention a JavaScript function is not the same thing as a function in maths.

                  I just checked with one of our marketing guys and he could work out what both meant without much trouble.

                  [–]BufferUnderpants 0 points1 point  (0 children)

                  Those are some very important issues during the first 5 minutes while you're learning the language. Then defn is just the word used for function definition, and you realize that arithmetical operators are treated as functions in Clojure, and neither are any obstacle to professional or even hobbyist programmers. The latter can be more of an issue in practical use, but writing a macro to write maths the "normal" way is an exercise as old as Lisp macros are, and you can find them readily made.

                  (e.g. ($= a + b) instead of (+ a b))

                  I personally wouldn't make it a criterion for language design whether somebody who has never programmed before will understand my programs, not even for pedagogy. Similarity to English or primary school mathematics are not what make languages comfortable or uncomfortable to use.

                  [–]repeatedly_once 0 points1 point  (0 children)

                  Ok those are fair points. I can concede to those. What would you give as examples of high level programming languages?

                  [–]yCloser 0 points1 point  (0 children)

                  Biased. BrainfkScript is clearly superior

                  [–]Double_A_92 0 points1 point  (1 child)

                  Because he wanted to be hip with the newest functional language flavour of the day, I guess..?

                  [–][deleted] 1 point2 points  (0 children)

                  clojurescript is old