3 ms·
You make a good point, so I'll answer in parts. First, when most people talk about static typing, they're talking about the near-useless version -- just types
by xapata 10y ago
You make a good point, so I'll answer in parts.
First, when most people talk about static typing, they're talking about the near-useless version -- just types like Int and String. I think we agree there, so I won't mention it further.
Second, a dynamically typed language like Python has more typing information than some folks first assume. Python's AttributeError is quite similar to a TypeError. In fact, with old-style classes (v2.1 and earlier), many errors that are now TypeErrors were AttributeErrors. Calling len() on an inappropriate object would raise "AttributeError: no __len__". In many cases where folks talk about wanting a static type system, they really just want interfaces.
The Sanitized string example is a good counter-point because the interface needs to be near-identical to a regular string. I'm not certain a more complex memory representation (caused by defining a different class) would cause noticeable inefficiency. We're probably not doing vectorized operations on strings.
This brings me to my third point, that Python 3 has a similar split between two types: bytes and str. The memory representation is slightly different, bytes vs unicode, but the interfaces are nearly identical. Two differences would be decode vs encode and that getting an element from bytes (annoyingly) gives an int. The distinction between the two types is enforced mostly inside builtin functions, implemented in C. This was a big deal, causing backwards incompatibility, many flamewars, and we're still resolving it, though I think it's clear to most people now that Python 3 is the future.
Is it possible that the Python 2/3 split could have been avoided if we had a static type system? Perhaps, if we had multiple dispatch, the function signatures could have remained the same, avoiding backwards incompatibility... I'm just speculating here. My guess is no, getting rigorous about unicode would cause incompatibility regardless of the type system. I'll get back to the main topic now.
> Now your type checker can catch SQL insertion vulnerabilities for you.
This sounds useful, but a good interface solves the problem just as well. I'm a Pythonista (if you haven't noticed), so my example is PEP 249 that specifies a DB API for all database wrapper implementers to follow. It states that it's the wrapper dev's responsibility to implement a sanitizing string interpolation for the cursor's execute method.
My conclusion is that designing a good interface is important whether you have dynamic or static typing. Static typing errs on the side of safety, dynamic typing errs on the side of flexibility. Both can mimic the other. Arguing that one is better is like saying linear regression is better/worse than k-nearest-neighbors.
- the_af 10y ago> First, when most people talk about static typing, they're talking about the near-useless version -- just types like Int and String. I think we agree there, so I won't mention it further. I don't agree. Who is "most people"? Certainly not PL designers and not most of what I've seen here in HN. More importantly, it's also not what the article under discussion is saying, either. > Static typing errs on the side of safety, dynamic typing errs on the side of flexibility. Both can mimic the other. Arguing that one is better is like saying linear regression is better/worse than k-nearest-neighbors. In my experience, this isn't true. Modern statically typed languages have all the convenience of dynamically typed ones, such as REPLs and elegance, plus the safety of early warnings and the guidance that static types give you while writing your code (if you've ever written code like this, you'll know the feeling of working with building blocks that "fit" with each other). So you can have your cake and eat it, too. Also in my experience, not having experience with these languages is what leads some people to think their type systems can only state trivial things such as "this is a String". They can do more. They can say things such as "this expression/function doesn't write to disk as a hidden side effect", which is useful!
- xapata 10y ago> you can have your cake and eat it, too. Like a dynamic language with optional type hints? As I said, both techniques can mimic each other, with the corresponding tradeoffs. As you use more generics in a statically typed language, you're sacrificing safety. As you use more type hints in a dynamically typed language, you're increasing syntax clutter and decreasing flexibility.
- wz1000 10y ago> As you use more generics in a statically typed language, you're sacrificing safety Actually, in languages like Haskell, the more generic your type, the more "safe" you can expect it to be. As an example, consider a function that gives you the first element of the tuple you pass to it. The most generic type of this function is fst :: (a,b) -> a However, it can also have the type fst1 :: (Int, Int) -> Int Now, you can be sure of the behaviour of fst immediately by looking at its type, but that doesn't hold for fst1 Pretty much the only definition of fst that the compiler will accept is fst (x,y) = x However, the compiler will accept all the following definitions of fst1 fst1 (x,y) = x+y fst1 (x,y) = x*y fst1 (x,y) = 2^x fst1 (x,y) = 7 ...