7 ms·
I'm curious what the proponents of dynamic typing over static typing think about the recent push towards adding type systems to the two biggest dynamic language
by m0meni 8y ago
I'm curious what the proponents of dynamic typing over static typing think about the recent push towards adding type systems to the two biggest dynamic languages out there: Python and JS.
- brightball 8y agoIMO it’s that people coming from static languages to dynamic languages want them. I honestly can’t think of anybody in my career who’s been comfortable with dynamic languages that had a desire to move to static. It’s such an impediment to the entire programming style that it doesn’t naturally happen. On the flip side, I know plenty of static typing people who don’t seem to think they can function without it. No matter what your preferred language, Python and JavaScript are almost unavoidable and because of that I think you see a lot of stuff like this brought to the table to help make people more comfortable. Python for sysadmin, math, ML, etc. Javascript for browser. You see a lot of the same thing in the Elixir community with its gradual type system. I can’t tell you how many times I’ve seen the discussion from people who want it to be statically typed, but neglect that all of the guarantees from it go out the window with distributed nodes.
- m0meni 8y agoCould you elaborate on that last point regarding elixir and why type systems don't work for it? I couldn't find anything when I did a cursory search on google.
- jerf 8y agoI like to use a cellular metaphor for programs, where you convert incoming data to either internal representations or errors as soon as possible, and delay converting to external representations as long as possible on the way out back into the "unfiltered world", but inside the cell things are considered "clean" and trusted. Type systems fit this point of view very naturally, because they can define that "clean view" of the world and enforce that you do the conversions early, because otherwise you won't have the target types. However, a "cell" has to be local, within a context where for instance it can count on having a stable view of the types and what they can do. (This being Erlang/Elixir, we can talk about upgrading running processes, but in that case, you have to provide a conversion function as well, though the default and common one is the identity conversion. Still, there is a conversion process.) Once you have a system with multiple contexts, which you can't help but have if you're crossing machines but even just across OS processes you ought to behave as if you have a separate context, the type system is less helpful. You can't take a message from a foreign node of type X!foreign and simply assume it's of type X!local, because you do not know in the general case whether the foreign and local concept of X is the same thing. Perhaps they are different versions. Perhaps they aren't even the same program. At a sufficiently large scale or with sufficiently bad luck, perhaps the foreign node is actively lying to you in a attempt to hack you. You end up having to serialize from the foreign node to the local one, and then deserialize on the local node, in order to communicate. Especially in a world where nodes can upgrade their code without so much as dropping their TCP connection to you or something. So there is a point of view from which having strong types at the language level isn't all that helpful to this process, because even having strong types doesn't let you escape from these issues. You can do all sorts of automated stuff to try to escape from the code boilerplate aspects of this problem, but you can not fully wrap the semantic problem of "this message, no matter how hard we try to abstract this away for you, may be invalid by local standards". How much this matters to you depends on how distributed your system is. If you've got a 3-node Erlang/Elixir cluster that you fully control all the code for, you might be able to get away with just ignoring the issue. Like many other programming issues, at small enough scales it doesn't matter and you can just ignore it. But as you scale up it becomes an inevitable problem you must program for; consider something like an AWS API for S3 or something, served by a few different servers and consumed by thousands of clients using every possible version of every SDK Amazon has ever put out and who knows how many home-grown implementations. Types can define the communication contract at that level, but provide zero guarantees to a server about what it's going to receive.
- m0meni 8y agoThat's an amazingly comprehensive answer. Thanks! So basically, when interacting with the outside world at scale, it's very hard to make any sort of guarantees about kind of data you're working with. And since you have to validate the shape of your data already, you're doing the job of the type system yourself, which makes it less useful to have one. Did I get that right? Aren't these issues only at the boundaries where you're receiving data from the outside world? Wouldn't it still be helpful to have a type system/static analysis at the local level?
- jerf 8y ago"And since you have to validate the shape of your data already, you're doing the job of the type system yourself, which makes it less useful to have one." I'd say it's more like you don't get the imaginary benefit of being able to skip that checking. And yes, a type system can absolutely help you with this, especially in terms of enforcing that you do this conversion (since the incoming byte[] stream is not going to be any of the types you actually want, even at the brute "int" or "char" level, let alone user-defined types). But there is certainly a sense in which this doesn't especially help you with dealing with remote nodes.
- brightball 8y agoIt looks like it's already been answered pretty thoroughly. The cell analogy works really well. I tend to describe it more akin to REST vs WSDL regarding the necessity of exchanging contracts between WSDL participants when there is a change to adhere to the structure.
- RussianCow 8y ago> I honestly can’t think of anybody in my career who’s been comfortable with dynamic languages that had a desire to move to static. It’s such an impediment to the entire programming style that it doesn’t naturally happen. Really? Anecdotally, I have the exact opposite experience: I know many devs (myself included) who had always used dynamically typed languages but got "hooked" on static typing after trying it in a decent language (Swift in my case), but I can't name a single person who went the other way. In my experience, if you use a modern statically typed language with a solid type system, after the initial learning curve, the type system stops being an impediment to probably 95% of the code you write. In return, you get some really nice guarantees about your code, and what would be large and tedious refactors in a dynamically typed language now become a breeze. And if you bolt static typing onto a dynamically typed language, you get the best of both worlds: safety guarantees by default, and the full expressiveness of the underlying language when you need it. Personally, I'm excited for these tools because I write code in dynamically typed languages every day, but I strongly value the benefits of static typing. This way, I can have my cake and eat it, too.
- brightball 8y agoI really think a lot of it depends on your stack. On the web application side, I find static typing to be entirely an impediment - usually because the types that I really care about are already defined at the database level. Every statically typed language I've worked with on the web just ends up forcing you to duplicate the same already defined structure in multiple places, writing a ton of extra code that provides marginal benefit but creates a major negative impact on productivity. For many other areas, especially on phones, embedded devices or desktop software static types will make a lot more sense. I think languages where the primary focus is data exchange the benefits are less pronounced. That's just my experience though.
- RussianCow 8y agoBut it's still incredibly beneficial to annotate the edges of your API. Not only does that quickly catch mistakes where you break the API contract, but it also serves as built-in documentation on the shape of the data you are serving, especially if you are using a dynamic format like JSON. And that's the beauty of having static types in a language like Python: you don't have to annotate everything, and can be selective about where you apply static typing to get the most bang for your buck.
- joshuamorton 8y ago>I honestly can’t think of anybody in my career who’s been comfortable with dynamic languages that had a desire to move to static. It’s such an impediment to the entire programming style that it doesn’t naturally happen. I'm someone who would be described as a pythonist. I learned CS in python, had a quick foray into Java (which I'm not particularly fond of), and then have done the vast majority of my coding, both personal and professional, in python. I'm a huge proponent of type hinting. Reasons for this: - It's not really an impediment. Quality code should already have APIs notated with argument and return types. Converting docstrings to mypy is easy. - It's optional. You have some weird super dynamic magic nonsense. Cool, annotations are optional. Don't include them on your metaclass-generating decorator function. Being able to opt out of the safety guarantees easily is really really useful for those cases where you do want to abuse dynamism. - Its super useful. I catch bugs faster now. I write less buggy code. Refactoring is much, much easier (mypy highlights the lines where I'm now doing bad attribute accesses etc.). Some of these things can be provided by a good ide, but I'm often not in an IDE, and this way I can run it as a pre-commit hook. Agreed that for sysadmin work its maybe not as helpful. For math and ML, I think it is. There are issues that make numpy/tensorflow really difficult to typecheck internally, but there's active work on that front as far as I know.
- david-cako 8y agoWhen I first started programming seriously (which happened to be early node.js, before any of the type systems), the lack of types was aneurysm inducing. That, combined with the tendency for libraries in dynamically typed languages to have less than ideal object documentation is very frustrating. It seems impossible to keep track of data flow in any decent sized project, and otherwise tedious. I don't know whether this is an unpopular opinion (seems like it might be?) but I would never tell anyone to start with a dynamically typed language.
- chubot 8y agoIt seems to be a pretty clear case of "failure by success". Python, JS, and PHP were so good for developing applications that many people wrote huge ones in them -- including companies that made billions of dollars like Google, Facebook, and Instagram. GMail and Google Maps broke new ground in terms of JavaScript applications (using the Closure compiler, which is probably almost 15 years old now.) At the start, those languages tended to be used for 100-line, 1000-line projects. They work really well in those domains. 5K lines works fine for single person projects too. Once you get to 10K- and 100K- line projects, and you have 10+ people on a project, types start to make sense. You can't change 10K lines of code at once, so you might as well have some rigidity. Also note that you can do a lot more in 10K lines of Python than 10K lines of Java, C or C++ -- and in the 90's, when those languages came up, those were basically your choices.
- rzimmerman 8y agoI think there are advantages and disadvantages to developing a project in a statically typed language just like there are for a dynamically typed one. For a lot of projects, Python makes sense because of the very deep and rich set of packages out there. It's also much easier to make something quickly if you're not fighting the compiler or a type checker. But it's not binary and there are plenty of good reasons to have static type checking. I personally went through an exercise where I applied type annotations to a large Python project and found a good amount of bugs just by type checking. I think having the flexibility to add type annotations later, only apply to parts of a code base, and allow some violations is a great middle ground and makes Python a much more attractive option for large code bases.
- bjoli 8y agoI doubt most of us really care. In fact, working in gradually typed systems is probably what I like the most. I am however pretty unconvinced by the superiority of static typing. Being able to let the compiler verify the types for me in compartmentalised pieces of my software is very nice an all that, but for me I doubt it has caught many bugs. I think a lot before writing code, and what comes out usually works on the first or second try.
- neves 8y agoA huge difference is that these languages doesn't force you to use type checking everywhere. You can use just in the more complex pieces of you source code. It would be nice to see how tools, like refactoring, would handle it.