Live data from Hacker News

The advantages of static typing, simply stated

pchiusano.github.io

81–90 of 127 posts

Re: The advantages of static typing, simply stated

#81
One of my problems with static types in a lot of languages is that they're usually very limited in what they allow you to express.

For example: a function that takes an integer between 1 and 100. That's a straightforward constraint! Elixir is an example of a language that lets you express some of those kinds of constraints, by using guard clauses. Along with its powerful pattern matching, you end up with very nice code.

What are other languages that are known for these kinds of constraints?

Re: The advantages of static typing, simply stated

#82
post #45

> Is it safe to call f(x)? The author asserts that static typing allows the compiler to answer this question, but this only allows the compiler to spot type errors in advance. There are many other kinds of errors that are completely invisible to the compiler. In a dynamically typed language, if I don't spot the error from reading the code, I must wait until runtime/testing to discover the error. This is also true for…

The biggest issue with dynamic programming for me is refactoring code. I feel very confident when refactoring a static code-base. With a dynamic code-base it 's much more risky - to the point where I avoid.

Of course having great test coverage helps alleviate this, but it's very rare where a large project has 100% test coverage.

Re: The advantages of static typing, simply stated

#83
It's important to remember that the terms "statically typed" and "dynamically typed" cover a huge range of different language features. To have a good discussion about the tradeoffs, it's better to talk about individual features rather than "statically typed" or "dynamically typed".

For example,

Like puzzle pieces with shapes that we can observe fit together, we can think of types as specifying a grammar for programs that ‘make sense’.

All programming languages have a grammar for programs that make sense (it's specified by the parser). Algebraic data types give you a grammar for values that make sense. Separately, a type checker assigns types to expressions and checks that they're consistent. You can have algebraic data types without a type checker (e.g. Racket's 2htdp/abstraction), and you can have a type checker without algebraic data types.

You can also have constraints on values that are too complex to be easily checked at compile time (e.g. clojure.spec) or that can be checked at compile time but only incompletely (e.g. Erlang's -type and Dialyzer).

Anyway, I don't mean to be critical of the article: it does a good job covering the high-level tradeoffs. I just think people are too quick to generalize their experience with particular languages to entire classes of language features.

Re: The advantages of static typing, simply stated

#84

Earlier quoted context omitted.

I didn't claim it was. That's one of the tradeoffs you make in exchange for a simpler, more forgiving programming model (and the ability to do serious work in a REPL or notebook). However, given that Julia programs can be mostly type inferred before execution, it is possible to check for this kind of error before running a program. There have been some projects to do exactly that [1] [2], and I suspect that once Juli…

You did... > For example, most of these advantages apply to Julia as well... and then you listed it as an advantage.

The advantage OP was referring to was that you could force a type warning at all, as opposed to PHP, JS etc where typed arrays don't exist (notwithstanding Uint32Array and such).

Re: The advantages of static typing, simply stated

#85
post #74

Earlier quoted context omitted.

I didn't claim it was. That's one of the tradeoffs you make in exchange for a simpler, more forgiving programming model (and the ability to do serious work in a REPL or notebook). However, given that Julia programs can be mostly type inferred before execution, it is possible to check for this kind of error before running a program. There have been some projects to do exactly that [1] [2], and I suspect that once Juli…

Being able to get these errors without running the code is almost all the benefit. It enables a whole class of highly effective program manipulations that are just unavailable to a non-statically-checked language.

The claimed benefit is getting the error earlier and "at the location the erroneous value is inserted." That's exactly what happens in a dynamic language with typed collections – but, as I admitted, not at compile time. Is it better to get an error at compile time? Sure, but most of the benefit comes from the error being raised at the erroneous insertion and not later when the value is used by some completely unrelated code. Hence, my claim of getting most of the benefit. Now there are certainly other arguments to be made about "highly effective program manipulations", but that's not the case being presented by the author here.

Re: The advantages of static typing, simply stated

#86
post #45

> Is it safe to call f(x)? The author asserts that static typing allows the compiler to answer this question, but this only allows the compiler to spot type errors in advance. There are many other kinds of errors that are completely invisible to the compiler. In a dynamically typed language, if I don't spot the error from reading the code, I must wait until runtime/testing to discover the error. This is also true for…

You are right - in a tautalogical way - that type systems only catch type errors. However, in modern languages (including Haskell, Scala, as well as newer, more experimental languages like Idris), those type errors can be extremely powerful. Many people assume that 'types' are simply primitives like Int and String, and that a type checker just makes sure you don't pass an Int to a function expecting String. However,…

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.

Re: The advantages of static typing, simply stated

#87
post #45

> Is it safe to call f(x)? The author asserts that static typing allows the compiler to answer this question, but this only allows the compiler to spot type errors in advance. There are many other kinds of errors that are completely invisible to the compiler. In a dynamically typed language, if I don't spot the error from reading the code, I must wait until runtime/testing to discover the error. This is also true for…

You are right - in a tautalogical way - that type systems only catch type errors. However, in modern languages (including Haskell, Scala, as well as newer, more experimental languages like Idris), those type errors can be extremely powerful. Many people assume that 'types' are simply primitives like Int and String, and that a type checker just makes sure you don't pass an Int to a function expecting String. However,…

Yes, this is the point that's often missing in discussions about types. You can (and you have to work to) encode properties as types to get more value out of them. It's not about avoid mixing ints and strings.

Re: The advantages of static typing, simply stated

#88
post #45

> Is it safe to call f(x)? The author asserts that static typing allows the compiler to answer this question, but this only allows the compiler to spot type errors in advance. There are many other kinds of errors that are completely invisible to the compiler. In a dynamically typed language, if I don't spot the error from reading the code, I must wait until runtime/testing to discover the error. This is also true for…

> Personally, type errors haven't been the kind of errors that haunt my dreams. The point of strongly-typed systems is that you can represent your constraints as types. This takes extra thinking and work, but gives you almost almost unlimited expressive power (ref: agda). Simple example: meters and feet as different numerical types. When you multiply them, you get a silly unit (foot-meters) that doesn't fit with what…

I haven't met anyone other than Haskellians that would create separate types for meters and feet.

I also wonder when you would make that distinction in the lifecycle of your application. I suspect not until you first encounter the bug of accidentally mixing units. If so, we'd be solving the problem at the same time, just using different techniques.

Re: The advantages of static typing, simply stated

#89
post #80
post #76

Earlier quoted context omitted.

> there is high probability that my code will work correctly right away I'll bet my Python code has a similar probability of working correctly on the first run, conditioned on the complexity of the task.

> conditioned on the complexity Indeed, difference in complexity is the key here.

I'm confused. Are you agreeing with me?

Re: The advantages of static typing, simply stated

#90
post #45

> Is it safe to call f(x)? The author asserts that static typing allows the compiler to answer this question, but this only allows the compiler to spot type errors in advance. There are many other kinds of errors that are completely invisible to the compiler. In a dynamically typed language, if I don't spot the error from reading the code, I must wait until runtime/testing to discover the error. This is also true for…

"Type errors" go way further than "Damn, I passed a string in where I expected an integer". Types are a way of expressing aspects of your code. You can avoid race conditions, you can ensure a program's state is always expected, you can avoid race conditions, you can avoid design errors by encoding the contracts of your design into your types. I think if you're used to a language like Java or C++ you may not see what…

Static typing is one technique for designing safe, easy to use interfaces. Depending on the language, there may be other tools that are just as effective.
Post reply on HN