6 ms·
I haven't felt the need for static typing in Clojure at all. I don't understand, why people are so dogmatic about static typing. In my experience and other on t
by kaliszad 5y ago
I haven't felt the need for static typing in Clojure at all. I don't understand, why people are so dogmatic about static typing. In my experience and other on the team share it too, static types really haven't (or wouldn't have) prevented any bugs. What is more important are good names for variables/ references/ functions, code that just speaks to you or is at least sufficiently clear, up-to-date and clear documentation with examples and links if needed and efficient testing/ sensible test coverage. If I really need to know the type of something, I can always use (type <something>) or more concrete e.g (string? <something>) if I want to use that information for something. If I don't know, how to use the function, I have to improve the name, the documentation and my understanding of the code perhaps. If I pass garbage to a clearly named function, I get garbage out as with the static type system. In both cases, I have to investigate and ask myself tough questions about how I understand code or whether our code-base is well maintained.
I can see static typing helping e.g. with compilers, low level software where every clock cycle and byte matter and some specialized stuff. I don't see much point in static typing in a language like Clojure.
- grayrest 5y agoIf you're on a project every day and familiar with all the pieces, there's not a large advantage to static typing. Static typing allows people unfamiliar with the program to make changes and have a reasonably high degree of confidence that they got them right. This can be junior devs, people new to the project, you after 5 years away, or a project that's grown to the point where nobody knows all the pieces. I'm not saying this as a die-hard static typing fan. I wrote Python for years, have written JS professionally most of my career, and spent 2 years writing Clojure professionally. I'm comfortable with dynamic languages. The Clojure codebase was the most stable I've been on (including typed languages) largely due to the senior team and excellent QA. The only problem I had with it was when business shifted from a subscription model to an a-la-carte model, which required manually reworking a LOT of maps to match the new requirements. This is considerably more painful in a dynamic language than it is in a static one. There IS a downside to static typing in terms of verbosity. I've seen Java codebases where half the code was there basically because of the static typing. More advanced type systems do not suffer from that problem. I'm fine with OCaml / F# / Rust / Typescript.
- kaliszad 5y agoGreat points, thank you for sharing your experience. Manual rework of maps seems like something that a good IDE or a small script should be able to automate, that is the point of Clojure being a data structure (EDN) after all - you can do stuff to the code as if it was data. Maybe there were specifics not allowing such sweeping changes, would love to hear more if you can share more about it. I have a colleague which became 18 just a few days ago. He newer heard of Clojure(Script) or CSS before late last year and started actively learning it sometime after that. Jan is able to work on considerable amounts of code for our new landing page that will have some special interactive OrgPad embeds in it. He didn't have much difficulty navigating Clojure or our code base considering he did most of the work after school and on weekends basically as a learning exercise. Of course, he is getting solid guidance by the team. Our CTO Pavel has 20+ years of experience as a programmer/ software engineer and can do code reviews with Jan, so that helps. It also doesn't hurt that Jan is very smart, basically hand selected over multiple years by our CEO Vít who led a mathematics course for children/ teens and as such known Jan very well. Giving Jan a chance like this is basically a pilot combining normal education with practical, professional experience. Something like a very long internship on steroids :-) I would still stress that static types are much less valuable than good variable/ function names and documentation/ clear code in my opinion and that maybe the complexity static types introduce isn't worth it overall. I also don't think, that static types as seen in e.g. Java or C# add any discernible degree of confidence - else somebody on the team would notice already. Jan didn't have problems navigating the code base even though most of the technologies, the language and the code base were completely new for him. Yes, anecdotal but I think it really is a valid and very important point.
- grayrest 5y agoI'm happy it's working for you well. The map changes were more in the line of changing core maps and then having to update every place they were used. IDEs are amenable to this as long as they can figure out the references. Cursive helped some but most of the work was still manual. My point of reference between typed and untyped code is primarily with Typescript and Javascript since that's 99% of what separates the two. For what it's worth, I do have 21 years of experience and have been lead on my projects for a number of years. As the lead, I get enough benefit from the type annotations that I've told co-workers to just any type anything they can't get working immediately and I'll fix it in code review. It's enough of an overall team velocity increase and easier code reviews that it's a win. I'm not trying to argue with your experience. Dynamic languages work fine for building products and Clojure is my favorite dynamic language by a significant margin. I'm sure I'll write more Clojure in the future. I'm just trying to explain the benefits since I had the same mindset 15 years ago and now prefer static types. I'll mention that don't particularly like C# or Java and their type systems are not expressive enough for me to prefer over dynamic language.
- throwaway894345 5y ago> I don't understand, why people are so dogmatic about static typing. Most static typing folks have backgrounds in dynamically typed languages, and it's this experience (not dogma) that informs their preferences. The inverse (people have extensive experience with statically typed languages but developed a strong preference for dynamically typed languages) seems far rarer, at least nowadays where the canonical statically typed language is not C++. Personally, I think one of the killer features of statically typed languages is that they make it difficult for people to write code for which the types would be very convoluted. In other words, statically typed languages provide rails which guide poor developers toward better habits (and incidentally, these same rails make it very painful to port a lot of JavaScript to TypeScript or for many JavaScript/Python developers to use statically typed languages). From my understanding, the lisp language communities tend to select for programmers who have good habits already so they probably don't benefit from this property as much as other dynamic languages. Similarly, lisp programmers can use metaprogramming without it turning into a complete shit show, which is what almost invariably happens whenever Python programmers start dabbling in the metaprogramming facilities of their language. That said, there are other advantages to static typing besides preventing classes of errors. For example, a lot of important documentation is generated and guaranteed by the type system. A perennial problem in dynamic languages including lisps is documenting the types. If you say something is a "file-like" object, what does that mean? Does the callee require that the object has a read() method, or does it also need seek(), close(), etc? And very often you don't even get "file-like object" but rather just a terse variable name (lisps are especially guilty of this, in my experience) or the documented type is outright incorrect (typically someone changed the code but didn't update the documentation). Additionally, you get a lot more powerful tooling, because the types can be reasoned about statically (which isn't to say Closure lacks powerful tooling, but rather that its tooling is powerful in spite of dynamic typing).
- kaliszad 5y agoWell, a considerable number of people in the Clojure programming community are often people, who developed in Java or C++ for one or two decades and sometimes people how have to switch between several languages. Most that I have talked to love Clojure above all else and can see the things not contributing to the solution of the problem at hand. Static types are at the top of the list of things that contribute almost nil and cause a huge amount of development overhead everywhere. It sometimes seems in these advanced languages, static types are there so the programmer makes the job of a compiler (easier) or that you can write an academic paper, where static typing is almost a must to get it into a journal for some reason. My colleague gave a really in depth talk/ Q&A about Clojure and touched on static types at length. I think, it could be interesting for you: https://www.youtube.com/watch?v=4UoIfeb31UU https://www.youtube.com/watch?v=4UoIfeb31UU
- hawthornio 5y agoAnecdotally, I encounter almost no bugs when writing Python code with mypy and frozen dataclasses (i.e. immutable data structures), but many, very difficult to understand bugs without them.
- CapsAdmin 5y agoReading all comments here I'm not sure what kind of typesystems you are refering to. (you mention static typesystems but the discussion seems broader than that) They come in different forms. Some can rely heavily on inference (Typescript) and some need to be very verbose (Java) There are structural typesystems (Typescript) and nominal typesystems (Java) In a structural typesystem the contents of a type can be compared to another type and match, whereas in a nominal typesystem it has to be the same type id to match. The former is more dynamic than the latter. I don't like Javas typesystem but I like Typescripts typesystem because it's more flexible and doesn't force you to be verbose (you can for example only type function arguments and let it infer the rest) One benefit I haven't seen mentioned here is the ability to refactor code with confidence and less need for unit tests. For example comparing Javascript to Typescript; If I change a functions argument that is used in many places, the typesystem will give me a list of other code where the function is used I need to change in order for everything to work again.
- kaliszad 5y agoI was referring mostly to Javas nominal typesystem. Thank you for trying to make the discussion more to the point/ precise.
- ddellacosta 5y ago> In my experience and other on the team share it too, static types really haven't (or wouldn't have) prevented any bugs. In my experience, having written Clojure professionally in three different organizations over a period of close to a decade, static typing would have helped tremendously in producing maintainable software that allowed new developers to come into a project and get up to speed quickly, and build out more features without struggling to overcome the burden of endless boilerplate and incoherent abstractions, which Clojure makes easy. Which is to say, every Clojure codebase I inherited was a mess, and the tools Clojure provides to mitigate the problems of sharing a big codebase among a team of programmers are insufficient and place a tremendous burden of manual labor on industrial programmers--especially spec, which ironically produces exactly the kind of boilerplate pain and maintenance labor that Clojure apologists blanket-accuse statically-typed languages of producing. This directly and meaningfully impacts productivity and efficiency, and of course helps amplify bug creation as well. > If I pass garbage to a clearly named function, I get garbage out as with the static type system. Yep, and for the most part the only way to figure out what functions receive or return in Clojure is to either read the code, or actually call them. Relying on other programmers to be consistent and coherent in their naming is not really a great long-term approach...go figure. And, note that a side effect of this is that you often don't find out until some code is in production that you are passing garbage data around. AND that's leaving aside how badly most libraries are documented--even core libraries, how type information is rarely if ever shared in library documentation, and how Clojure doesn't enforce any kind of purity on functions so that basically, any function called anywhere can be doing basically anything. Really it's not even about not having static typing--which is not a silver bullet, and absolutely has tradeoffs--but the fact that the community seems fundamentally immature and unable to discuss software engineering topics (static typing especially) without turning it into an emotionally laden battle between tribes, vs. a comparison between different tradeoffs. Simple vs. easy indeed. I really did enjoy the language at one point, and credit it and RH for introducing me to the world of functional programming, but at this point I doubt I'll ever write Clojure professionally again. However if I do, it will be with a team that understands its strengths and weaknesses without attachment to emotionally-driven arguments about static typing, or whatever.
- kaliszad 5y ago