if (you.religion = GOD_XOM) {
This actually made it to the live test server, where player save files are automatically upgraded to the most recent build, so anyone logging in immediately found themselves infallibly worshiping the god of chaos, every single tick of in-game time (renouncement is futile). Chaos indeed!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.
> 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.
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`.
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.
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.
Also it's slightly awkward to read, as mentioned by others already.
It's OK if your tools absolutely can't diagnose accidental if(a = b), but it should be the last resort.
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() ...Take this example:
function handle_request($http){
if("OPTIONS" === $http.request.method){
...
}else if("GET" === $http.request.method){
...
}else if("PUT" === $http.request.method){
...
}else if($http.request.method === "POST"){
...
}
...
}
Did you read $http.request.method four times? I bet not. Some of you may have read it the first time; I wouldn't have. But to know that the fourth block handled POST requests I made you read to the end of the line. That makes it harder to scan the code looking for the section that you want to change. In production code that I've seen, the predictable side of a comparison is often quite long.What's especially bizarre to me is the reason people give when advocating writing in the last style. Yes, it verbalizes nicely as "Otherwise, if the http request method post, then..." But who internally translates their code to English to understand it? COBOL was designed to read like natural language. Do you enjoy programming in COBOL? If English-like syntax is desirable for code readability, why don't modern programming languages prioritize English-like syntax, too?
Greek mathematics got stuck because it remained a verbal, pictorial activity, Moslem "algebra", after a timid attempt at symbolism, died when it returned to the rhetoric style, and the modern civilized world could only emerge —for better or for worse— ... thanks to the carefully, or at least consciously designed formal symbolisms that we owe to people like Vieta, Descartes, Leibniz, and (later) Boole.
-- Dijkstra,
if ($value = getSomeValue()) {
// Safely use value
}
Yoda Conditions defend nicely against accidents when '=' and '==' can be used legally this way and honestly you get used to reading them pretty quick.C++, for instance however has language syntax to prevent confusion when using this idiom – declarations inside conditionals:
if (auto val = getval())
foo(val); // executed only if getval() returned something that evaluates to true
// in a boolean context
Considering that PHP already has the useless var keyword, they might just adopt something similar in the future if (var $val = getval()) {}They're also a false sense of security as they won't catch:
if $(value = $someOthervalue) ... if( booleanVariable == true )
{
...
}
else if( booleanVariable == false )
{
...
}
else
{
// Typically, this section would include an exact copy
// of one of the above sections, as it was 3 years ago,
// presumably to pad out the SLoC metrics.
}
That place had its head so far up its own ass....Equivalence is commutative. Please never complain about the order of its operands as "confusing" or "less readable". It just tells me that you're an ass, trying to enforce a coding convention that has no objective reason to exist.
if "start" == argv[1]:
....
else if "stop" == argv[1]:
....
else if "reload":
....
else if "status" == argv[1]:
....
I think it'd be harder to make this mistake with the conditions the right way around. (Also, never mind that the equality bug isn't even possible in Python.) {'start': fn_start,
'stop': fn_stop,
}.get(
argv[1] if len(argv) > 1 else None,
fn_undefined
)(*args, **kwargs)
I used this in a demonstration terminal nibbles/worms video game clone, https://github.com/jquast/blessed/blob/master/bin/worms.py#L...Ex:
Foo SOME_CONSTANT = <something-not-null>;
Foo userSuppliedInput = <some-user-input-possibly-null>;
// This can raise an null pointer exception
if (userSuppliedInput.isEquals(SOME_CONSTANT) {
// ...
}
// This can't raise a null pointer exception (assuming isEquals handles nulls properly):
if (SOME_CONSTANT.isEquals(userSuppliedInput) {
// ...
} if([userSuppliedInput isEqual: SOME_CONSTANT]) { ...
If userSuppliedInput is nil, the isEqual: returns false, and it works.It gets really fun when both might be nil:
if([a isEqual: b]) { ...
If a and b are both nil, then they're conceptually equal, but isEqual: still returns false because it's a mindless "always return 0 for messages to nil" thing that doesn't even look at any parameters passed in. if x > 0:
y += x
versus y += x if x > 0 save if valid
rather than if valid
save
end
but what I see 9 times out of 10 is things.do each |thing|
foo
bar
baz
end if valid
orreally.long.thing.that.i.try.to.parse.in.my.head if acutally_almost_never_happens
which is harder to read since I read top to bottom / left to right, but the flow is bottom to top and right to left
# Not allowed
for ( 1 .. 10 ) {
say $_;
} if 1;
# Allowed
map { say $_ } ( 1 .. 10 ) if 1;
The idea seems to be that a post-conditional should be simple and obvious by the time you've parsed the statement. A block makes it confusing, as does mixing post control structuresPost-loop structures have the same limitation:
# Not allowed
{ say "foo"; say $_ } for ( 1 .. 10 );
# Allowed
say $_ for ( 1 .. 10 );
When used correctly, these can become very succinct and clear. my %data = get_data_record_hash("foo");
$data{$_} = update_field(data{$_}) for ('field1','field4',other_field');
# Compare to map, which normally you expect to return values
map { $data{$_} = update_field(data{$_}) } ('field1','field4',other_field');
The single statement limitation keeps you from going wild in ways that are probably not useful to future readers of the code (including you).In Perl:
if ($x > 0) { $y += $x }
versus: $y += $x if $x > 0; $days = 28 if $month eq "February";Example: plantArrowhead, plantGuzmania, plantMarmo vs. arrowheadPlant, guzmaniaPlant, marmoPlant.