News for hackers. Stuff that matters.
Re:Yoda Conditions by paol on Friday February 17, 2017 @10:48AM (#13668983)
Don't do this.

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.

Re:Yoda Conditions by hashkb on Friday February 17, 2017 @11:25AM (#13669387)
The real lesson is for language designers, who for some reason love using equals for assignment. Lisp got it right a hundred years ago and nobody learned.
Re:Yoda Conditions by dom96 on Friday February 17, 2017 @11:46AM (#13669597)
There is nothing wrong with using equals for assignment, the language designers just have to disallow assignments in if conditions.
Re:Yoda Conditions by tel on Friday February 17, 2017 @12:05PM (#13669799)
It's a little weird. lvalues and rvalues are different things so a biased symbol feels nice to me, <-, e.g.
Re:Yoda Conditions by junke on Friday February 17, 2017 @12:03PM (#13669773)
One more corner case, instead of designing orthogonal features.
Re:Yoda Conditions by kibwen on Friday February 17, 2017 @12:16PM (#13669907)
It's not a corner case if you do it right.

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.

Re:Yoda Conditions by junke on Friday February 17, 2017 @12:21PM (#13669937)
Thanks, that's indeed a sensible way to do that.
Re:Yoda Conditions by kazinator on Friday February 17, 2017 @07:00PM (#13672780)
That's a cure worse than the disease. If I faced a false choice between = as an assignment operator or else accepting syntax that distinguishes statements and expressions, I'd just take the = operator.
Re:Yoda Conditions by nilved on Friday February 17, 2017 @03:33PM (#13671465)
There's nothing wrong with using assignment in if conditions. For example, `if let Some(thing) = computation_that_may_fail { ... }`.
Re:Yoda Conditions by kazinator on Friday February 17, 2017 @06:53PM (#13672732)
The operator there is let. The = is just a punctuator which indicates the initial value expression for the let.

Litmus test: if this was rendered into S-expressions, the let would stay, but the = would disappear.

Re:Yoda Conditions by nilved on Sunday February 19, 2017 @12:53PM (#13680862)
No, that's just because the example I used was Rust. In Ruby it would be `if user = User.find(..)` and the same goes for Go and plenty of other languages.
Re:Yoda Conditions by kazinator on Sunday February 19, 2017 @10:47PM (#13684125)
If user is being freshly bound, that isn't an assignment but an initialization.

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.

Re:Yoda Conditions by cronjobber on Saturday February 18, 2017 @05:42AM (#13674361)
Hacker News is implemented in a dialect of Lisp designed by a guy who wrote multiple books on Lisp. Seems even lispers don't learn:

> 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.

http://www.paulgraham.com/arcll1.html

Re:Yoda Conditions by kazinator on Saturday February 18, 2017 @02:39PM (#13676292)
That is quite silly. I briefly contemplated this idea for TXR Lisp, but completely rejected it. The = function is numeric comparison, like in Common Lisp. You don't want to turn that into assignment. People used to Lisp dialects where = is numeric comparison will make the mistake:

  (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.

Re:Yoda Conditions by flukus on Wednesday February 22, 2017 @07:36PM (#13710631)
I'd say the issue is keyboard designers, if ':' didn't require shift I bet we'd see it for assignment more often.
Re:Yoda Conditions by marcosdumay on Friday February 17, 2017 @12:22PM (#13669948)
Well, languages can either use another assignment operator or have type system that wont check that kind of statement. Both ways fix it.

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`.

Re:Yoda Conditions by jordigh on Friday February 17, 2017 @03:28PM (#13671427)
`int a <- b <- 0` or `int a := b := 0` would have worked just as well.

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.

Re:Yoda Conditions by kbenson on Friday February 17, 2017 @12:04PM (#13669780)
There are useful cases for this. It's much less ambiguous in those cases if your language allows the definition of the variable in the same location, and scopes it. For example, Perl:

    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.

Re:Yoda Conditions by dbaupp on Friday February 17, 2017 @01:21PM (#13670435)
Declaration and a (mutating) assignment are different: your example demonstrates that Perl signals the declaration with `my`, and other languages offer similar things like `if let ... = ... { ... }`
Re:Yoda Conditions by kbenson on Friday February 17, 2017 @01:36PM (#13670557)
> Declaration and a (mutating) assignment are different

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.

Re:Yoda Conditions by brianwawok on Friday February 17, 2017 @10:56AM (#13669073)
Eh, I think it is good in Java in cases where Null input is possible.
Re:Yoda Conditions by paol on Friday February 17, 2017 @11:09AM (#13669226)
Yes, "foo".equals(bar) is useful in Java if bar can be null, but that's a different thing.
Re:Yoda Conditions by brianwawok on Friday February 17, 2017 @11:26AM (#13669402)
Not really different. In fact is is mentioned on the Wikipedia page.
Re:Yoda Conditions by megawatthours on Friday February 17, 2017 @12:26PM (#13669993)
I never got the Java argument. I would much rather fail early and noisily with an NPE than return false and let my program happily chug along when it wasn't expecting a null. If the value is intended to be nullable, I would use an optional.
Re:Yoda Conditions by brianwawok on Friday February 17, 2017 @02:29PM (#13670970)
Well for 95% of Java's live, there was no such thing as Optional.

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.

Re:Yoda Conditions by xxs on Friday February 17, 2017 @12:37PM (#13670098)
Java8 optional is way slower (write a tree alike struct with optional for left/right/parent) and null checks are one of the free ones. (Hardware optimized)
Re:Yoda Conditions by PaulHoule on Friday February 17, 2017 @11:53AM (#13669683)
I think it is better than if(x!=null && x.equals("y")

You have to take bits of concision where you can find them in Java.

Re:Yoda Conditions by busterarm on Friday February 17, 2017 @12:26PM (#13669992)
Counterargument:

Do do this if the coding standards for the language/framework you're working in require it. Like WordPress.

Re:Yoda Conditions by sethrin on Friday February 17, 2017 @05:18PM (#13672217)
Wordpress is a legacy procedural codebase and should not be used as an example of good development practices.
Re:Yoda Conditions by busterarm on Wednesday February 22, 2017 @07:31PM (#13710602)
Regardless of your religious convictions, Wordpress still exists and that work has to be done by somebody.

I'd rather it be done by people who care than those that don't.

Re:Yoda Conditions by sethrin on Saturday February 25, 2017 @10:50PM (#13735558)
How is that a comment on coding standards or best practices? I'm afraid the arguments against procedural code are not religious. Procedural code provides poor encapsulation and modularity. If procedural code was all that great, we wouldn't have needed to have C++, C#, Java, and Objective-C, and any number of other derivative languages. Regardless of my or your opinions, WordPress is a legacy codebase. Procedural code today is all but completely discarded.
Re:Yoda Conditions by michaelmior on Friday February 17, 2017 @10:55AM (#13669067)
While I don't disagree, curious to hear your reasoning for not doing this.
Re:Yoda Conditions by paol on Friday February 17, 2017 @11:15AM (#13669283)
This trick can only save people who remember to use it. Warnings emitted by tooling save everyone.

Also it's slightly awkward to read, as mentioned by others already.

Re:Yoda Conditions by yellowapple on Friday February 17, 2017 @01:03PM (#13670285)
Warnings can only save people who bother to read them. Yoda conditionals save everyone trying to run or compile the code in question. It goes both ways ;)

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 1
Re:Yoda Conditions by busterarm on Friday February 17, 2017 @12:30PM (#13670035)
The trick saves the person writing the code and anyone modifying it down the road.

You can't force everyone who edits your code to have linters and warnings turned on. Not everyone follows bests practices.

Re:Yoda Conditions by michaelmior on Friday February 17, 2017 @12:35PM (#13670072)
Does it? You also can't force everyone who edits your code to follow your conventions.
Re:Yoda Conditions by digler999 on Friday February 17, 2017 @05:08PM (#13672135)
actually you can, depending on the management structure in an organization :)
Re:Yoda Conditions by mikeash on Friday February 17, 2017 @10:59AM (#13669114)
It's unnatural, confusing to read, and won't save you anyway in cases where you're comparing two variables.

It's OK if your tools absolutely can't diagnose accidental if(a = b), but it should be the last resort.

Re:Yoda Conditions by akerro on Friday February 17, 2017 @11:04AM (#13669159)
In some languages it's better to use it, eg. in Java you can go with:

   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.

Re:Yoda Conditions by scj on Friday February 17, 2017 @11:19AM (#13669332)
> It's unnatural, confusing to read ...

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.

Re:Yoda Conditions by mikeash on Friday February 17, 2017 @11:29AM (#13669424)
"Don't do it because it is not done" is a good reason unless you're working solo and are sure your code will never be seen by others. And even then, it's a good idea to stick to what's done so you don't accumulate bad habits for projects that do have others looking at the code.
Re:Yoda Conditions by pasquinelli on Friday February 17, 2017 @01:38PM (#13670577)
how would you write a yoda conditional with two variables? which is the yoda conditional (a == b), or (b == a)?
Re:Yoda Conditions by mikeash on Friday February 17, 2017 @02:28PM (#13670960)
You can't if they're both mutable, since the whole idea of a yoda conditional is to put an immutable thing on the left side. What I meant was that you can't use them in that case, so it's a technique you can't use with 100% consistency.
Re:Yoda Conditions by MikkoFinell on Friday February 17, 2017 @11:45AM (#13669587)
Also clang warns "using the result of an assignment as a condition without parentheses".
Re:Yoda Conditions by mirekrusin on Friday February 17, 2017 @10:58AM (#13669105)
Exactly, and use 'if ((a = b)) ...' in those rare cases when it's appropriate.
Re:Yoda Conditions by efaref on Friday February 17, 2017 @12:04PM (#13669782)
Even then I would prefer an explicit comparison:

    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() ...
Re:Yoda Conditions by devy on Friday February 17, 2017 @01:57PM (#13670734)
What about PHP? It's in the coding standard in WordPress and Symfony... :(