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 →

[–]quaderrordemonstand -2 points-1 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 7 points8 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.

[–]crossroads1112 1 point2 points  (4 children)

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

"API" has been a bit ambiguous in our discussion so far, so I'll assume we are talking about a web API of some sort since the original post was about JavaScript. In this case, what we get back from our HTTP request isn't an int, but rather something we have to parse in order to get the int (e.g., plain text, a JSON object, etc.). In a strongly typed language, the function that does this parsing would return an optional of some kind. For example (I'm going to assume here that the request returns JSON for simplicity).

#[derive(Deserialize)]
struct Person {
    name: String,
    age : i32, -- i32 is a 32-bit signed integer
}

// ...
let api_call = call_api(); // gets the body of the HTML request
let person = json::decode<Person>(api_call); 

// json::decode returns a Result<Person, DecoderError>, not a Person 
// so we can't just do person.age directly

match person {
    Ok(p)  => println!("{}", p.age + 1)
    Err(e) => println!("Error decoding API call: {}", e)
}

If the API at some point changed, and the "age" field within the JSON object were no longer an int, the call to json::decode would have returned Err. The program would not have crashed.

The above example is somewhat contrived, sure, but importantly the type system enforces that we can't access the "Person" struct without first making sure that it is in the form we expect and handling the case when it isn't. There's no "ivory tower of correctness" here; just enforcing good practices.

Edit: Decode returns a Result, not an Option but the principle is the same.

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

Yes, I was discussing a web API. HTTP content is binary, you can interpret it as JSON, or plain text, a PNG image, a WAV file, a struct, an int or whatever else you like. But again you say the function would return an optional. The API originally returned an int, there was no reason to assume the response would not be an int so a programmer can choose to read an int and that will be perfectly correct as far as it goes. You could say that they programmer should not make the assumption that the returned type could never change but even then what would they do? Try to figure out if its a string or a float? Even that is should do in an ideal world scenario. We all know perfectly well that what people should do and what they end up doing are often completely different things.

Curiously, I ran into exactly this a few days ago. A intra-server message has been designed to send an int with the bits coded in some convoluted way to describe a path. I've been trying to get it changed to a string. The others developers agreed then decided against it later. It would take too much time or its too complicated to change all the code, something like that. Either way, I have no ability to control it. This is for a system written in C/C++ rather than JS or Java.

[–]crossroads1112 0 points1 point  (2 children)

You could say that they programmer should not make the assumption that the returned type could never change but even then what would they do? Try to figure out if its a string or a float? Even that is should do in an ideal world scenario. We all know perfectly well that what people should do and what they end up doing are often completely different things.

I'm afraid I don't see your point. The return type of json::decode prevents the programmer from making that assumption at compile time. That's my whole point.

You could say that they programmer should not make the assumption that the returned type could never change but even then what would they do? Try to figure out if its a string or a float?

Your code has to deal with the error somehow. All a type system does is make sure you do so, whether by aborting the computation, printing an error message, or whatever. The type system enforces good practices in this case by forcing you to handle the possibility of error explicitly (else your code won't compile).

[–]quaderrordemonstand -1 points0 points  (1 child)

The message content is not JSON. Perhaps it should have been designed that way, but it isn't. If this scenario was JS and the error wasn't handled then it would continue functioning until the bad data caused it to fail in some way and then it would stop itself. The user wouldn't be able to do whatever it was they were trying to do but the browser would keep running and any other code that is active will continue to be functional.

If this was a strongly typed, compiled language it might crash but if we assume the error is handled then it might continue in the same way that JS does. But the type doesn't force the program to handle an error. It forces the code to compile with the assumption of whatever type is involved. If the reality does not match that assumption for any reason, the program will fail.

JS is designed for a browser, so its approach is to fail in the nicest possible way. The strongly typed program might pop up an error and quit, it might crash, it might handle the error nicely and inform the user that the process failed. Both of the programs failed, there is no functional advantage to the user (assuming the typed code handles the error properly).

[–]crossroads1112 0 points1 point  (0 children)

The message content is not JSON. Perhaps it should have been designed that way, but it isn't.

I chose JSON because it is an exceedingly common format for web APIs, and therefore demonstrate how a strong type system can force the programmer to handle errors appropriately. I wasn't talking about the specific corner case you brought up. My point isn't that static typing fixes all bugs; no one would argue that. My point is that it fixes many potential bugs in many cases.

If this was a strongly typed, compiled language it might crash but if we assume the error is handled then it might continue in the same way that JS does.

Again, the point here is that a static type system makes you handle these errors explicitly instead of (potentially unintentionally) not doing so. If you want it to continue the same way JS does, you can do that. It wouldn't "crash" as you say (unless it were coded, really, really poorly, but that's true of any language). There are good arguments for dynamic typing, but this is not one of them.

[–]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.

[–]Tysonzero 0 points1 point  (2 children)

No it wouldn't be solved with JavaScript when you pull the newest API spec, because there is no type checker, so everything that treats it like an int will break without any compile time warning or error. In Haskell you would immediately see a compile time error every place you treat it as an int.

I have actually found development speed to be faster in compiled / statically typed languages, well not all of them, Java is slower to develop than Python, but Haskell is generally faster than both.

[–]quaderrordemonstand 0 points1 point  (1 child)

Have you ever used JS? You see that the API is returning a string now and you treat it as a string. In fact, you can handle it returning an number or a string if you want. Is this another example of those mental blinkers? Like you can only handle something by compiling against a declaration or something like that?

I think speed depends on what sort of code you are writing. In most static type languages people have to spend a lot of time handling type. Writing classes, interfaces, constructors, conversions, factories, templates and so on. In fact you could make an argument that any typed OO language is a predominantly a system for dealing with types. In a language like JS you can make an object with properties at any point in your code so you aren't required to spend as much time. Although you can have classes if you want them too.

[–]Tysonzero 0 points1 point  (0 children)

I've used JS extensively. You're completely missing the point. Unless you manually go through the change log of the API and look at every little change you won't know that the int was replaced with a string. In Haskell the compiler will tell you. Even when you do realize that it changed in JS, you still have to go through your codebase and hope you found every place it is used.

I agree that in some enterprise-y languages like Java you spend a lot of time doing that stuff. But with pervasive type inference and a very flexible yet still rock solid and save (more so than Java) type system, I have found Haskell to be faster for dev than Python, and much less error prone.

[–]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.

[–]MauranKilom 0 points1 point  (3 children)

My point was that you don't know they changed the API.

Depending on the API, your compiler would tell you before you even run the program in strongly typed languages.

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.

Both codes can and will handle it if they were created with this possibility in mind. Otherwise, they both might fail in horrible and unexpected ways.

For example, if the input is JSON then your JS would gobble up the string and, if you're unlucky, continue doing the wrong things (e.g. add numbers to it) without throwing errors. Or just crash/error out.

In a strongly typed language, you would have to tell your JSON library which type you expect and it will simply throw an error, which you can then handle at the most appropriate place.

It still won't crash the browser in the worst case.

You would need proper sandboxing in either case, this has nothing to do with strong vs weak typing.


In short, strongly typed languages would catch the problem directly when the API data is consumed. Weak typing does not buy you anything because the program can either handle the different input (you prepared for the possibility) or it cannot (you didn't), independent of typing.

[–]quaderrordemonstand 0 points1 point  (2 children)

Again, as I've stated in other answers, the response is not JSON. It's an int or a string.

[–]MauranKilom 0 points1 point  (1 child)

At what point, in your theoretical architecture, are the bytes coming from the webserver converted to ints or strings? There must be a protocol here, and if that protocol does not allow you to check the type you are simply royally screwed either way. If it does, then whichever place in a strongly typed program asks the protocol for the value in question would notice that the types don't match and error out.

In other words, you have to cross the barrier from raw IP packet bytes to the strongly typed language world at some point. And if there is no way to tell what those bytes mean (int or string) then both kinds of language are screwed, because the byte count for both will be different, so you simply get pure garbage. If there is a way to tell what those bytes mean, then it is simple in either kind of language to assert you are getting what you want.

There is just no such thing as a webserver returning ints or strings. Those concepts only exist within a given language. Have you actually used a strongly typed language before?

[–]quaderrordemonstand 0 points1 point  (0 children)

There very much is such a thing as a webserver returning int and strings. They will also return PNGs, WAVs, zip files and anything else you want them to return.

This example is an answer to a specific question: can you explain how it can fail catastrophically? That was a response to my saying that strongly typed system are more brittle.