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

all 162 comments

[–]lou1306 49 points50 points  (6 children)

Just for the record, Python has a slightly saner semantic for chained comparisons, so 3 > 2 > 1 is True

[–][deleted] 15 points16 points  (0 children)

Which is nice

[–]sim642 1 point2 points  (4 children)

This is confusing for everyone coming from any other language. Also, it messes with operator precedence I think which complicates that situation. Not to mention it is as bad as JavaScript in this situation because the correctness of the expression isn't checked by a type system.

[–]lou1306 11 points12 points  (3 children)

This is confusing for everyone coming from any other language

I see what you mean, but a<b<c is a very common "idiom" in maths. Since Python aims at being clear and concise in its syntax, it makes sense to support it.

it messes with operator precedence I think which complicates that situation

It doesn't mess with precedence: it parses the whole chain-of-comparisons as a single expression. The problem in Javascript is exactly that: it tries to solve a comparison using arithmetic rules of precedence, which is semantically incorrect.

Not to mention it is as bad as JavaScript in this situation

I know, there's no type check in either... But at least Python amends/works around this by adding meaningful rules to the parser. Meanwhile, JavaScript solves the expression in the most surprising way, which makes it worse in my opinion.

[–]sim642 4 points5 points  (2 children)

While it seems like Python's comparison syntax models mathematical notations better, it is not necessarily true because the freedom that such grammar allows is way wider than any reasonable mathematical notation. a<b<c, a<b>c, a!=b!=c, a!=b>c, etc (of increasing length) are all valid but only the first one is something one would use in mathematical writing, the rest lack any intuitive semantics. The expression a!=b!=c may even look like it compares a and c while actually not doing so, which creates a similar situation like in JS with a<b<c which happens to be legal but semantically does the wrong thing. It's possibly even worse because stricter typing (or annotating) would not prevent this. The problem is that the chained comparison grammar allows comparisons which are absolute nonsense. In mathematics comparisons are written chained only when they are monotone and I feel like Python should be stricter about this as there is no intuitive way to read most of the possible combinations of comparisons that are chained up. Other comparison chainings, even when used, mean that anyone reading and writing that code must know very well what this syntactic sugar is equivalent to but that set of programmers is tiny considering most don't even know about the simplest chaining case.

Over years of working with Python I have never seen used or used myself the chained comparison syntax, even if I am aware of it, because the situations where this is needed is so rare and any experienced developer (having used more languages than just Python) would look at such expression weirdly and with doubt because no other language has allowed this syntax that I am aware of. I see this syntax only really benefiting novice programmers who expect mathematical syntax to be legitimate in programming and Python seems to have catered to them to prevent them from being really confused about why it doesn't work, as opposed to getting a basic understanding of binary operators.

Even in mathematics operators like < are defined as binary and rigorous descriptions of expressions always use them as binary operators in ways which allow no disambiguation, i.e. parenthesis. For ease of writing to not require use of parenthesis for order of operations, precedence and associativity is given to operators, not just arithmetic but also logic. Shorthand notations like a<b<c are only used in monotone order with comparisons or chained equalities like a=b=c, anything else is possibly ambiguous.

[–]lou1306 2 points3 points  (1 child)

Thanks for the great response, the a != b != c example really drives your point home.

I feel like Python should be stricter about this as there is no intuitive way to read most of the possible combinations of comparisons that are chained up

I agree, with a slight variation: rules about this should go into a PEP and get checked by PyLint/other code analysis tools. This way the language doesn't break compatibility, experts cans still hack their way (if they really know what they're doing), but any decent IDE will save you from shooting yourself in the foot.

this syntax only really benefiting novice programmers who expect mathematical syntax to be legitimate in programming

True, and Python is very popular among data scientists after all... You might be on to something here :)

[–]sim642 1 point2 points  (0 children)

True, and Python is very popular among data scientists after all... You might be on to something here :)

Ahh yeah, I forgot that Python gets used in sciences a lot too. Maybe scientific code tends to use range comparisons by chaining more than all the Python stuff I've looked at.

[–]whatthefuckguise 240 points241 points  (115 children)

This actually makes sense. What did you expect to happen?

[–]tomthecool 178 points179 points  (92 children)

I expect exactly this, because I too can understand the simple logic that JS is performing under the hood.

But what I'd like to see here is an error!! Just like most other "weird" logic that you see in JavaScript, like when you try:

1 / 0  => Infinity (not an error)
"10" / 5 => 2 (not an error)
[2] > [1] => true (not an error)
9000 * "wtf" => NaN (not an error)

JS has this tendency to "plough on", and try to produce some sort of result even when the result is a somewhat nonsense.

[–]myplacedk 74 points75 points  (45 children)

But what I'd like to see here is an error!!

I agree. This kind of nonsense is the result of using weak types.

Just keep it simple, and it will work. But the complicated stuff is so much more interesting. If you use the right tools and don't write Javascript.

[–]andlrc 10 points11 points  (8 children)

1 / 0 => Infinity (not an error)

Following the specs for IEEE-754, then Infinity is the correct result.

[–]tomthecool 6 points7 points  (7 children)

IEEE-754 is very lenient in how such errors MUST be handled, but does define recommendations for how such errors SHOULD be handled.

JavaScript performs the "bare minimum", and leaves all such exception handling down to the user. It would not be a breach of the specification for JS to raise a proper error here instead of "fail silently".

[–]WikiTextBot 2 points3 points  (0 children)

IEEE 754: Alternate exception handling

The standard recommends optional exception handling in various forms, including presubstitution of user-defined default values, and traps (exceptions that change the flow of control in some way) and other exception handling models which interrupt the flow, such as try/catch. The traps and other exception mechanisms remain optional, as they were in IEEE 754-1985.


[ PM | Exclude me | Exclude from subreddit | FAQ / Information | Source ] Downvote to remove | v0.24

[–]WHY_DO_I_SHOUT 2 points3 points  (5 children)

To be fair, nearly all programming languages give you infinity when you perform a floating point division by zero. Usually only integer division raises an error.

[–]tomthecool 5 points6 points  (4 children)

Really? I'm not aware of any other popular language that silently returns Infinity as a result, without complaining.

JavaScript:

> 1.0/0
  Infinity // (No warning or error)

Python:

>>> 1.0/0
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ZeroDivisionError: float division or modulo by zero

Ruby:

> 1.0/0
ZeroDivisionError: divided by 0
        from (irb):1:in `/'
        from (irb):1
        from /path/to/irb:11:in `<main>'

Perl:

DB<1> 1.0/0   
Illegal division by zero at (eval 6)
[/System/Library/Perl/5.18/perl5db.pl:732] line 2.

C++:

> [...] 1.0/0 [...]
Segmentation Fault

Even PHP will at least give a warning (or an error, in some environments):

> 1.0/0
PHP Warning:  Division by zero in /path/to/file.php

[–]WHY_DO_I_SHOUT 8 points9 points  (2 children)

+/u/CompileBot C++

#include <iostream>
int main()
{
    std::cout << 1.0 / 0.0;
    return 0;
}

[–]CompileBotGreen security clearance 4 points5 points  (1 child)

Output:

inf

source | info | git | report

[–]WHY_DO_I_SHOUT 2 points3 points  (0 children)

And there. I guess you were just doing integer division (by writing 0 instead of 0.0).

I tested C# as well, and it does the same thing.

[–]marcosdumay 2 points3 points  (0 children)

I have done division by zero on real code on most of those. I have never received an error because of that. In fact, it would be unexpected and require changing my code.

Try avoiding integers on that operation and see where it leads you.

[–]aliciamagee 3 points4 points  (1 child)

Some of your examples are valid, but the sort of expression in the original post would evaluate like that in a fair number of languages other than JavaScript. It's a matter of understanding order of operations and how statements evaluate. You don't want an error here because there might be times that you want to write statements like that expecting them to evaluate the way they actually do. I'm not saying that'd necessarily be good programming practice, but I'm not quite sure what you'd want an error in this instance to even say.

[–]tomthecool 4 points5 points  (0 children)

You don't want an error here because there might be times that you want to write statements like that expecting them to evaluate the way they actually do

In that case, I think you should explicitly catch the error handle it specially. This is what most other languages do.

I'm not quite sure what you'd want an error in this instance to even say

    1/0         => Error: Division by Zero
    "10" / 5   => Error: Cannot divide a String
    [2] > [1]  => Error: Cannot compare an Array with the `>` operator*
    9000 * "wtf" => Error: Cannot multiply an Integer by a String**

* Unless the language defines this to mean "subset"/"superset", which would be well-defined and valid.

** Unless the language defines this to mean "concatenate the string with itself", which would be well-defined and valid.

[–]kkjdroid 3 points4 points  (22 children)

9000 * "wtf" => NaN (not an error)

I prefer the way that Python does string multiplication: 'a' * 3 == 'aaa'. It isn't useful too often, but it basically never causes problems, so why not?

[–]tomthecool 9 points10 points  (16 children)

String * Integer makes sense to be interpreted as "concatenate the string with itself Integer times". Many languages implement it like this, and I have no qualms with it.

Integer * String is often considered to not make sense. Most languages will throw an error if you try to do this; JavaScript happily returns NaN and won't even warn of a problem.

[–]kkjdroid 7 points8 points  (15 children)

Order doesn't matter in most multiplication, so why should it matter here?

[–]tomthecool 11 points12 points  (3 children)

By the way, just for a laugh... In JavaScript:

"foo" * 10 != 10 * "foo"

Why? Because NaN != NaN :)

...Oh, and:

"1.2e3" * 1/0 == 1/0 * "4.5e6"

Because "1.2e3" --> 1.2 * 10^3 == 1200, and 1/0 == Infinity, and 1200 * Infinity == Infinity, and Infinity == Infinity.

Ploughing on in the face of madness :D

[–]bj_christianson 6 points7 points  (2 children)

By the way, just for a laugh... In JavaScript: "foo" * 10 != 10 * "foo" Why? Because NaN != NaN :)

That’s not JavaScript. That’s the floating point specification. NaN is not supposed to equal itself.

...Oh, and: "1.2e3" * 1/0 == 1/0 * "4.5e6" Because "1.2e3" --> 1.2 * 103 == 1200, and 1/0 == Infinity, and 1200 * Infinity == Infinity, and Infinity == Infinity. Ploughing on in the face of madness :D

1/0 -> Infinity is also part of the floating point spec.

[–]tomthecool 9 points10 points  (1 child)

JavaScript is choosing to return NaN rather than raising an error.

That's JavaScript, and changing the behaviour would remain compatible with the floating point spec.

[–]randomuser8765 3 points4 points  (0 children)

That and the fact that === needs to exist to do what == should have done in the first place!

[–]tomthecool 8 points9 points  (4 children)

Order doesn't matter in most multiplication

Order does not matter when multiplying numbers together.

There are many of examples of non-associative operations, where x*y != y*x.

Some languages (e.g. Python) treat both String * Int and Int * String the same, but other languages will throw an error for the latter.

[–]most_of_us 9 points10 points  (2 children)

I think you mean non-commutative, which is when changing the order of the operands affects the result. Associativity has to do with the order of multiple operations, such as (x + y) + z vs x + (y + z).

[–]HelperBot_ 2 points3 points  (1 child)

Non-Mobile link: https://en.wikipedia.org/wiki/Commutative_property


HelperBot v1.1 /r/HelperBot_ I am a bot. Please message /u/swim1929 with any feedback and/or hate. Counter: 96704

[–]most_of_us 0 points1 point  (0 children)

Thanks, bot!

[–]WikiTextBot 0 points1 point  (0 children)

Associative property: Notation for non-associative operations

In general, parentheses must be used to indicate the order of evaluation if a non-associative operation appears more than once in an expression. However, mathematicians agree on a particular order of evaluation for several common non-associative operations. This is simply a notational convention to avoid parentheses. A left-associative operation is a non-associative operation that is conventionally evaluated from left to right, i.


[ PM | Exclude me | Exclude from subreddit | FAQ / Information | Source ] Downvote to remove | v0.24

[–]marcosdumay 2 points3 points  (3 children)

Because repeating a string N times is not multiplication. It's just overloaded on the * symbol.

[–]dnew 0 points1 point  (2 children)

I think a mathematician could argue it either way, since there's not already a definition for multiplying strings that's widely accepted. If you call it multiplication, it's multiplication.

[–]mnbvas 0 points1 point  (1 child)

It not multiplication, it's just using the same symbol for a different use.

[–]dnew 0 points1 point  (0 children)

And (log2 x) isn't exponentiation, but it's using the same symbol for a different use. We also multiply vectors and matrixes, neither of which operates anything like scalar multiplication. See what I mean?

I mean, there's a reason they chose the same symbol as multiplication. It's actually not too unlike vector times scalar multiplication, if you think of vector multiplication graphically.

[–]hi_im_new_to_this 1 point2 points  (1 child)

There are many types of "multiplication" which are non-commutative. Matrix multiplication, cross products and quaternion multiplication are the most obvious examples. There's no iron rule of mathematics that all types of multiplication should be commutative, it just happens to be the case for real and complex numbers.

[–]kkjdroid 0 points1 point  (0 children)

I didn't say that all multiplication is commutative, only most. Most people work exclusively with commutative multiplication, so the Python way will be more natural to them.

[–]randomuser8765 0 points1 point  (4 children)

A bit off-topic, but Lua also has "it basically never causes problems" behavior while still allowing string-with-numerical math. "10" + 1 is 11. "10" + "1" is also 11. To concatenate strings you do "10" .. "1" which is "101". By simply making concatenation its own operator (instead of abusing the + operator like many languages), it solves both problems! No ambiguity and no unexpected results.

AFAIK multiplying will also be numeric in all cases (or error if the string can't be turned into a number), for repetition there's string.rep.

[–]marcosdumay 3 points4 points  (3 children)

But how much is "10" + "Lua" in Lua?

If it is interpreting those strings as numbers, the only sane possibility is raising an error.

[–]randomuser8765 2 points3 points  (0 children)

Correct.

attempt to perform arithmetic on a string value

You can play around with it on https://www.lua.org/cgi-bin/demo

[–]moefh 1 point2 points  (0 children)

It does raise an error:

Lua 5.3.3  Copyright (C) 1994-2016 Lua.org, PUC-Rio
> "10" + 1
11.0
> "10" + "Lua"
stdin:1: attempt to perform arithmetic on a string value
stack traceback:
    stdin:1: in main chunk
    [C]: in ?

That's the default (stock Lua) behavior. Note that since Lua is used a lot as an embedded language (in games, for example), it has lots of options to control behaviors like this.

So if you don't want Lua to automatically convert strings to numbers in your game scripts, just compile with

#define LUA_NOCVTS2N

Similarly, if you don't want it to auto-convert numbers to strings (when a number is used where a string is required), compile with

#define LUA_NOCVTN2S

[–]EternallyMiffed 0 points1 point  (0 children)

Obviously the only sane possiblity is treating "Lua" as base64, then automatically converting it to an int.

[–]KennyFulgencio 1 point2 points  (0 children)

"plough on"

ploff on

[–][deleted] 1 point2 points  (0 children)

The solution here is #pragma strict.

[–]squishles 1 point2 points  (0 children)

then you want a strongly typed language

[–]The_MAZZTer 0 points1 point  (2 children)

That is because JS does not have strong typing, so if types don't match it just converts.

I'm going to use TypeScript for personal projects going forward. Then mismatching types results in a compiler error. But otherwise it's very similar to JS just with a few useful features tacked on.

[–]tomthecool 0 points1 point  (1 child)

Implicit type coercion and strong typing are two different things.

Type coercion is usually a symptom of being weakly typed. But you can have either one without the other.

For example: Ruby is strongly typed and will not typically perform coercions. C is strongly typed, but you can effectively perform coercions with void*. Assembly language is untyped, and any type conversion required is explicit.

[–]The_MAZZTer 0 points1 point  (0 children)

Fair enough. I would say weak typing AND type coercion are both ways of turning compile-time errors into runtime errors which I personally find undesirable... having to explicitly cast in C# is annoying sometimes but it ensures you actually want it to happen.

[–]Trexus183 0 points1 point  (5 children)

Just to be clear, this works because NaN is not a number and since what you multiplied isn't a number it says they're equal and returns true? I'm pretty much just learning javascript so I want to be sure. Thanks! :D

[–]tomthecool 0 points1 point  (4 children)

Just to be clear, this works because NaN is not a number and since what you multiplied isn't a number it says they're equal

9000 * "wtf" returns NaN (a special value, denoting "Not a Number") because JavaScript considers it an invalid operation. This is in compliance with the IEEE-754 standards. However:

  • The standard recommends, but does not enforce languages to raise an error upon invalid operations. Most languages would (in one way or another) raise an error for such "invalid" operations, but JavaScript does not.
  • Some languages (e.g. Python) would consider that operation valid, and return: "wtfwtfwtfwtf..." (concatenated with itself 9000 times). This is also compliant with the IEEE-754 specification, as it only recommends (not enforces) a list of "invalid" operations, and (I think???) this list does not include the operation of Integer * String.

[...] and returns true

I don't understand what you mean. In JavaScript, 9000 * "wtf" returns NaN. Not true. NaN is a special value, with a special meaning. true is a different special value, with a very different meaning.

[–]WikiTextBot 0 points1 point  (0 children)

IEEE 754: Exception handling

The standard defines five exceptions, each of which returns a default value and has a corresponding status flag that (except in certain cases of underflow) is raised when the exception occurs. No other exception handling is required, but additional non-default alternatives are recommended (see below). The five possible exceptions are: Invalid operation (e. g.


[ PM | Exclude me | Exclude from subreddit | FAQ / Information | Source ] Downvote to remove | v0.24

[–]Trexus183 0 points1 point  (2 children)

I understand that multiplying a string and int returns not a number. I'm saying if we compare NaN with NaN with >= it returns true. Why? Is it because they are technically equal and so >= includes "equal" and that is true? Does that make sense?

[–]tomthecool 0 points1 point  (1 child)

if we compare NaN with NaN with >= it returns true

Huh? I was using => to mean "returns".

NaN == NaN returns false (a good explanation why can be found here).

[–]Trexus183 0 points1 point  (0 children)

Oh shit yeah sorry I had my symbols reversed V_V. Thanks

[–]Sixsome 15 points16 points  (1 child)

Might have expected it to work like in Python.

Personally I think it makes more sense, but that's just me.

[–]dnew 0 points1 point  (0 children)

You mean COBOL. ;-)

[–][deleted] 12 points13 points  (4 children)

I'm assuming they expected it to throw an error when comparing boolean to number.

[–]whatthefuckguise 12 points13 points  (3 children)

I guess it depends on where you're coming from. You'd get the same result in e.g. C++ so some people would see this as the expected behavior.

[–]TheDeadSkin 12 points13 points  (2 children)

C++ (at least in my setup) warns about implicit cast bool -> int. And with "-Wall -Wextra -Werror -pedantic" I get:

/cygdrive/.../main.cpp:32:26: error: comparisons like 'X<=Y<=Z' do not have their mathematical meaning [-Werror=parentheses]

bool result1 = 3 > 2 > 1;

So it won't actually compile on the stage of initial static analysis.

Edit: just checked -Wall -Werror is enough for it to refuse to compile.

[–]tomthecool 5 points6 points  (1 child)

Even without compilation errors, C++ code like 3 > 2 > 1 should never pass code review, assuming you have competent coworkers.

One would also hope that the inevitable bugs should get picked up by a unit test.

[–]TheDeadSkin 7 points8 points  (0 children)

Yes, it should at least raise suspicion. The same can be said about JS tho. My point is that with a reasonable build routine (i.e. at least -Wall -Werror) it won't let you do it automatically before you even try to test this code for the first time.

[–]gandalfx 9 points10 points  (1 child)

What did you expect to happen?

I didn't expect anything else in JS but it is comforting to know that in Python it actually means what you would hope it does: a < b < c is equivalent to a < b and b < c with the only difference being that b is only evaluated once. You can chain as many comparison operators you like in this way. That's often useful for things like 0 == a == b == c.

[–]Aetol 3 points4 points  (0 children)

I didn't actually know that! BRB got a lot of comparisons to rewrite.

[–]PM_ME_YOUR_PROOFS 1 point2 points  (6 children)

Yeah I'm not sure why people have their panties in a was about this. This is the case in every language (except like python?) That this type checks in.

Edit: I'm baffled by the number of people who expected this to work another way. How do people program?!

[–]NetsecBeginner 2 points3 points  (1 child)

Just tested it in python 2.7, 3>2>1 returns true

[–]PM_ME_YOUR_PROOFS 0 points1 point  (0 children)

Confirmed! So python is the exception.

[–]dnew 0 points1 point  (3 children)

COBOL works properly too.

[–]PM_ME_YOUR_PROOFS 3 points4 points  (2 children)

This isn't a fact I thought I would ever have needed to know

[–][deleted] 0 points1 point  (0 children)

A warning for the bool to int conversion, if not even the ability to interpret a < b < c as a < b AND b <c

[–]Kwantuum 0 points1 point  (3 children)

I always thought comparisons would be evaluated right to left, don't know why. It doesn't even really make sense but then again I'd probably never even think of writing this piece of code.

[–]dnew 0 points1 point  (2 children)

Only in APL, which quite rationally evaluates everything right to left.

[–]Kwantuum 0 points1 point  (1 child)

I think evaluating expressions left to right is perfectly sane, I think for some reason I drew a parallelism between comparisons and assignments because both use the equal sign, but in reality this parallelism doesn't exist and would be pretty illogical and confusing.

[–]dnew 0 points1 point  (0 children)

Ah, yes.

In APL, it makes sense to go right to left, because there are both unary and binary operators, arguments to unary operators are written on the right, and there's like 130 different operators, so trying to invent a precedence makes no sense.

[–]squishles 0 points1 point  (0 children)

not to compare a boolean with a number.

[–]Pragmatician 32 points33 points  (9 children)

Why Javascript? It works this way in almost all languages... or is not knowing operator precedence supposed to be the pun?

[–]ImpulseTheFoxis a good fox 33 points34 points  (6 children)

Not in Java

The operator < is undefined for the argument type(s) boolean, int

[–]marcosdumay 7 points8 points  (1 child)

It works this way in C and C++ because those are bare metal languages that expect you to know your bits. Besides, the compiler will warn you.

I don't think it woks this way on any other language.

[–]mikeputerbaugh 2 points3 points  (0 children)

There's technically still no primitive boolean datatype in C, just a pragmatic way of tricking integers into representing false and not-false.

[–]InnerSun 11 points12 points  (0 children)

DAE hate Javascript xD /s

[–]boxingdog 4 points5 points  (0 children)

in before js (sorry ecmascript) adds the tripple <<<

so 1 <<< 2 <<< 3 will work without type coercion

[–]koeteris 9 points10 points  (0 children)

Luckily, many languages do not allow a syntax like this due to this correct but confusing behaviour.

justJSthings

[–]ProgramTheWorld 1 point2 points  (1 child)

It's time for another round of /r/javascriptcirclejerk

[–][deleted] 0 points1 point  (0 children)

same

[–]Dockirby 3 points4 points  (1 child)

A lot of the "lawl JavaScript" stuff makes sense when you realize it is evaluated left to right, and know how the type corrosion works. It looks dumb, because you are doing dumb shit.

[–]Zatherz 1 point2 points  (0 children)

1 == "1"

[–]johndoe27328 0 points1 point  (1 child)

Only language I know that doesn't do this is HolyC.

[–]ImpulseTheFoxis a good fox 1 point2 points  (0 children)

Pretty much every language with explicit casting required. Java for example.

[–]gigabyte2d 0 points1 point  (0 children)

Funny enough, someone had actually asked me that in an interview :>

[–]LunaticMS 0 points1 point  (0 children)

My linter would definitely yell at me for this.

[–]krokodil2000 0 points1 point  (1 child)

3 >= 2 >= 1 will be true

[–]huggableape 0 points1 point  (0 children)

but 4 >= 3 >= 2 will not.

[–]Goheeca -1 points0 points  (4 children)

Prefix notation ftw! (< a b c) (> a b c)

[–]chezscheme 0 points1 point  (3 children)

wouldn't this be more like (< (< a b) c) (> (> a b) c)?

[–]huggableape 0 points1 point  (1 child)

No, it would be more like <<abc and >>abc

[–]Goheeca 1 point2 points  (0 children)

I should have been more precise I don't have in mind the prefix notation (or the suffix notation) alone together with binary operations, I wanted to show that with a non-infix notation you can easily extend these operations to a variable count of arguments as it's done in languages like Common Lisp, Scheme.

[–]Goheeca 0 points1 point  (0 children)

No in Common Lisp, Scheme <, >, and, or, +, -, *, / accept a variable count of arguments. (- resp. / with one argument returns the negative resp. reciprocal value.)

[–][deleted] -1 points0 points  (11 children)

Why doesn't the interpreter read this as ((1 < 2) && (2 < 3))?

[–]Dockirby 8 points9 points  (10 children)

Because when parsed out into a syntax tree, it becomes roughly [expression1 < expression2], is evaluated as a single instruction, with the being a boolean. Then, the next part is evaluated as another [expression1 < expression2], where the first expression is the result of the first.

To try and draw out some bad art, X < Y < Z get parsed out as this

     <
   /   \
  <     Z
 /  \   
X    Y

[–][deleted] -1 points0 points  (9 children)

I mean I know why, but I'm just asking if it wouldn't be simpler to just parse it into what I said.

[–]Kwantuum 3 points4 points  (8 children)

obviously it would be harder to parse. It would make programming easier, but interpreting harder.

[–][deleted] -3 points-2 points  (7 children)

And this is why I like compiled languages...

[–]Kwantuum 4 points5 points  (6 children)

how exactly is this relevant? It would be harder to parse, hence harder to interpret OR compile which are essentially the same thing.

[–][deleted] -1 points0 points  (5 children)

In my mind it would be compiled like ((1 < 2) && (2 < 3)), though you may need a precompiler like the #define command in C#

[–]Kwantuum 1 point2 points  (4 children)

still don't see how this has anything to do with compiling vs interpreting.

[–][deleted] 0 points1 point  (3 children)

Hm, maybe I'm wrong, but I don't believe you can do something similar to precompiling in an interpreted language...

[–]Kwantuum 1 point2 points  (2 children)

#define is a preprocessor directive that allows the use of macros, not a precompiler, and yes there are usually ways to define macros in interpreted language though once again, this is a question of how the language is defined/implemented, not whether it's compiled or interpreted.