Hacker News new | ask | show | jobs
by fasterik 8 days ago
Static type checking catches a whole class of programming errors for free. Writing tests costs tokens or human time, so you end up needing more code (and probably more CPU time) to achieve the same level of error-checking in a dynamic language.
1 comments

Very simplistic look, IMO. I'll add another one mostly as a counterpoint (not that I believe it is strictly true, but largely yes!).

Python is a lot more expressive than other languages and has a very terse syntax, and thus requires LLM to output much fewer tokens to achieve the same job compared to other languages.

Adding a few more tests to ensure data conformity on top of what you have to do anyway with a statically typed language still results in fewer tokens overall.

The expressiveness of a language and whether it does static/dynamic type checking are orthogonal. Type inference and generics are a thing in most modern languages. I also think you're underestimating the amount of code you need to guarantee that there are no type errors in your Python code.
You were talking about token economics: expressiveness surely matters there?
Does it have a terse syntax? I main F#, and when I have to work with Python I generally find myself complaining about how verbose it is. (Needing intermediate variables for what should have been a pipeline, the ceremony around parallelism, having to store constructor parameters as object fields, etc.)
It sure does in comparison with most mainstream statically typed languages — if you feel that way about Python, I wonder what you say about Java, C++ or even Rust or Go?

Checking some examples at https://learn.microsoft.com/en-us/dotnet/fsharp/tour, I'd say it's quite similar in verbosity — eg. no need to declare a module in Python since the code already lives in a file that is the module (plus one less indentation level for module level functions); inline function declaration and calling is thereabouts with F# slightly more terse (let vs lambda + spaces vs parenthesis); if-then more verbose in F# (no then in Python, just "if x:"); F# does not seem to need "return"...

In many cases you can avoid intermediate varibles: inline ifs, list comprehensions, lambdas, etc... Constructor arguments are a good point, but this is mostly about idiomatic use instead of language itself: you can simply do

  def __init__(self, **kwargs):
      self.args = kwargs
I'll give you one on the ceremony around concurrency, though! I have different ideas of how it should have been done to shift the cost to the language runtime instead of the developer, but alas... :)