For example, in C the assignment operator evaluates to the value of the right-hand side expression (so `int x = (y = 2);` initializes `x` to 2). But in Rust, the assignment operator always evaluates to `()` (a.k.a. "unit", the empty tuple), and trust me, this is how you want the language to work in the presence of pervasive move semantics and single ownership. Furthermore, nothing in Rust is "truthy": if-expressions accept a boolean and nothing else (this is also, IMO, exactly what you want in every language, but I'm sure others will disagree :P ). So `if x = 2 {` is a compiler error in Rust because `()` can't be coerced to a boolean (to say nothing of the fact that this reassignment would probably be a compiler error anyway because most variables in Rust are immutable). This doesn't require any acrobatics, it's just the natural fallout of how the rest of the language works.
Litmus test: if this was rendered into S-expressions, the let would stay, but the = would disappear.
If the construct is not allowed when user is already in scope, it reflects the designer's view that an assignment in a conditional isn't a good thing.
If the construct is allowed when user exists already, with no diagnostic, then it carries the pitfalls that this thread is about.
> The assignment operator is =. I was dubious about this, but decided to try it and see if I got used to it. It turns out to work well, even in prefix. Stripes stand out, which is why they get used on warning signs and poisonous animals.
(if (= whatever whatever-else) (you-got-burned))
Arc code written by people used to Lisp dialects where = is a pure comparison function, or Arc code converted from other Lisp dialects, has to be carefully reviewed against this.If I put this into a Lisp dialect, I would make the code walker issue a warning whenever the value of a (= ...) assignment is used, and provide an alternative assignment operator which doesn't have that warning.
In fact, it's not easy to have this kind of bug on your language. C just has it because people wanted to write stuff like `int a = b = 0`.
Programmers using equals for assignment is a bit of a misunderstanding of what the mathematical idiom "let x = 5" means. The assignment is signaled by "let", not by "=". In fact, several programming languages use "let" exactly for this purpose too.
use strict;
use warnings;
sub one { 1 }
if ( my $one = one() ) {
say $one; # prints 1
}
say $one; # compilation error, "Global symbol "$one" requires explicit package name"
This case is trivial, but when you want a temporary variable and don't want to clutter your scope, it can be useful.That's not to say assignment and equivalence might not be better off with different operators, as noted by others here.
Yes, that's what I was trying to get at by saying definition, but not very clearly. It's one of the reasons I prefer languages to require and clearly indicate variable declaration in most cases.
So say untrusted user input.. many cases where it could be something or null. Yoda checking it was a nice way to save a null check.
You have to take bits of concision where you can find them in Java.
Do do this if the coding standards for the language/framework you're working in require it. Like WordPress.
I'd rather it be done by people who care than those that don't.
Also it's slightly awkward to read, as mentioned by others already.
Re: awkwardness, it doesn't feel awkward at all to me; given that Erlang and Elixir use assignment for destructuring and pattern-matching, Yoda conditionals feel very natural to me in comparison.
For example, this is valid Elixir code:
foo = {1, 2}
bar = if {baz, 2} = foo do
525600
end
IO.inspect foo # prints {1,2}
IO.inspect bar # prints 525600
IO.inspect baz # prints 1You can't force everyone who edits your code to have linters and warnings turned on. Not everyone follows bests practices.
It's OK if your tools absolutely can't diagnose accidental if(a = b), but it should be the last resort.
mString != null && mString.equals("test")
or "test".equals(mString)
They do the same, but the second one adds hidden `defensive programming` to prevent NPE in `equals`. Saves time AND code.Intended usage of if(a=b) should be written as if((a=b)). Don't know what tool you use at work or at home, but most static code analysers will point you that. Try SonarQube at least.
I feel as if that can rephrased "Don't do it because it is not done." A left-hand side constant is a convention that can have practical benefits in limited cases. Which at least should merit consideration.
if ((a = b) != NULL) ...
I think Rust has a happy medium, where assignment evaluates to (), not the variable (important as this means you don't have an implicit borrow), but the idiom expressed here is usually replaced by: if let Some(thing) = fn_that_returns_option_thing() ...
In languages where accidental assignment is possible (i.e. writing if(a=b) when you meant if(a==b) ), configure the compiler or linter to emit a warning in this situation.
For example in C, GCC will complain about this when compiling with -Wall, which you should be using anyway.