4 ms·
Is clojure.spec a replacement for static typing? I ask because I've taken a look at clojure in the past and generally like what I see, but after moving from Jav
by disease 9y ago
Is clojure.spec a replacement for static typing? I ask because I've taken a look at clojure in the past and generally like what I see, but after moving from JavaScript to TypeScript at work I don't think I can ever return to a dynamically typed language again. Types are just priceless when refactoring, integrating someone else's code with your own or just exploring new libraries or APIs.
- tensor 9y agoIt addresses similar problems as static typing, yes, but it's not a compile time check. Instead, it's an optional runtime check. The idea is to use it during testing and development, and have it be disabled during production.
- jeremiep 9y agoIts also great at validating data! We're running some of our specs in production to enforce guarantees on data coming in and out of the app :)
- misterbowfinger 9y agoYup, specs can be used at runtime as well. Very helpful to validate data, or perhaps a set of business rules. Insures the spec you use to test is the same logic you use at runtime.
- always_good 9y ago>specs can be used at runtime as well. What do you mean "as well"? I thought it was only a runtime check at all.
- simongray 9y agoOne of the stated goals of spec is generative testing. While technically runtime, it's is not runtime from the user's point of view.
- ambulancechaser 9y agoi think they're talking about production run time versus development runtime. think of it as turning asserts off on production builds. but spec can conform data and explain the reason for non-conformance so some might leave some spec in production for logging, messages, etc.
- misterbowfinger 9y ago^^ this, using spec at run time in your actual application logic
- billburcham 9y agoThat's right spec is a runtime thing. This Spectrum thing purports to evaluate your specs at compile time though: https://github.com/arohner/spectrum https://github.com/arohner/spectrum
- soberhoff 9y agoMacros are checked at compile time. So it is a static check to some extent.
- gw 9y agoAs with many things in life, it's a tradeoff, not a replacement :) Specs don't run at compile-time (except for macros), but they are more flexible than static types. Apart from runtime instrumentation, they can be used to validate or destructure complicated data (read from the wire or disk, for example), and they can generate tests automatically.
- vemv 9y agoIn addition to the sibling comments: worth noting that spec offers you a-la-carte typing - typing when/where/how you please. This is very different from the experience of having to constantly satisfy a compiler. Generally I decide to 'spec' a tiny percent of my code - just the most critical one, or APIs with complex method signatures, etc. When doing so, if the spec'd function used N other functions, one could argue that those N functions are also being implicitly checked.
- indigo0086 9y agoin addition to type validtion it offers a neat tool for advanced destructuring. Here's a question I asked on reddit regarding that with a good response and examples https://www.reddit.com/r/Clojure/comments/7eb4ct/are_the_results_from_conform_in_the_spec_library/ https://www.reddit.com/r/Clojure/comments/7eb4ct/are_the_res...
- ledgerdev 9y agoI think it's better referred to as a toolkit for building more correct software. One of the things it can be used for is to check variable types at dev time, just as static type systems check a type compile time. It can also be used for runtime validation, randomized generative testing, more advanced checks/rules than current type systems can specify(eg checking outputs are correctly related to inputs). Also an important philosophical difference with type systems is an open approach to data structure, where types are generally closed. The concept is that it allows more flexible systems that are easier to adapt to new needs. Here's the best intro to spec I've seen, it's long and sound is terrible, but it's a great talk. https://vimeo.com/195711510 https://vimeo.com/195711510
- yogthos 9y agoWorked with static typing for about a decade primarily with Java in the enterprise. However, I've also used Haskell and Scala which have advanced type systems. I moved to work with Clojure about 8 years ago, and I don't miss types. If I did, I would've gone back to a typed language a long time ago. My experience is that dynamic typing is problematic in imperative/OO languages. One problem is that the data is mutable, and you pass things around by reference. Even if you knew the shape of the data originally, there's no way to tell whether it's been changed elsewhere via side effects. The other problem is that OO encourages proliferation of types in your code. Keeping track of that quickly gets out of hand. What I find to be of highest importance is the ability to reason about parts of the application in isolation, and types don't provide much help in that regard. When you have shared mutable state, it becomes impossible to track it in your head as application size grows. Knowing the types of the data does not reduce the complexity of understanding how different parts of the application affect its overall state. My experience is that immutability plays a far bigger role than types in addressing this problem. Immutability as the default makes it natural to structure applications using independent components. This indirectly helps with the problem of tracking types in large applications as well. You don't need to track types across your entire application, and you're able to do local reasoning within the scope of each component. Meanwhile, you make bigger components by composing smaller ones together, and you only need to know the types at the level of composition which is the public API for the components. REPL driven development [1] also plays a big role in the workflow. Any code I write, I evaluate in the REPL straight from the editor. The REPL has the full application state, so I have access to things like database connections, queues, etc. I can even connect to the REPL in production. So, say I'm writing a function to get some data from the database, I'll write the code, and run it to see exactly the shape of the data that I have. Then I might write a function to transform it, and so on. At each step I know exactly what my data is and what my code is doing. Where I typically care about having a formalism is at component boundaries. Spec provides a much better way to do that than types. The main reason being that it focuses on ensuring semantic correctness. For example, consider a sort function. The types can tell me that I passed in a collection of a particular type and I got a collection of the same type back. However, what I really want to know is that the collection contains the same elements, and that they're in order. This is difficult to express using most type systems out there, while trivial to do using Spec. [1] http://blog.jayfields.com/2014/01/repl-driven-development.html http://blog.jayfields.com/2014/01/repl-driven-development.ht...