7 ms·
I think in language design there’s an expectation that if an expression or statement doesn’t make any sense, then people won’t write it that way. I think that’
by Non24Throw 6y ago
I think in language design there’s an expectation that if an expression or statement doesn’t make any sense, then people won’t write it that way.
I think that’s a pretty reasonable expectation, too.
In JavaScript, {} + [] evaluates to integer 0. That doesn’t make any sense, but it makes more sense after reading the ES spec for the addition operator.
There are many expressions you can write in dynamically typed languages that don’t make any sense, probably most of them actually, but they have to be considered valid because it’s a dynamically typed language. So they’re valid, they will evaluate to something.
The language designers aren’t so concerned with identifying every possible combination that makes no human-intuitive sense. The important part is that when it seems like types should be inferred and coerced in a particular way, then that’s how it should work. It should match human intuition.
I don’t have any intuition or opinion about how True == False is False should be evaluated, this kind of thing is going to receive superfluous parentheses from me every time for the benefit of the reader, and if someone else wrote it this way I’m always going to look it up or test it in a REPL...
10 < x <= 100 though, if that’s considered a valid expression and it doesn’t evaluate to true for numbers in the range (10,100], I’m going to stop using that language...
- pansa2 6y ago> There are many expressions you can write in dynamically typed languages that don’t make any sense, probably most of them actually, but they have to be considered valid because it’s a dynamically typed language. Not really - a language could throw an exception in these cases, as Python does for things like “a”+1. Not every dynamically-typed language is JavaScript.
- mantap 6y agoThat is the difference between a dynamically typed language (like Python) and an untyped language (like JS). The dynamically typed language checks types at runtime, whereas the untyped language doesn't.
- shrimpx 6y agoIt’s really not dynamic vs untyped, but the extent to which the language design chooses to coerce a value into a given type instead of raising a runtime type error. Python is guilty of this too with its truthy values, e.g. `if []` — an empty list of type `list` is suddenly apparently inhabiting the bool type and is equivalent to False.
- pmontra 6y agoPython (and Ruby) are dynamically typed and strong typed. They are two different things. Strong typed doesn't mean that you can't do this a = "a" a = 1 That's dynamic typing. Strong typing means only that a = "a" + 1 fails. More about that at https://en.hexlet.io/courses/intro_to_programming/lessons/types/theory_unit https://en.hexlet.io/courses/intro_to_programming/lessons/ty... JavaScript and PHP and Perl automatically cast to a reasonable value with all the advantages and pitfalls.
- dorgo 6y ago>Strong typing means only that > a = "a" + 1 >fails. String a = "a" + 1; works in Java. So Java is not strongly typed?
- sah2ed 6y agoThat’s because the language designers overloaded the arithmetic operator (+) to perform string concatenation when the operands can be cast as Strings. Without overloading the + operator, string concatenation which is a common operation, would have been unnecessarily verbose. Your example without the + operator would look like below: String a = new String(“a”).concat(1); // String object concat String a = “a”.concat(1); // String literal concat
- jakear 6y agoThe same could be said of JS but for some reason it gets shit but Java gets off Scott-free.
- simias 6y ago>In JavaScript, {} + [] evaluates to integer 0. That doesn’t make any sense, but it makes more sense after reading the ES spec for the addition operator. It's the consequence of ill-thought mechanics when it comes to type coercion. It's the original sin of many scripting languages: "let's just add a bunch of shortcuts everywhere so that it doesn't get in the way of the developer trying to make a quick script". Then you end up with a bunch of ad-hoc type coercion and the language guessing what the user means all over the place, and eventually these bespoke rules interact with each other in weird ways and you end up with "{} + [] = 0". > I think in language design there’s an expectation that if an expression or statement doesn’t make any sense, then people won’t write it that way. That's either very idealistic or very naive. In either case I'd argue that's a terrible way to approach language design. I'd argue that many well designed languages don't make any such assumptions. >but they have to be considered valid because it’s a dynamically typed language. Nonsense. Try typing `{} + []` in a python REPL. You seem to be suffering from some sort of Javascript-induced Stockholm syndrome, or maybe simply lack of experience in other languages. JS does the thing it does because it was designed(?) that way, not because there's some fundamental rule that says that dynamically typed languages should just do "whatever lol" when evaluating an expression.
- lonelappde 6y agoPython, C, Go, and even Haskell have wtfs too where language features collide. Every complex language does, as a consequence of complexity too.
- Non24Throw 6y agoI don’t write JavaScript or have a strong opinion about it. The widespread prevalence of JS transpilers and everyone’s apparent unwillingness to write pure JS makes me think it probably isn’t such a great language. It probably never had a chance given its history with browsers. Just using it to make the point that every language has valid expressions that make no sense. You can find similar examples in every language. All you have to do to find them is start writing code in a way that no person ever would or should write it. Especially in the case of dynamically typed languages, throwing an exception sometimes but not always based on the “human intuitiveness” of any given type inference would make the language even more unpredictable. It’s just instead of asking why expression a evaluates to x, we would all be asking why expression a evaluates to x but similar expression b throws an exception. If you ask me, the latter is even more arbitrary. These aren’t useful criticisms. The only reason these kind of critiques even get so much attention is because people reading the headline think: “I wonder how the hell that would be evaluated?” And so they click. The headline is only interesting to begin with because nobody ever writes that, and nobody should ever write that. If nobody would ever write it or have any expectations about its evaluation, then how is it even significant that the language will interpret it one way vs another? I think these criticisms are a good springboard to have the debate about static vs dynamic typing, but arguing over whether True == False is False should be evaluated one way vs another is kind of pointless. If the result of that argument is agreement, then we might end up with people actually writing this, which should be the last thing any of us want.
- esrauch 6y ago> In JavaScript, {} + [] evaluates to integer 0. This not really true. Put this js console and you'll see that a is the string "[object Object]": a = {}+[] When you put just {}+[] in your console its doing an empty block followed by unary-plus,like: {/*do nothing block*/}; +[]
- jakear 6y agoHuh that’s quite interesting. It behaves this way even when you explicitly make it an object literal rather than a block. I guess JS’s parser explicitly prohibits adding things to a curly-brace enclosed entity? I’m normally quite defensive of JS, but I’ll have to admit I don’t like that.
- esrauch 6y agoIt's just ASI (automatic semicolon insertion) and at the top-level {} declares a block not an object. You can also do like ({} + []) and it will actually be "adding" them; the confusion solely comes from people typing into the JS console something that wouldn't make any sense to put into an actual script.
- Zarel 6y agoHow did you explicitly make it into an object literal? ({}) + [] -> "[object Object]" will correctly make it "[object Object]" Did you try to do this? {a: 1} + [] -> 0 That's interpreted as the statement 1 labeled a, not as an object. This makes it obvious it's not an object: {a: 1, b: 2} + [] -> Uncaught SyntaxError: Unexpected token ':' JavaScript supports labels so you can continue/break multiple levels at once: { a: while (true) while (true) break a; }
- jakear 6y agoYes, I realized after the fact that I was indeed making a label. I’m now back to not having an issue with JS
- Non24Throw 6y ago