The code below attempts to print out "is even" for numbers divisible by 2.
Should it not be if (test) then() rather than: if (!test) then(), when condition tested is "n % 2". The code below seems to read "IF numbers are NOT divisible by 2, print out 'number is even' ", which does not seem logical.
More generally speaking, what are the advantages of writing an Unless function over using an If statement in specifying condition, when what we could do is simply write if (!condition)?
Any help is much appreciated.
function unless(test, then) {
if (!test) then();
}
function repeat(times, body) {
for (var i = 0; i < times; i++) body(i);
}
repeat(5, function(n) {
unless(n % 2, function() {
console.log(n, "is even");
});
// → 0 is even
// → 2 is even
// → 4 is even
The code below attempts to print out "is even" for numbers divisible by 2.
Should it not be if (test) then() rather than: if (!test) then(), when condition tested is "n % 2". The code below seems to read "IF numbers are NOT divisible by 2, print out 'number is even' ", which does not seem logical.
More generally speaking, what are the advantages of writing an Unless function over using an If statement in specifying condition, when what we could do is simply write if (!condition)?
Any help is much appreciated.
function unless(test, then) {
if (!test) then();
}
function repeat(times, body) {
for (var i = 0; i < times; i++) body(i);
}
repeat(5, function(n) {
unless(n % 2, function() {
console.log(n, "is even");
});
// → 0 is even
// → 2 is even
// → 4 is even
Share
Improve this question
edited Jan 24, 2015 at 0:28
Henry
asked Jan 23, 2015 at 23:43
HenryHenry
2792 gold badges4 silver badges13 bronze badges
5
|
3 Answers
Reset to default 7The arguable advantage of this is that the code reads slightly more like English: "Unless n modulo 2 is nonzero, log to the console that n is even."
In my experience, the practical consequence of this is that most programmers will have to go double-check what unless() actually does before they feel comfortable with it. Because it's not a standard piece of Javascript, they have no way of knowing whether it uses ! or ==true or ===0 or some other ever-so-slightly different test, unless they go look at the implementation.
My favorite example of this principle is COBOL. That language tried very hard to resemble English, so that even non-programmers could use it...but in reality both programmers and non-programmers seem to hate working with it.
There are no advantages if the condition is provided inline as in this scenario. You can easily apply a transformation to negate it as appropriate in all cases (e.g. adding a !
in front), and taking unless
out of the picture means there's one less thing the reader has to know about.
There could be an advantage if the condition was provided in the form of a callback, e.g.:
function test() { return true; }
function unless(test, then) { if (!test()) then(); }
unless(test, function() { console.log("test failed"); });
In this situation you could not directly pass the negation of test
to a hypothetical function onlyIf
that is complementary to unless
, so having both onlyIf
and unless
can make the code more readable because it allows you to do this:
onlyIf(test, function() { console.log("test passed"); });
instead of this:
onlyIf(function() { return !test(); }, function() { console.log("test passed"); });
The above situation could be even worse if the callback is given arguments that need to be propagated into test
.
I agree with Mahdi that this likely came about in reaction to an intentionally strange example of callbacks, but for the sake of completeness—plus a particular interest in negation—there is one more option:
if(test){}else{then}
This is shorter than unless() even after the arrival of arrow functions. It also keeps the metaphor of having a "free pass" on the expression. I think any further attempt to contend with the ! or ?: operator for grammatical reasons, realistically, would require the language to allow:
else(test){then}
Given this, I would still pick the former for flexibility, and for existing. :)
%
doesn't test divisibility. It's a modulo operator. This code tests ifn % 2
evaluates to something that could be considered false (aka0
) and, if so, it's even. – anon Commented Jan 23, 2015 at 23:46if number is not divisible by 2
butif a number divided by 2 does NOT have remainders
– slebetman Commented Sep 11, 2022 at 3:43