最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

function - Unless vs if in Javascript with use of exclamation point? - Stack Overflow

programmeradmin1浏览0评论

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
  • % doesn't test divisibility. It's a modulo operator. This code tests if n % 2 evaluates to something that could be considered false (aka 0) and, if so, it's even. – anon Commented Jan 23, 2015 at 23:46
  • "The code below attempts to print out "is even" for numbers divisible by 2." - It doesn't attempt it, it does it. (At least, once you fix the syntax error at the end it will do it.) Anyway, I agree that the idea of "unless" doesn't really make sense semantically for this test, but the code does have the desired output. Those type of functions look like they belong in a testing framework, letting you make an assertion and do something if the assertion proves false. – nnnnnn Commented Jan 23, 2015 at 23:47
  • 2 This code is horrendous, as evidenced by the fact that it's not even clear what it does without careful analysis. There's no advantage here. I can't posit advantages in the general case. Maybe it's advantageous to do it this way when your pointy-haired boss says do it this way or you'll be fired. You need to give context for when you might for this question to be viable. – djechlin Commented Jan 23, 2015 at 23:49
  • @djechlin The code is part of Eloquent JavaScript. It seems out of context in here, it is just an example while explaining higher order function. – user4588945 Commented Mar 25, 2019 at 19:11
  • 1 The code is correct. Your understanding of integer division is wrong. It is not if number is not divisible by 2 but if a number divided by 2 does NOT have remainders – slebetman Commented Sep 11, 2022 at 3:43
Add a comment  | 

3 Answers 3

Reset to default 7

The 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. :)

发布评论

评论列表(0)

  1. 暂无评论