if (x = 3):
Intended, or not? if (x = 3):
Intended, or not?When your assignment operator is "←" you are never going to confuse assignment for comparison.
Assignment:
a ← 23
Comparison:
a == 23
Extending this to something like Python: # Assignment
if x ← 3:
do_something()
# Comparison
if x == 3:
do_something()
In fact, you could argue that once you have a dedicated assignment operator you no longer need the "==" construct, because "=" is enough, which is precisely how it works in APL. The above examples the, would become: # Assignment
if x ← 3: # x is assigned 3 and then evaluated
do_something()
# Comparison
if x = 3: # Is x equal to 3? It even reads exactly as it is meant
do_something()
So, if we want to reduce error and this kind of ambiguity the solution isn't to now have two different assignment operators using easy to mistype characters but rather to have distinct symbols that cannot be confused. Hence the genius of APL, where the notation is, as Iverson put it, a tool for though and the abomination of J, where notation was tossed out the window in favor of ASCII soup.The ambiguity could be resolved easily by adopting notation that makes sense. Why do we use "A*B" for multiplication when we can use a proper multiplication symbol "A×B"? Or division? "A÷B" Not to mention the logical comparisons; Or:"A∨B", And: "A∧B" , Nor: "A⍱B", Nand: "A⍲B" (these are real symbols used in Logic, BTW, as well as APL).
It was to avoid that ambiguity (or error prone pattern, if you prefer) which is present in, say, C.
More accurately, in Python it would be:
if x = 3: # x is assigned 3 and then tested
do_something_here()
This is different from: if x == 3: # x is compared to 3
do_something_here()
Very clear difference between the two statements.What if we want to assign and then compare?
if (x = 3) == y:
do_something_here()
or... if x = 3; x == y: #Python evaluates left to right...
do_something_here()
In fact, you could... if x = 3; x == y; x = x + 1: #Python evaluates left to right...
do_something_here()
Not super elegant, but it makes sense. I wouldn't want to write code like that in any language unless it was very well justified.What if we want to compare and then assign?
if x == y; x = 3: #Python evaluates left to right...
do_something_here()
Side note: Why, oh why, don't we have pre and post increment/decrement (++/--) in Python? Another religious decision.I guess I am having trouble seeing where this ambiguity might be. What is ambiguous about usage that is currently not legal and is later defined as a new way to make assignments?
In other words, nobody is using it that way today because it doesn't work. Tomorrow we say: From now on, you can make assignments inside of several conditional statements.
What's ambiguous about that?
This isn't foreign at all, is it? I mean, we have been able to do this in C for decades:
int i;
for(i=1; i<=3; i++)
{
printf("%d\n", i);
}
In fact, you can do this: int i;
for(i=1; i<=3; i=i+1)
{
printf("%d\n", i);
}
That's TWO assignments, not just one. No special operator or syntax. Last I checked no airplanes have crashed, MRI machines stopped working and nobody died because of this. Forgive me but, I just don't see the ambiguity at all. Once you define the extension of functionality the rest is not a problem.That said, I am eager to learn. I've only been designing hardware and software since about 1982 or so and have programmed in nearly every mainstream language in existence on platforms ranging from embedded to Silicon Graphics supercomputers and even the web. It is quite possible I am confused or just don't understand something. I do have a very pragmatic view of this stuff. By which I mean to say: Simple is usually better and there has to be a very, very good reason to reinvent any wheel.
There are many theoretical and quasi-religious arguments you can make about this point, but I think the real reason is a lot simpler: in practice, allowing assignment during expression evaluation has led to tons and tons of bugs.
The number of times a programmer accidentally uses a single "=" sign instead of a "==" in a conditional statement compared to any efficiency gains of avoiding an extra line of code, has empirically resulted in a net negative in productivity.
This isn't a theoretical or philosophical point, it's one rooted in collective experience. This "collective" experience may not match your own, but honestly, for experienced developers it's such a minor issue, that I'm fine giving up 0.001% of my productivity if it allows less experienced programmers to gain more than that.
Yet, at a more fundamental level, there's nothing wrong with code like this (taken from the PEP):
reductor = dispatch_table.get(cls)
if reductor:
rv = reductor(x)
else:
reductor = getattr(x, "__reduce_ex__", None)
if reductor:
rv = reductor(4)
else:
reductor = getattr(x, "__reduce__", None)
if reductor:
rv = reductor()
else:
raise Error(
"un(deep)copyable object of type %s" % cls)
What is wrong with this code that desperately needed fixing through the introduction of a new operator?There's something in the PEP about programmers wanting to save lines of code. Really? The code at the microprocessor level is the same. Heck, if lines of code were so important I would still be programming in APL, where I could shrink a hundred line C program into just a few characters on a single line of code.
I guess my problem is with the idea of fixing something that isn't broken while ignoring stuff that is just nonsensical. A simple example of this is the lack of pre and post increment/decrement (++/--), frankly, it's just silly. We are writing "x = x + 1" instead. The real irony is that every microprocessor I know has increment and decrement instructions! I mean, it's hilarious! "x = x + 1" is likely to be compiled to such an increment instruction, which, is the machine language equivalent of "++" (in rough strokes). One could not make this stuff up. Who are we fooling?
Your belief conflicts with Swift, which also disallows assignment in if conditions for this reason [0]. With GCC, that warns about "suggest parentheses around assignment used as truth value" when compiling with `-Wall` [1]. With the most popular Javascript linter [2].
The tricky part is that "that code isn't going to do what they wanted" isn't always immediately obvious. For example, when I google'd "comparison assignment typo", this is one of the first results: https://gitlab.freedesktop.org/wayland/weston/commit/209e8f1... If the author was expecting that test to pass with the ==, then = would introduce a subtle but devastating bug. In the future, someone could break that function but it would never get caught by the unit tests.
[0] https://docs.swift.org/swift-book/LanguageGuide/BasicOperato...
No, they don't want to save lines of code, they want to save time to understand code. Disallowing assignments during expression is one way to advance that.
But I'm not really understanding your bigger point here. Who cares about such minutia? Is "x++" versus "x += 1" versus "x = x + 1" really all that different to the programmer? When have you proudly used the shorter versions and actually made code better in some marketable way?
These programmer purity metrics are silly and counter-productive, we should instead focus on programmer quality and speed to get things done.