Hacker News new | ask | show | jobs
by fit2rule 4390 days ago
There isn't really much evidence of this out there, other than groupthink, in my opinion.

What makes a language 'okay for smaller projects' but suddenly unsuitable when it gets larger? Having a minimal set of types doesn't necessarily mean you're going to have 'more bugs as the codebase grows' - the only place it really makes sense to say that dynamically-typed languages 'break' is when they don't have the types that the application needs.

In Lua's case, the only thing I can think of it missing is native floating-point support, and that's really it. Everything else: you can get there with nil, number, string, function, CFunction, userdata, and table. (But CFunction and userdata should be enough for anyone! :)

6 comments

> What makes a language 'okay for smaller projects' but suddenly unsuitable when it gets larger

As projects get larger the benefits of tooling (automated testing, automated type checking, efficient compilation, etc) become more relevant and the costs of using the tools become less relevant compared to the costs of writing the program itself.

> the only place it really makes sense to say that dynamically-typed languages 'break' is when they don't have the types that the application needs

Actually, I don't think any dynamic languages used in practice actually do this right now. Most dynamic languages only check base types (numbers, null, "object") but fail to check for higher order types (functions and objects). For example if you code

    MyClass x = new OtherClass();
    x.foo();
wouldn't it be better to get an error in the first line than an error on the second line? Specially when you consider that the method call can be delayed and only happen much latter, in some other function and without the true guilty line even showing up in the stack trace.
> In Lua's case, the only thing I can think of it missing is native floating-point support, and that's really it. Everything else: you can get there with nil, number, string, function, CFunction, userdata, and table. (But CFunction and userdata should be enough for anyone! :)

I think you're missing the point; static typing doesn't let you write more programs, it specifically lets you write fewer programs, by ruling out ill-typed programs. If I see a Haskell variable of type "Int -> String" then I can be quite confident that it's a function turning Ints into Strings; in, say, Python I can't be confident of much without analysing the entire codebase.

If nothing else, it kind of follows from Curry-Howard correspondence.

What makes it okay? This Python program will not throw an exception when ran

  def f(x):
    return x

  if False:
    f(1,2)
even though the types are wrong. Are you 100% certain that you will never make a bug like this even when there are 10^13 conditions and the call stack is deeper than the Mariana trench? Note that that this is not the only type of bugs that static typing prevents.
> What makes a language 'okay for smaller projects' but suddenly unsuitable when it gets larger?

One and one makes two. Two and two makes four. Four multiplied by eighteen is seventy-two.

Compare to:

  1+1=2
  2+2=4
  4*18=72
Notation, aka language, has scaleability as a feature, whether the designers intended it or not. Dynamically typed languages are nice, I love them for prototyping, and some of them, I think, are suitable for large scale applications. But not all of them. The notations made available in some languages just make large scale development easier or harder (for various reasons). Consider using maps/json objects to produce data constructs, this is a sort of duck typing unless you add some sort of schema checker to it. At which point it's either a runtime error or you're running your code through a static analysis tool. Why not use an actual type system for this that the compiler checks at compile time?

I feel like a broken record this past week.

Dynamic languages are good, I can't imagine doing the sort of exploratory/prototyping stuff I've done in them with typical statically typed languages. I wouldn't even object to using erlang for a large scale project (actually, I'd love to do this), it's got features in both syntax (bit syntax, I love it) and semantics (concurrency) that make it ideal for certain problem domains. It's got dialyzer which gets back a lot of the static analysis that statically typed languages offer. On the other hand, javascript offers duck typing, weak typing, dynamic typing, it's fine for certain applications (and essential for anything living in a web browser these days), but it's type system holds it back for large scale work. Experienced programmers may be able to get passed it with relatively few errors, but it's still going to suffer huge performance issues because there's only so much that can be known about the values passing through a block of code. Does `a + b` mean we're adding two numbers? A number and a string? two strings? The result changes depending on those circumstances and the interpreter/compiler just doesn't know enough to optimize it significantly. Similarly, it doesn't know that one is an error right away, the actual error may start here, but only appear in some function that's a child/parent/cousin in the call tree, obfuscating the cause and creating a great deal of work for the developer and tester.

Lua already has native floating support (by default). The number type is double by default.

Lua 5.3 (work 2 already available) introduces integer subtypes so now you can have both floating point and integers.

Similarly to Javascript, all numbers in Lua are floating point numbers and all number operations are floating point operations. Integers can be represented accurately up to 2^53.
Changing the Lua number type from a float to an integer type is something like a 3 line patch.
Right. :)