5 ms·
I've used Clojure in a few cases and I totally adore the simplicity of its Lisp syntax as opposed to the baroquesque abomination that is Scala. However, lack of
by MarcusBrutus 10y ago
I've used Clojure in a few cases and I totally adore the simplicity of its Lisp syntax as opposed to the baroquesque abomination that is Scala. However, lack of strong typing is sorely felt. I 've done a little playground-style OCaml coding and the feeling you get with OCaml is that once your program compiles, it most likely also runs correctly. Is a Lisp language with strong typing for the Java ecosystem too much to ask? Apparently it is or else we would have had it by now.
- jeremiep 10y agoTheres the new clojure.spec[1] in 1.9 and core.typed[2] adds an optional type system as well. [1]: http://clojure.org/about/spec http://clojure.org/about/spec [1]: https://github.com/clojure/core.typed https://github.com/clojure/core.typed The REPL-driven development of Lisps makes types not as important because everything is interactively tested as you write it. Having an optional type system makes it much easier to start with dynamic types and gradually add type annotations as your architecture stabilizes.
- yogthos 10y agoConversely, lack of mutability makes dynamic typing much easier to reason about. Since variables typically can't be changed via side effects, you can do local reasoning about your code vast majority of the time.
- rkrzr 10y ago> Conversely, lack of mutability makes dynamic typing much easier to reason about. Dynamic typing does not imply lack of mutability. Those are unrelated concepts. Python and Ruby are dynamically typed but both are certainly mutable. Conversely static typing actually makes it easier to reason (locally or not) about things, since you always know the type of everything.
- jeremiep 10y agoI think he meant it in the context of Clojure, which has immutable values. I don't feel static typing makes it easier to reason about, at all. Reasoning about values and their transformations is more important to me than reasoning about types, and since values carry types you're actually working with more information. Most of the time the types I'm interested in are closer to concepts (sequences, mappings) than concrete classes. Thats where having immutable dynamically typed values is better than having statically typed mutable ones.
- rkrzr 10y ago> since values carry types you're actually working with more information. Only for the specific value that you are reasoning about. If you want to reason about all possible values, then you are de-facto reasoning about their types. > Most of the time the types I'm interested in are closer to concepts (sequences, mappings) than concrete classes. But sequences and mapping are also types, right? You can abstract types to type classes (i.e. whole classes of types, e.g. all types that can be iterated over, or all types that are ordered etc.) and also reason about them. > Thats where having immutable dynamically typed values is better than having statically typed mutable ones. Sure, ideally you want to have immutable statically typed functions and values, since you can then do some equational reasoning and prove certain properties of your program.
- jeremiep 10y ago> If you want to reason about all possible values, then you are de-facto reasoning about their types. True, but a variable can only ever have one value at any given time; knowing a variable is an int is good, knowing a variable is the same int value throughout its extent is better :) > But sequences and mapping are also types, right? Yes, but they're not concrete types and don't map to a single interface either. When they do these interfaces are compositions of smaller interfaces anyways and I prefer to reason about these smaller parts. Which means I'm reasoning more about the shape of the data than the actual type implementing it, and that to me is closer to a value than a type. Its the same with type-classes, you're reasoning about the features of a value rather than the specific type implementing said features. > ideally you want to have immutable statically typed functions and values For functions we're talking about purity rather than immutability (which qualifies variables). Type systems also are very leaky abstractions; null pointer exceptions, can't limit the range of value, requiring more code which introduces its own bugs and complexity and more. From experience I prefer a smaller dynamically typed codebase that has tests for the trickier parts over a statically typed codebase (even if tested). The productivity difference is startling and the resulting quality is about the same.
- mindcrash 10y agoTyped data was already possible with schema [1], which is now maintained by the plumatic (former prismatic) team. Which also says something about the way Clojure is awesome. Everything is optional, you arent forced to use anything to get to a working solution. Stuart Halloway and Rich Hickey also have some great talks on this subject. If you are interested you might want to check out "Radical Simplicity" [1] by Stuart and "Simple Made Easy" [2] by Rich to see why Clojure wipes the floor with almost any other programming language, especially the likes of C# and Java. I am not surprised at all Bob Martin loves it. Any principled software engineer would. [1] https://skillsmatter.com/skillscasts/2302-radical-simplicity https://skillsmatter.com/skillscasts/2302-radical-simplicity [2] https://www.infoq.com/presentations/Simple-Made-Easy https://www.infoq.com/presentations/Simple-Made-Easy
- sdegutis 10y ago> "the feeling you get with OCaml is that once your program compiles, it most likely also runs correctly" The feeling you get with Clojure is that, when you write and test each function (using CIDER) and get live feedback to make sure they work, you can combine them into bigger functions that most likely also run correctly.
- kazinator 10y ago> I 've done a little playground-style OCaml coding and the feeling you get with OCaml is that once your program compiles, it most likely also runs correctly. This is only a feeling. Without carefully testing the code to exercise its cases, all you know is that they are properly typed. For instance, suppose we write a complicated function (or group of functions) which goes through a block of intermediate code (output of a compiler) and assigns registers to all the temporaries, introducing memory spills in situations where more variables are live than the available registers. We might have a feeling that because this code compiles, it must be free of problems such as accidentally assigning the same register to two variables which have overlapping lifetimes. That feeling is poorly supported by reality; it is the "safyness" of static typing. Untested code is garbage. And thorough testing is difficult to impossible, so there is a bit of garbage in almost all software, unfortunately. Statically type checked code has all of its code paths effectively tested by the compiler, but those tests have only the limited point of view of trying to show that the program contains a trivial type mismatch, a close cousin of the syntax error. These "tests" are not actually feeding values into the code and trying to make it fail or behave incorrectly with respect to its specification.
- rkrzr 10y ago> Statically type checked code has all of its code paths effectively tested by the compiler The type checker just ensures that a program is well-typed (i.e. free of type errors). The better the type system the more program properties can be encoded in it and the more errors it can catch (up to the point of proving correctness of your program). But you are right that type checking alone is no substitute for testing. They are orthogonal concepts and both should be employed to ensure that your programs behave correctly. One nice thing of statically typed languages is that they can automatically generate some tests for you, like e.g. the QuickCheck library for Erlang and Haskell.
- deleted 10y ago[deleted]
- jeremiep 10y agoClojure has quickcheck as well: https://github.com/clojure/test.check https://github.com/clojure/test.check
- justinhj 10y ago"baroquesque abomination" is a very colourful but somewhat unfair description of Scala. I've been using it in production for a few years now and I find it can be quite pretty if you're careful, and is quite readable once learned. Not only that but after years of Common Lisp and Clojure programming (at hobby level) I never really satisfactorily lived the dream of the programmable programming language that lisp offers. With Scala I find it has capable facilities for writing DSL's without even resorting to compile type macros. I do agree the syntax can be terrible especially when people go crazy making DSL's for libraries or make their code too dense and unreadable.