Hacker News new | ask | show | jobs
by 567arlo 3205 days ago
This being a result of JavaScript's weapons grade weak-typing, I've always wondered of what benefit weak typing actually brings, once dynamic typing is assumed, over strong typing as in python/Ruby. Or at least stronger typing. Reasonable coercion from 11434 -> "11434" is one thing, but why not throw an exception when anything more ambiguous is encountered? It would seem even for an absolute newcomer to programming, or someone experienced who wants to rapidly prototype, the bugs resulting from this hidden coercion complexity outweigh any gains in productivity. Especially considering the alternative is simply a set of special unambiguous casting functions that could be easily looked up.
2 comments

> I've always wondered of what benefit weak typing actually brings

It makes your code crash less, and I would argue that in many cases that's desirable. I think it's a bit sad that the default behavior for computers is often to completely give up on the sight of any error. If you're running code in development or need to worry about data integrity, it makes sense to fail quickly and loudly, but if the analytics system or the "like" counter or some other non-critical feature crashes for a real user, it's a much better UX to degrade that feature rather than taking down the whole page.

I think the "avoid crashing at all costs" mindset was especially sensible when the web was viewed more as a collection of documents, with JS existing to give light optional enhancements rather than drive the core functionality. Imagine opening a Word doc or a PDF and having it crash because the author made a mistake. These days, I would certainly prefer that JS be more strict by default, especially in development.

I think the right way to handle the situation these days should be to define boundaries where a crash in one part of the code is contained to its boundary, e.g. React error boundaries ( https://facebook.github.io/react/blog/2017/07/26/error-handl... ). I also think it's useful to have a variant of "assert" that just logs a warning and continues in production, since in many cases that's the desirable behavior.

> It makes your code crash less

Wait, can you back this up? What makes you think strongly typed languages crash more than weakly typed languages? What's a scenario where a strongly typed language will crash at runtime, but a weakly typed language won't?

I can see an argument that an interpreter of a weakly typed language will let you run a program with dangerous type conversions without complaining, while a strongly typed language won't even let you execute it - but are you counting that as a crash?

To be clear, I'm talking about strong/weak typing and static/dynamic typing as distinct concepts. My comment mostly applies to dynamic-typed languages.

In JavaScript, `1 + {}` gives the string `1[object Object]`. In Python, `1 + {}` crashes. Neither language has a static type system, so neither language is able to disallow an expression like `a + b`; it needs to actually execute the code to find out that you're adding two things that don't make sense. I think most examples of "Python is stronger-typed than JavaScript" are of that form; Python crashes while JavaScript silently does something that may or may not make sense. Accessing a missing property, accessing an array out of bounds, and calling a function with the wrong number of arguments are also examples where Python crashes and JS doesn't.

So "crashing less" is pretty much inherent in my (simplified) definition of weak typing, and not meant to be anything controversial.

Why is crashing less often better in these cases? When it crashes, you know there is a problem with the code that needs to be fixed. When it doesn't, you might have nonsensical results that you're not aware of.
It depends on the exact context, but I think that in many cases, it's better to present wrong data to the user than to crash the page, since crashing the page makes it useless. Let's say Facebook accidentally introduces and ships some bug when computing the "like" count on about 1 in 5 news feed items. I could imagine two scenarios:

1.) The JS code crashes and the Facebook news feed page breaks for basically everyone. The flood of errors is reported to the error monitoring system and Facebook engineers frantically fix or roll back the problem to limit the amount of time Facebook is unusable.

2.) 1 in 5 news feed items shows "NaN people liked this", but Facebook is otherwise usable. The flood of errors is reported to the error monitoring system and Facebook engineers frantically fix or roll back the problem to limit the amount of time the weird "NaN people" message is shown.

Scenario #1 is a really bad outage, and scenario #2 is a temporary curiosity/annoyance that most people don't notice, and hopefully it's clear that scenario #2 is a better situation for everyone. But it really depends on context; if the bug is "a bank's website shows incorrect account balances", then crashing the page is probably a better user experience.

I'm certainly not saying JS got it right; JS doesn't do the part from #2 where it alerts you if there's a non-fatal error in production. But I think the basic idea of error resiliency has plenty of merit.

The problem with "avoid crashing at all costs" is that the alternative is usually "produce invalid output". The latter doesn't sound so bad in theory - but in practice, it means that the resulting bad data can go quite a long way, further accumulating errors as it flows through the pipeline. Worse yet if there are any observable actions taken on the basis of bad data (like, say deleting a file, or deciding to show some piece of private data).
Python 2 has some strange behaviour of its own with regards to comparing objects of different types, for example:

    >>> None < 0
    True
    >>> '0' > 0
    True
Granted, this follows a much simpler rule than Javascript's comparison operators, and both throw TypeError in Python 3.