6 ms·
Dynamic Languages Are Static Languages (2011)
- mordocai 11y agoThe author's stated reasons for why dynamic languages are used may be valid (I use them because the type of job I like to get usually does) but there are real advantages to them. It is much easier to quickly prototype or experiment in a dynamic language. Note that I am thinking versus a language like Scala or Haskell where types are a integral part of the language. This applies less to languages like Java. You don't have to stop and figure out your types for every function and then go back and change them every time you figure out there is a better way to represent the data. That being said, I get their 'Dynamic Languages really just have one type' argument. I understand what they are saying. Doesn't mean we can't still use the term dynamic to describe such languages. Words mean whatever we(as a group) want them to mean.
- Others 11y agoI think the author of the article is unreasonably upset about dynamic languages. It is, ironically, restrictive to only use the most static of languages. Dynamic languages are fun to!
- mlitchard 11y ago10,000 lines of bubblegum and chicken wire is not fun. At all.
- Others 11y agoI never said you should be building 10,000 line apps in python, nor passed any value judgment. All I was implying is that sometimes it is just fun to use different sorts of languages.
- oldmanjay 11y agoI can't imagine how you are deriving an emotional state from that post.
- mlitchard 11y ago"It is much easier to quickly prototype or experiment in a dynamic language." I disagree. I can say what I mean with types, and if I didn't mean what I said, refactoring is a breeze. "You don't have to stop and figure out your types for every function and then go back and change them every time you figure out there is a better way to represent the data." You don't have to do this in languages like Haskell either. Type inference will help you most of the time when figuring out a function's type, and you don't have to use the type system as it was intended at first. You can have a prototype with Strings and Lists, the compiler won't be able to help you much though.
- falcolas 11y agoWhile Haskel has quite a few tools to help assuage issues like this, I can't help but think that niche tools do not define the genre. When I hear "statically typed", I don't think of Haskel, I think of C, C++, Go, Java, and Rust. All of these languages offer tools to handle similar duck typing via interfaces or traits or polymorphism, but they are far from simple to use. When Haskel gains a mindshare outside of its current niche, or the type inference becomes more broadly implemented in languages used across our industry, then let's talk about how it makes statically typed languages better and easier to use than "unityped" languages.
- dragonwriter 11y ago> I can say what I mean with types This is one of those things that is perhaps true in theory, but often falls short in practice. Static type systems tend to require (more or less frequent) additional incantations, but may not be sufficiently-express, even with those incantations, to express the desired intent. (Or, the required complexity of the incantations may be a greater cognitive workload than actually writing the functional code.) > You don't have to do this in languages like Haskell either. Most static languages -- particularly, the ones with the strongest standard libraries and ecosystems that are likely to support whatever it is you are doing -- aren't like Haskell.
- sampo 11y ago> You don't have to stop and figure out your types for every function and then go back and change them every time you figure out there is a better way to represent the data. Hmm, if you change your data representation from an array to a dict, say, don't you anyway need to go back and change code in every function that accesses this data?
- falcolas 11y agoFrequently the answer is no, you don't need to change every function. If you're iterating through values, are obtaining the lookup value outside the function, or just passing it along, no changes are necessary. Compared with your average statically typed language, you do have to update the function signature and everything that calls it. Now then, admittedly, Haskel is not your average statically typed language - but then again it's very rare to actually run up against Haskel in production code.
- sampo 11y ago> iterating through values I don't think you can iterate thought the values in an array and in a dict in e.g. python with the exactly same syntax. > just passing it along In languages with global type inference (e.g. OCaml) you would not have written the type in the code in the first place, so changing the type of an argument that you just pass through, would not require any changes in the code. But yes, in Haskell people are in the habit of writing the type signatures, even though the compiler does not require them, so in this case edits are needed.
- dragonwriter 11y ago> I don't think you can iterate thought the values in an array and in a dict in e.g. python with the exactly same syntax. That depends on what you mean by "values". The default iterator over dictionaries in python iterates over the keys, so if you use the exact same syntax as iterating over members of a list you iterate over the keys of a dictionary, not what are usually called the values (there is a separate iterate for that, and for key/value pairs). But, yes, dicts and lists are iterable via the same syntax since they both support Pythons iteration protocol.
- wvenable 11y agoType inference in static languages eliminate 90% of the advantages of dynamic languages including being easier to quickly prototype or experiment.
- Others 11y agoWhile the core theory of this article, that dynamically typed languages are just statically typed languages with just one type, is correct, its extensions are questionable at best. It tries to claim that it is somehow restrictive to have only one type. That is nonsense, anyone has sat down and tried to write code in both Python and Haskell can tell you it is much harder to get the Haskell compiler to accept your code. Now having such a strict compiler is great sometimes, and having a more forgiving compiler like Python's is also great soemtimes. But that observable forgiveness makes it obvious why it is silly to claim Python programmers are struggling against "the bondage of restricting attention to a single type."
- merb 11y agoAlso Python seems to look like a dynamic language, but it isn't. The type system is really not as easy as the most other interpreted languages.
- curun1r 11y agoDon't confuse static/dynamic with strong/weak. Python is strongly typed, but it's still dynamic.
- zzalpha 11y agoFYI: None of those terms actually mean anything. Or, more accurately, they mean different things to different people. There's unfortunately very little in the way of standardized vocabulary for discussing this topic in a meaningful way. My theory is that this reflects the religious nature of the discussion.
- jghn 11y agoYou can be both dynamic and strong
- psygnisfive 11y agoWhen Bob says that it's restrictive, what he means is simply that you cannot say more. Which is true -- you can't express things when your only type is "something". You're allowed to saying nothing, and that's it. And that's pretty darn restrictive!
- logophobia 11y agoThis article feels a bit condescending. Like most things, it's a trade-off. While sophisticated types do have a lot of advantages over dynamically typed languages (I spend most of my time using languages like that), that doesn't mean there's no trade-off. Dynamically typed languages are, in my opinion: * Simple * Typically require less design upfront * Easier to get started with There's real value in that. Perhaps not for the author. It's easy to scoff at languages like ruby, python or javascript and claim they're completely inferior to 'real languages', but there are completely valid reasons to use them. The real value comes from simplicity. If you use a language where runtime/dynamic typing is a subset of what's possible, you lose that simplicity.
- chc 11y agoOn the other hand, you also lose some simplicity if you use a language where the contents of a given variable could take on literally hundreds of different forms — some of which you weren't even aware of when you wrote the code — and could change form unpredictably at any time. There is a lot of complexity inherent in dynamism.
- falcolas 11y agoThe trick is, most of the time it doesn't matter. So long as it quacks like a duck, and we need the value to quack like a duck, we don't really care that it's a wolf with a duck call.
- chc 11y agoBut most of the types in your program probably do not quack like ducks. Even the ones that seem duck-like enough that somebody might deliberately pass them into your function sometimes turn out to actually honk like a goose (e.g. bytes vs. str in Python, or unicode vs. str in other versions of Python). Having used mostly dynamic languages throughout my career, personally, a huge number of the errors I've encountered have boiled down to getting the wrong type of thing — an unexpected null, a Business where I expected a Person, an array where I expected a string, an escaped HTML string where I expected an unescaped one, etc. Sometimes they quack kind of like a duck, but still do it differently enough to trigger faulty behavior (e.g. people and businesses both have names and addresses, but the latter can be in multiple places at the same time). It usually works right, but in the cases where you're passing sensible types, you'll probably be OK in a statically typed language too — not always, but usually. Static type systems introduce some edge cases where you need to think about the type system even though you shouldn't have to, and dynamic type systems introduce other edge cases where your program's behavior can be unexpectedly brittle. They're both kinds of unnecessary complexity.
- rhaps0dy 11y agoThis is not exactly the point the article talks about, but it's irked me for quite some time. When you see the documentation for a library in a dynamic language, it looks the same as if the language was static: the class of all the arguments and what the functions return is specified. So in the end you end up using it just like you would a static language, but with all the type checks done at runtime instead of before. This doesn't make much sense if you want to avoid errors.
- woah 11y agoSure, that's the common argument, but static languages often require a bunch of gymnastics to get the compiler to accept valid code. They have a lot of abstractions that are not even necessary in dynamic languages.
- rhaps0dy 11y agoThe gymnastics part is correct. You have to convince the compiler the code you are producing is correct, even if it may be correct already. However, this makes your code way more unlikely to crash or be incorrect. The "lot of abstractions" is the distinction between type and class the article addresses, I guess?
- loup-vaillant 11y ago> static languages often require a bunch of gymnastics to get the compiler to accept valid code I'd rather do the gymnastic and have the compiler tell me where I screw up right away. That's a tighter, more accurate feedback loop than a REPL. (Source: trying to implement a simple depth first search in both Lua and Ocaml.)
- dllthomas 11y agoAnd of course, you can still have the repl :D
- dragonwriter 11y ago> Sure, that's the common argument, but static languages often require a bunch of gymnastics to get the compiler to accept valid code. There's really two problems hidden in that that deserve to be considered: (1) Static languages with insufficiently-expressive type systems may require more complex code (in terms of actual operations, not just type declarations) for the code to be valid when compared to dynamic languages (or static languages with sufficiently-expressive type systems.), and (2) static languages may, depending on the situation and the completeness of their type inference system, require arcane incantations to the type system before it accepts that correct code is, in fact, correctly typed. Some statically-typed languages are good on one or both of these measures, and so make less of one or both types of problems (Haskell, IMO, is pretty good on both, as static languages go, but lots of more popular static languages are really bad at one or both.)
- snissn 11y agoFor me the big difference between dynamic and statically typed languages is catching bugs like: foo = bar() if foo: fooo = baz() in a static language, you'd have to write int foo = and the third line where you have an assignment fooo would be caught by the compiler. Of course there's advantages to dynamic languages, like being able to write something like mydata = {} mydata['foo'] = {} mydata['foo']['bar'] = MyObject() without a lot of boilerplate
- hayksaakian 11y agothanks to tab completion i virtually never run into this bug in javascript or ruby
- snissn 11y agocould you share what editor and what, if any, plugins you're using?
- hayksaakian 11y agosublime text 3, out of the box. the only plugin i have is ES6/Babel syntax highlighting. it mostly "just works"
- chc 11y agoThat's not really a difference between dynamic and statically typed languages — what makes the difference here is having different syntax for variable declaration and assignment. It so happens that most dynamic languages use the same syntax for both, but there's nothing about separating the two that requires static typing. For example, strict mode JavaScript is a dynamic language that can detect this error, because JavaScript uses var to declare variables.
- SomeCallMeTim 11y agoThat's what linting is good for, at least in JavaScript where you have optional "var" declarations: You can set jshint to flag as an error any assignment that isn't part of a "var" declaration (or any reference that isn't explicitly defined), which will catch (at compile time) any variable name typos. It won't catch this.fooo, though, so it's only a partial solution. My editor has great completion, though, so as long as the string is IN the file somewhere, I usually autocomplete it. Way fewer typos that way. I see there's a PyLint, so MAYBE it has a way of spotting typos like the one you cite? Not sure how it would work in Python, though, other than on variable reads.
- haberman 11y agoYou can apply this same idea to serialization formats. JSON doesn't have a schema. On the other hand, you can think of all JSON values as belonging to this Protocol Buffers schema: message JsonArray { repeated JsonValue value = 1; } message JsonObject { map<string, JsonValue> properties = 1; } message JsonValue { oneof value { JsonObject object_value = 1; JsonArray array_value = 2; bool is_null = 3; bool boolean_value = 4; string string_value = 5; // Represented as a string because JSON doesn't restrict the // range/precision of numbers. string number_value = 6; } }
- girvo 11y agoSo, this is something I've been thinking about recently: do you gain much by using Protocol Buffers (et al) for a client-side web application's communication with a server? Having JSON/XMLHttpRequest in the browser by default is such a boon that it'd have to be a lot better as a serialisation format for it to be worth it, but that might actually be the case?
- deleted 11y ago[deleted]
- niccaluim 11y agoHaving gone back and forth between statically and dynamically typed languages a few times now, I have to say that this comment sums it up for me: "expressing and enforcing invariants in the program itself is so helpful that it’s just ludicrous to deprive yourself of them." It's the single biggest problem I have when I work in a "unityped" language.
- dllthomas 11y agoGod yes.
- aero142 11y agoI've gone through the same transformation but I think you aren't appreciating the larger picture. Having the ability to specify both compile time and runtime invariants are both useful features. Java is good at expressing invariants around datatypes that looks like hardware data storage but it is so restrictive around interfaces that it is easy to paint yourself in a corner. Since Java was the mainstream typed language, people saw what could be done in languages like Python without such enforced rails, that many people decided the expressiveness was worth the tradeoff. I think Java 8 is much better about the tradeoff, but ultimately I think we haven't invented the system for expressing invariants in a language that makes the best tradeoffs between expressiveness and flexibility.
- unabst 11y agoAnd for those stuck using javascript but with they had static typing there is: http://flowtype.org/ http://flowtype.org/ The arguments for flow seem to resonate nicely with the points raised in the article.
- mlitchard 11y agoI shall stick with fay https://github.com/faylang/fay/wiki https://github.com/faylang/fay/wiki and the like.
- kelvin0 11y agoI like the fact that interpreting subjectively what 'Dynamic' and 'Static' means for a language, the author is able to pull a rabbit out of his proverbial hat ... except that we see the hole beneath the hat, and the rabbit is a dead rat. Clearly programming in Python vs C++ is a world apart in terms of how 'fast' you can get simple things up and running.
- rhaps0dy 11y agoThe author specifically says C++ is too restricted, and that it makes no distinction between the "class" and "type" the author is talking about. C++ has no sum types (afaik, the language is so huge I might very well be wrong)
- dllthomas 11y agoC++ (like C) has union, with which you can build tagged unions (aka sum types).
- kelvin0 11y agoBe that as it may, the tone of the article is clearly written 'looking down' at the readers, and tries to rack up some points by showing 'how smart I am (author) to be able to correct most of you...'. If he simply described that the definition of the terms, with some examples and then lead into his point to correct the 'popular' assumptions, it would have been a lot better than feeling like you're being lectured from the pulpit on a Sunday morning.
- AnimalMuppet 11y agoThe last line of the article: "Let a thousand flowers bloom - as long as they're all static." More to the point, things that are formally equal to each other do not necessarily have equal value in certain uses. (For example, think about Stokes' Theorem. It says that an integral of a function on the boundary of a manifold is equal to the integral of the derivative of the function on the whole manifold. That's useful precisely because sometimes the integrals, while they have equal results, are not equally hard to do.) A dynamically typed language may be formally equivalent to a static unityping, interpreting the tag at runtime. That doesn't mean that they're equally easy to use, though. When I want to do that kind of thing, I want to do it like it's dynamic, not where I have to do the book-keeping to make it dynamic.