That is exactly how I always feel when working in Clojure. Constant "what is this? What's in it?"
You can't just say "it's a map". Sure, it's a map, but there's data in there I want so can you at least tell me what keys it's supposed to contain? Sadly the language has nothing to help me make up for the lack of documentation other than inspecting values at runtime inside a half-constructed program and this just doesn't feel very efficient compared to returning a defined data structure with specified properties.
And yet people could run circles around static typing programmers using Lisp, Smalltalk and other dynamic languages to build programs faster and iterate on them quicker.
Except if you mean "doesn't feel very robust", which I'd somewhat agree.
It's always a matter of system theory. You can have the fastest native code ever, if your system is suboptimal then it's almost moot. That's why people prototype in python or whatever (lisp and smalltalk decades ago), because they can design the system right and then tighten the organs with native code.
Except that is the whole point of spec. Yes, it’s not available for all libraries, but can always add it when you need it, and you don’t need it that often.
At which point do you consider it OK to NOT use typing for a library, or any piece of code that another programmer is going to have to use or maintain ?
I think basically never ( even for throwaway code, because they often end up being reused). So i’d much prefer a language for which static typing is not an afterthought..
Pretty much always. I mean, as a frontend developer I'm dealing with an untyped api all the time: the backend. We've written pretty huge software using many untyped services, and we're doing fine.
Who is using gradual typing in a clojure codebase? I've never seen any usages of core.typed in the wild. Using schema is more common although its future seems uncertain in the wake of spec. In my experience schemas require just as much effort as specifying types without the benefit of automatic checking or the usual IDE integrations like navigation or autocompletion. As a result they're rarely used widely enough to be useful.
This is how I feel generally when working with codebases which make copious usage of type inference.
I hate it, and think it is simply counter-productive in most cases. Though most other developers scoff and this and can't understand why I'm happy to write "unnecessary types".
I long for a language where types are mandatory and on the left. But not Java <10.
You can pry scheme from my cold dead hands. I don't mind ocaml, in fact I'd probably chose to write most kinds of software in it, but scheme is what I write to keep my soul. It is what I write to rediscover that programming is fun.
The gradual typing systems that are out there are usually enough when I want a typed module, but the tooling could improve (like, you know, getting type hints when calling a typed function from untyped code).
Do you miss the parentheses when you're working in ocaml? I'm not a huge lisper / ocaml-er, so maybe it's just that I have trouble seeing the expressions when they're not neatly wrapped in parentheses. But for that reason I tend to prefer the lisp syntax.
This is so true
Moving back from a Scala application to Ruby feels like having an arm and a leg chopped off.
However if you like safe compiled languages i can only recommend to have a look at Rust.
Having a compiler that guarantees code to be free of deadlocks and such at compile time is just incredible.
And it is not even that hard to learn compared to Scala.
Scala is a really great language. But its open syntax, which ranges from c like imperative with curly braces to points free style can be hard to grasp. Not speaking of obscure compiler messages when a library using a weird dsl is missing some implicits.
Rust being more opinionated and having less stuff shoved into it while having all the stuff you need is really great.
The borrow checker has like half the rules of the "this" keyword in JavaScript ;)
TLDR: After programming in Scala and Haskell for a while, the author has become increasingly nervous and uncertain when programming in dynamic languages like Ruby and Clojure. The author takes his own personal experience with this unpleasant sensation to mean that the era of languages like Ruby, Python, and JavaScript is ending and soon we’ll all be programming happily in Haskell... wait what?
Meanwhile the world continues on as it ever has: individual languages go through their life cycles and change and grow and fade and they each have their own strengths and weaknesses and fans and detractors, and through it all Haskell continues not to catch on.
Also, balanced software architectures designed by balanced people will continue to "alternate hard and soft layers", as the traditional precept says, in the form of convenient and easy to learn DSLs and dynamic language scripting layered above a dependable and unchanging (and therefore usually compiled and high performance) application core.
In related news, people will continue to choose the right tools for the job, for example by preferring functional languages only when managing I/O and state is trivial enough.
> But HTML is the perfect DSL for writing HTML—why replace it for another DSL with your own set of rules and restrictions, and lose the decades of tooling and know-how of every designer on the face of the planet?
HTML (as understood in XHTML) describes a certain type of tree structure. Creating this tree structure in just another DSL is perfectly fine, because it will produce HTML in the end. I don't understand the authors issue here.
I've worked in a Scala shop, it was probably the lowest performing team of developers I've ever worked with coupled with the highest amounts of bragging, theoretic talk, elitism and winging about other languages, especially dynamic langues. Is this a common theme across all Scala / Haskell communities or something ?
I witnessed many times where a solution could've been solved much more efficiently using a simple Ruby or Python service of no more than a few hundred lines but the suggestion was scoffed at.
Side note, the ecosystem around Scala seemed horrible, SBT is filth and it seems to lack good libraries for most basic tasks. For something of such advertised greatness it seems there is a lot to dislike about Scala, including dragging around a JVM.
I've worked in a scala shop, it was the highest performing team of developers I've ever worked with, coupled with the highest amounts of wanting to get shit done.
The ecosystem around scala is great, you get to use any jvm library using a relatively sane ML derived language that is safer than most other alternatives.
> Is this a common theme across all Scala / Haskell communities or something ?
I worked at an employer who used Scala for their main product. It was a pragmatic style though (mainly a Java++ if you will). So, not all Scala places are like that.
That being said, I would probably not use Scala for the same product they were building today. Kotlin is much more pragmatic, better standard library, better IDE support, and better interoperability with Java. SBT is slow and sluggish, not excusable really. But the JVM is a superior platform for building almost anything today, especially after project Jigsaw where you can ship a stripped down version of it if you choose: http://august.nagro.us/small-java.html
Much of this article sounds familiar and plausible to me, and yet my current project seems to prove it all wrong.
We're doing mostly javascript. A complex web application that displays massive amounts of complex, related data with all sorts of ways to search through it and visualise it in different ways. Fun stuff.
All javascript, so dynamic and untyped, but that doesn't matter; we're churning out new features at an amazing pace.
Still, quite often I'm wondering what kind of object I've got in my hands. Is this an Element, is it just the id of that Element, or is it something wrapped around the Element? No idea. So we quickly switch to typescript and move on. Problem is, we still haven't described our data structures, all our types are still `any`, and I still don't know what I've got in my hands. Doesn't matter, though, we're still churning out new features at a pace I've never seen before.
We switch to a graph data base, and we get our data in a completely different format, still without any description of its structure. It's not slowing us down from writing new features or refactoring our code at an amazing pace.
Alright, so someone writes up some actual classes. Only the Element type has just an id and an `element` field that contains an untyped object with all the actual data. I still have no idea what I've got in my hands, but it doesn't matter, we're still churning out new features, new designs and new visualisations at amazing speed.
So I'm not so sure that not knowing what my data looks like, actually slows down our development. We're doing fun stuff and that's what's making us productive. I would absolutely like to have all our data described by classes, and have our classes designed a bit more sensibly, and I'm sure I'm going to do that some day, as soon as I'm out of cool new features to write.
We're violating all the best practices I've always adhered to. I think we've got two whole unit tests in this project. And yet everything works, there aren't any serious bugs as far as I can tell, everybody loves what we're doing, and we're working at an unbelievable speed. So now I'm doubting everything I've always known.
How is the word "spec" not anywhere in that article? And HTML isn't statically typed anyway, so, while using Hiccup does introduce a bit of complexity, static typing isn't going to solve that, however, spec can bring back a lot of the functionality HTML-aware editors give.
But the IDE's ability to tell you depends on the language. IDE features for dynamic languages are worse because the static structure of the code is not available, so usually devolves into basic string matching. In the case of C#, the language and IDE support are developed together, and new features like async, linq etc are not considered done until the tooling (IDE, debugger etc.) supports them. It's unfair to dismiss the tooling for such languages when they were explicitly designed with them in mind.
I've been working with clojure professionally for over 4 years. The default navigation in emacs is non-existent as far as I can tell and only works at all once you've loaded the source into the REPL. Even that only works for resolving top-level vars and doesn't work for local bindings. Admittedly I tend to use cursive so this may have changed recently. But that still doesn't help you understand the argument/return types of functions etc.
maybe I don't expect as much as you do then.. I always felt a lot happier in a repl than in an IDE but I have to admit too that I didn't use IDEs a lot recently. (my last bits were scala and java graph moocs under eclipse and I was as angry as I used to be previously).
The availability of powerful IDEs is one of the biggest selling points of Java, arguably topped only by portability and the large ecosystem of libraries. The fact is, if you're writing Java, you will almost certainly be using tools that help you write correct code more quickly.
And the nature of Java is what makes that possible. The IDE knows what your data means, and it knows if you're trying to do something that isn't allowed. That's the entire point of the article: Java forces you to declare what you're trying to do, the IDE holds your hand through that, and the compiler enforces it.
I think it's mostly a fallacy. Static OOP can only do so much, and it's just a cultural side effect that your editor comes preconfigured with JDT. It doesn't help your editor to know what Factory to use to instantiate some constructor, only the author and the doc. You'll still be reading suggested method docs. It's just that your IDE .. as you say it, holds your hand.
Working in Ruby is fine if you’re just adding a feature on top of the pile of features. All you have to do is add some unit tests, make sure the old ones pass, and run away. But anything else is impossibly difficult.
No, not "impossibly difficult". Just not as effortless as you'd like it do be. Which fortunately makes it easy to discount the the rest of the article for what it is - needlessly charged hyperbole and (gross) oversimplification of what should be viewed as a substantially more complex set of tradeoffs.
> There's a slight bias here: static structures don't help discovering
OTOH, they support tooling that can, used properly, though that tooling itself increases the surface and scope that needs to be learned and accessible in using the language. (And often is less helpful than it should be, because if it often takes more what is necessary for code to function to make discovery useful, but that involved the kind of documentation lots of people avoid.)
43 comments
[ 4.8 ms ] story [ 63.7 ms ] threadYou can't just say "it's a map". Sure, it's a map, but there's data in there I want so can you at least tell me what keys it's supposed to contain? Sadly the language has nothing to help me make up for the lack of documentation other than inspecting values at runtime inside a half-constructed program and this just doesn't feel very efficient compared to returning a defined data structure with specified properties.
And yet people could run circles around static typing programmers using Lisp, Smalltalk and other dynamic languages to build programs faster and iterate on them quicker.
Except if you mean "doesn't feel very robust", which I'd somewhat agree.
Except that is the whole point of spec. Yes, it’s not available for all libraries, but can always add it when you need it, and you don’t need it that often.
I think basically never ( even for throwaway code, because they often end up being reused). So i’d much prefer a language for which static typing is not an afterthought..
I hate it, and think it is simply counter-productive in most cases. Though most other developers scoff and this and can't understand why I'm happy to write "unnecessary types".
I long for a language where types are mandatory and on the left. But not Java <10.
The gradual typing systems that are out there are usually enough when I want a typed module, but the tooling could improve (like, you know, getting type hints when calling a typed function from untyped code).
However if you like safe compiled languages i can only recommend to have a look at Rust.
Having a compiler that guarantees code to be free of deadlocks and such at compile time is just incredible.
And it is not even that hard to learn compared to Scala.
Scala is a really great language. But its open syntax, which ranges from c like imperative with curly braces to points free style can be hard to grasp. Not speaking of obscure compiler messages when a library using a weird dsl is missing some implicits.
Rust being more opinionated and having less stuff shoved into it while having all the stuff you need is really great.
The borrow checker has like half the rules of the "this" keyword in JavaScript ;)
Meanwhile the world continues on as it ever has: individual languages go through their life cycles and change and grow and fade and they each have their own strengths and weaknesses and fans and detractors, and through it all Haskell continues not to catch on.
In related news, people will continue to choose the right tools for the job, for example by preferring functional languages only when managing I/O and state is trivial enough.
HTML (as understood in XHTML) describes a certain type of tree structure. Creating this tree structure in just another DSL is perfectly fine, because it will produce HTML in the end. I don't understand the authors issue here.
I witnessed many times where a solution could've been solved much more efficiently using a simple Ruby or Python service of no more than a few hundred lines but the suggestion was scoffed at.
Side note, the ecosystem around Scala seemed horrible, SBT is filth and it seems to lack good libraries for most basic tasks. For something of such advertised greatness it seems there is a lot to dislike about Scala, including dragging around a JVM.
The ecosystem around scala is great, you get to use any jvm library using a relatively sane ML derived language that is safer than most other alternatives.
It's so tempting to hope that the right language will make everything better, but it never does.
I worked at an employer who used Scala for their main product. It was a pragmatic style though (mainly a Java++ if you will). So, not all Scala places are like that.
That being said, I would probably not use Scala for the same product they were building today. Kotlin is much more pragmatic, better standard library, better IDE support, and better interoperability with Java. SBT is slow and sluggish, not excusable really. But the JVM is a superior platform for building almost anything today, especially after project Jigsaw where you can ship a stripped down version of it if you choose: http://august.nagro.us/small-java.html
We're doing mostly javascript. A complex web application that displays massive amounts of complex, related data with all sorts of ways to search through it and visualise it in different ways. Fun stuff.
All javascript, so dynamic and untyped, but that doesn't matter; we're churning out new features at an amazing pace.
Still, quite often I'm wondering what kind of object I've got in my hands. Is this an Element, is it just the id of that Element, or is it something wrapped around the Element? No idea. So we quickly switch to typescript and move on. Problem is, we still haven't described our data structures, all our types are still `any`, and I still don't know what I've got in my hands. Doesn't matter, though, we're still churning out new features at a pace I've never seen before.
We switch to a graph data base, and we get our data in a completely different format, still without any description of its structure. It's not slowing us down from writing new features or refactoring our code at an amazing pace.
Alright, so someone writes up some actual classes. Only the Element type has just an id and an `element` field that contains an untyped object with all the actual data. I still have no idea what I've got in my hands, but it doesn't matter, we're still churning out new features, new designs and new visualisations at amazing speed.
So I'm not so sure that not knowing what my data looks like, actually slows down our development. We're doing fun stuff and that's what's making us productive. I would absolutely like to have all our data described by classes, and have our classes designed a bit more sensibly, and I'm sure I'm going to do that some day, as soon as I'm out of cool new features to write.
We're violating all the best practices I've always adhered to. I think we've got two whole unit tests in this project. And yet everything works, there aren't any serious bugs as far as I can tell, everybody loves what we're doing, and we're working at an unbelievable speed. So now I'm doubting everything I've always known.
What makes Clojure awesome - it's the REPL. Everything else is secondary.
And any criticism of Clojure just falls apart once you get to the power of the REPL. That alone could make you undeniably productive.
- Make it work - Make it right - Make it fast. In that order!
And Clojure is a language designed to build programs in that order.
Edit: Oh, 2015. Should be in the title.
But why would I ever want to?
If you get a Request object, how do you know what is in it ? the IDE is telling you, not the language.
I'm even pretty sure that until a decade ago, Emacs had a more grammatical understanding of source code than Visual Studio.
maybe I don't expect as much as you do then.. I always felt a lot happier in a repl than in an IDE but I have to admit too that I didn't use IDEs a lot recently. (my last bits were scala and java graph moocs under eclipse and I was as angry as I used to be previously).
Why?
The availability of powerful IDEs is one of the biggest selling points of Java, arguably topped only by portability and the large ecosystem of libraries. The fact is, if you're writing Java, you will almost certainly be using tools that help you write correct code more quickly.
And the nature of Java is what makes that possible. The IDE knows what your data means, and it knows if you're trying to do something that isn't allowed. That's the entire point of the article: Java forces you to declare what you're trying to do, the IDE holds your hand through that, and the compiler enforces it.
No, not "impossibly difficult". Just not as effortless as you'd like it do be. Which fortunately makes it easy to discount the the rest of the article for what it is - needlessly charged hyperbole and (gross) oversimplification of what should be viewed as a substantially more complex set of tradeoffs.
Or that is to say: a rant.
OTOH, they support tooling that can, used properly, though that tooling itself increases the surface and scope that needs to be learned and accessible in using the language. (And often is less helpful than it should be, because if it often takes more what is necessary for code to function to make discovery useful, but that involved the kind of documentation lots of people avoid.)
And again, the point is not that dynamic => uncertainty it's that static != certainty. It's static + man hours that reduce some uncertainty.
ps: remember the stubs of code in the Eclipse/UML era... that was tooling too. We got to be a little more precise.