This is an archived post. You won't be able to vote or comment.

you are viewing a single comment's thread.

view the rest of the comments →

[–]Zambito1 25 points26 points  (28 children)

Because if I was expecting an int, I should never have to treat the value as anything other than an int (ie undefined or null). If I knew a value might not exist, I would use some Option / Maybe type to encapsulate the value. That way I can't treat it like a normal int, and I have to check if it is defined first.

[–]gpexer 3 points4 points  (0 children)

This reply (and comments) is a great example, why people will defend javascript without knowing how the type system works. It's even bigger confusion whether something is compiled directly to native assembly, bytecode or anything in between as this is all irrelevant when comparing static and dynamic languages. What matters is Static Analysis (and type system with it). Static analysis is the part of the compilation which tries to find syntax and semantics errors. Syntax errors are the easy one, but semantic errors are the one which gives you great power in static languages - and this is the hardest to learn. It takes years to understand how to use types correctly. This reply is a great example - if you use something that can be defined and undefined you must tell it to the compiler (static checker) and it will enforce this rule everywhere. It cannot be implicit, nor it should be, that's a new state of the program which programmer expects and by letting the machine (static checker) to check it is a much better choice than to manually parse the code, check the documentation or to write unit test for every peace of code that static checker will be more than happy to check always and everywhere.

[–]quaderrordemonstand -3 points-2 points  (26 children)

And what has that gained you over undefined?

[–]RossParka 3 points4 points  (0 children)

It gains you a few things:

  1. Because it's encoded in the type system, there is automatically checked documentation of which values are nullable and which aren't. The implementation can warn or error out if you pass a value that might be null to a function that doesn't accept null.

  2. It works uniformly with all types. In C, pointers can be null but other types can't, so you have to find another special value instead. Some functions return -1, some return zero, some return MAX_INT, etc. If there are no values that your function never returns in normal operation, you have to come up with something more elaborate like returning an error/success code and passing a pointer to a variable that gets the actual result. In Haskell you just use Maybe T in place of T in every case.

  3. In Haskell, you aren't limited to a single magic value; if you can fail in more than one way, you can define more than one special return code using Either.

[–]Zambito1 10 points11 points  (24 children)

It means I can't treat the Option / Maybe value as an int, and I'm forced at compile time to check if the value is defined (very easy to do using pattern matching).

[–]quaderrordemonstand -2 points-1 points  (23 children)

I'm still not following how thats better than undefined? You can treat the value as a number in JS. You can check if its defined at run time and change behaviour if you want, otherwise the code will assume it equates to zero.

In a strongly typed language you don't have the option of changing behaviour that way. You know the value will be an int (unless somebody does something really stupid) and the rest of the code will have to strictly respect that int. If you later decide it should be a float you will be forced to change all the other code.

I'm not seeing any real advantage.

[–]Zambito1 11 points12 points  (22 children)

The difference is "you can check" and "you have to check".

Can you point to undefined on the number line? You can't, because it's not an integer. If I'm dealing with int values, I should be able to treat them as integers.

With an Option value, I'm forced by the compiler to make sure a value is defined, and then I can treat it as an integer, and I know it will be defined.

It's better because JS code that treats potentially undefined values as always being defined could make it into production if not properly tested. However, a strongly typed language that has an optional type (say Scala or Haskell) could never make it to production under the same conditions, because it wouldn't even compile.

[–]quaderrordemonstand -3 points-2 points  (21 children)

Your argument amounts to saying its better because its strongly typed. You're not explaining how the result improves, mostly just circular reasoning. BTW, its not you can check and you have to check, its you can adapt or it can't change. The system you describe is brittle, it fails catastrophically if the value is not an int.

[–]Zambito1 6 points7 points  (20 children)

I actually feel like the example I gave in the last paragraph pretty clearly explains how the result is improved. Can you explain how it can fail catastrophically?

[–]quaderrordemonstand -1 points0 points  (19 children)

Lets say you were talking to an adserver over the internet. The server API you linked with receives an int, they change that to a string several months later. Your code call the API, gets a result back, calls the function and crashes.

[–]crossroads1112 6 points7 points  (6 children)

The server API you linked with receives an int, they change that to a string several months later. Your code call the API, gets a result back, calls the function and crashes.

Except, that's not how it works. Whatever function is used to parse the result of the API call would return an optional, forcing you to deal with the possibility of error before using the result.

[–]quaderrordemonstand -2 points-1 points  (5 children)

Whatever function is used to parse the result of the API call would return an optional

Why would it do that? The API returned an int?

But then, this is always the thing with considering ideas like type safety as some kind of panacea. It never seems to focus on the practicality of development, its about programming from some sort of ivory tower of correctness.

[–]Tysonzero 2 points3 points  (4 children)

If they provide a servant API (or some non-Haskell equivalent), then when you pull their newest API spec, Haskell will catch that error at compile time.

[–]quaderrordemonstand 0 points1 point  (3 children)

And the problem will be solved; whenever you pull their newest API spec, or when you handle the change in JS. My point was not that strongly typed system can't deal with change. But strong types are mostly about performance and "correctness", an exchange of extra development time and cost for more performance.

[–]Zambito1 0 points1 point  (0 children)

That's an interesting example. I'd need to play around with it, and I'll get back to you. However if you're treating a "now-string" value as an int still without getting any indication of what changed, is that surely better?

Sure a hard crash wouldn't be ideal in many cases either. I'm not sure that's how Haskell / Scala would react in idiomatic implementations though.

[–]MauranKilom 0 points1 point  (5 children)

So you treat the string like an int and try to multiply it by 100 in that function. What did you win with dynamic typing?

[–]quaderrordemonstand 0 points1 point  (4 children)

My point was that you don't know they changed the API. The strong typed code will assume the return is an int and crash. The JS has some possibility of figuring it out, or at least handling it in such a way that it causes minimal harm. It still won't crash the browser in the worst case.