1. 28

  2. 3

    Either it would be something akin to Haskell in S expressions, or it would be indistinguishable from Clojure with some tweaks under the hood.

    Hey @arrdem, what are your thoughts on core.typed?

    1. 6

      I have many thoughts on core.typed, most of them as a dissatisfied user and probably enough to give a real blog post a go.

      When I first experimented with it, I was able to detect and fix real type level bugs but I didn’t find that it really aided me in refactoring. The notational overhead was too high. The CircleCI postmortem largely rang true for me when it came out. These problems seem to be endemic to gradual typing or at least present efforts.

      My biggest complaint however is that “optional” or bolt on types don’t help me structure or optimize my programs. The instant a programmer admits that they could have an instance of some type, it must become part of their case analysis. I built guten-tag pretty much because of this single impulse. core.typed doesn’t help you at all there. You have to declare the possibility of such other types in the function signature, and then retype all that information in your condition handling. This goes back to the verbosity issues.

      When last I mucked with it, core.typed didn’t help with type hints at all. Since the strictly tagged Clojure work I did is likely to reappear this is definitely a concern for me.

      This and the success of Elm in generating excellent type error messages all kind of leads to the view that the type system AND HAVING ONE is pretty central to the usability of any language. You can’t just act like it doesn’t exist and the fact that we have core.typed and schema and guten-tag and a dozen other “schema” (type) checking projects confirms this to me.

      1. 8

        This and the success of Elm in generating excellent type error messages all kind of leads to the view that the type system AND HAVING ONE is pretty central to the usability of any language. You can’t just act like it doesn’t exist

        I see where you’re coming from, and I think in the context of Clojure it’s probably correct. But Erlang does a great job of having an optional type system that provides a ton of benefit even when it’s not used for the whole codebase. I think this is largely because it leans much more heavily on inference and success typing, but also partly because of Erlang has dramatically simpler types to begin with. And the ubiquity of pattern matching helps a lot too.

        Those prerequisites are much harder to hoist onto a system from the outside, but that doesn’t mean you can’t have a successful type system that resides outside the core language. You just need the right foundation in place first.

        1. 1

          I actually disagree with CircleCI’s post. core.typed makes my code more readable (e.g. I don’t forget what types of data are flowing through my functions) so iteration time is faster. If I need to do exploratory stuff at the REPL, I just turn off type checking for a bit. The language support and 3rd party library support are definitely issues, but they are at least solvable problems. I think core.typed is in its infancy but it has a ton of potential, more potential than schema anyway.

      2. 0

        It’s too bad this still targets the obese and slowly disappearing JVM. The one thing really holding back Clojure is the fact that it uses a heavy-weight dinosaur technology instead of something like LLVM to compile directly to native code.

        Edit: “Troll”? Really? How is any of that trolling, please explain. I’ve used Clojure and have watched The State Of Clojure surveys as they come out every now and then. Consistently this issue is brought up again and again.

        1. 13

          Some facts about Clojure:

          • It relies on having a high-quality GC implementation
          • It relies on having high-quality concurrency primitives and a well-defined memory model
          • A huge part of its value proposition is being effective glue for an existing ecosystem

          The JVM provides all of these, while LLVM provides less than all of these out of the box. I have no doubt someone could write their own pared-down version of the JVM for Clojure to run on, but that’s clearly not a priority for the people running the core project, nor for anyone else I’m aware of in the Clojure community. Other than aesthetic objections to the JVM, I’m not sure why it’s worthwhile to pursue. Feel free, though.

          1. 2

            Other than aesthetic objections to the JVM

            Let’s not be disingenuous, nobody is making “aesthetic objections” to the JVM. They are making technical objections to the JVM on the grounds that it is a poor virtual machine. Its various significant flaws include:

            1. Very long startup time that leads to decreased developer productivity and poor deployability
            2. Poor platform support (those great days when this was not true are long gone)
            3. Large memory usage

            I stopped using Clojure because of it, and I’m certain many others have as well.

            It would’ve been better to implement this language as another transpiled-to-JavaScript language and leverage the asynchronous Node runtime than to use the JVM. Even better would be to fork the Go runtime.

            The JVM is Clojure’s biggest handicap, and it is not helpful to Clojure to be in denial about this fact.

            1. 10

              The JVM is far from perfect, but has best-in-class GC and tooling for monitoring and debugging complex production issues. If you compare V8 and JVM for backend services and find the JVM wanting, I’m not quite sure how to respond to that. Likewise, the Go runtime is still significantly behind the JVM on both these counts.

              I’m sorry if you feel it’s unfair to characterize your focus on footprint and startup time as aesthetic complaints, but these are not things that have been at all relevant to my extensive production use of Clojure. I freely admit that my use cases are not representative of everyone else’s, but I think your assertion that the JVM is Clojure’s biggest handicap misses the point of Clojure and what sorts of problems it’s trying to solve.

              1. 5

                I feel like the issue here is that those use cases are heavily constrained by the JVM’s limitations. There was a time when Java applets meant to run in the browser were commonplace. It was fairly brief, because of that startup time. Indeed Java is heavily used today for server-side situations, where startup time is not a constraint.

                I do see your point that this is a choice about the audience of Clojure, and one which was made intentionally. I personally feel rather irritated that there was an excellent standard and portable Lisp, which has not attained the popularity that Clojure has. (Yes, there are several JVM implementations of Common Lisp.)

                I mean, I know that it would be highly unfair to blame Clojure for being popular. And, actually, I feel that I understand the cultural factors (related to a culture of writing code with the expectation others will reuse it) that have gotten Clojure more mindshare than CL has had in a long time. But I still understand being wistful about things that didn’t happen, and I think that’s where @itistoday is coming from.

                1. 3

                  That is more of a dismissal of my comment than an actual reply.

                  People want a fast, lightweight, portable language. The JVM makes that impossible. Lots of people would jump at the chance to use a Lisp like Clojure to develop games for iOS or beautiful desktop applications, but they can’t (or they can, but only by jumping through some insane hoops few are willing to go through). Even server apps are rarely done in Clojure because of the high memory demands and poor platform support. Why? The JVM.

                  1. 6

                    You seem more critical of the JVM than Clojure, and you’re conflating your resentment for the former as distaste for the latter.

                    Certainly Clojure’s lack of adoption at scale has nothing to do with its reliance on the JVM, on the contrary, that if anything has helped it to become popular. If anything that is slowing Clojure down is either its strangeness (yes, people don’t like Lisps) or lack of promotion. It’s growing in popularity, but still shrouded in relative obscurity.

                    I do not think your resentment for the JVM is well-founded. It has its drawbacks, but they aren’t in performance or memory consumption. Startup times aren’t relevant on server side programs, hot swapping on the other hand is.

                    Say what you want about the rising popularity of other languages, but the JVM isn’t disappearing. The new G1 garbage collector is unrivaled in sophistication and performance. What is more, the addition of specific value types to Java9 will boost its performance even more yet keep language interoperability easy (reified generics, which it is not getting, would make this difficult). Compound this with the rising popularity of Scala, Kotlin and Clojure and other JVM languages, the popularity only growing.

                    1. 2

                      you’re conflating your resentment for the former as distaste for the latter.

                      I have no distaste for the latter. Don’t know why you’re getting upvotes for what is an obvious straw man.


                      I didn’t mention performance.

                      or memory consumption

                      Memory consumption is a big problem when a tiny web app takes up a hundred of megs of RAM.

                      the popularity only growing.

                      OK, I have not seen evidence of that.

                2. 4

                  If you want Clojure but on Node, you can use Clojurescript, which is an almost-Clojure that compiles to JS. Its primary motivation was to run Clojure in the browser, but since it exists, people are also using it out-of-browser on top of Node. Its upsides are faster startup time and exact equivalence between the in-browser and out-of-browser VMs, if you want to run the same code both places. Downsides are generally worse performance on longer-running code, and a more limited set of concurrency primitives (e.g. no STM).

                  1. 1

                    If you want Clojure but on Node, you can use Clojurescript, which is an almost-Clojure.

                    I did ClojureScript development as well, however development still required using the JVM, and the code it generated was oddly bloated & convoluted. That said, yes, the fact that the end-result doesn’t require the JVM is quite nice.

                    EDIT: One major drawback though (last I checked) is that it’s not designed to target or work well with Node.

                    1. 2

                      I’ll point you to Sibilant

                  2. 4

                    Even better would be to fork the Go runtime.

                    My understanding is that Google’s Go runtime doesn’t allow loading new code at runtime. Sounds like a disastrous choice for interactive development.

                    1. 1

                      Interesting, didn’t know that. I also don’t know whether, if true, that is a difficult thing to fix or not. Other runtimes that could be worth exploring include LuaJIT, Julia, and yes, V8.

                      1. 1

                        There was a GSoC project a couple years ago to port to Lua. No idea how far it got.

                        Suggesting the mainline development should just stop because some people prefer the tradeoffs of other runtimes is pretty bonkers though.

                        1. 1

                          Suggesting the mainline development should just stop because some people prefer the tradeoffs of other runtimes is pretty bonkers though.

                          Good thing I didn’t suggest that.

                3. 7

                  The value add of Clojure (and Clojarr) is simply developer efficiency relative to Java in using Java tools and libraries. Same as Scala or JRuby or Kotlin or what have you. Given this goal, criticizing Clojure/arr for not targeting bare metal is frankly silly since bare metal performance has little to do with the utility of the projects.

                  Thanks to @ztellman for articulating the related performance concerns much better than I was able to.

                  1. 3

                    I agree with other commenters that a huge part of Clojure’s value proposition is the fact that you can interoperate with a huge existing ecosystem of libraries. This is a really interesting project and I’m glad to see a Clojure fork that adopts community-driven development in the vein of other languages like Rust.

                    From a purely experimental/shits-and-giggles perspective, I’ve been thinking about the ramifications of implementing a Clojure-alike on top of a Swift-based runtime/interpreter:

                    • Clojure’s persistent immutable data structures map surprisingly cleanly to Swift’s copy-on-write value type collections
                    • The fact that data structures are immutable makes it a lot more difficult to produce the circular references that RC doesn’t handle well
                    • Swift doesn’t have a proper concurrency model yet. I looked briefly into using GCD to implement the (non-STM) concurrency primitives but didn’t get very far before having to drop the project
                    • Community-driven development hopefully can steer parts of the Swift project in a way that deficiencies for this use case (e.g. anemic reflection support for interop) can be addressed eventually