2

I'm trying to understand how does this piece of code work. I know that the ternary operator is condition ? option1 : option2 but I don't know how does this work in this scenario.

constructor(minSupport: number, minConfidence: number, debugMode: boolean) {
            this.minSupport = minSupport ? minSupport === 0 ? 0 : minSupport : 0.15;
            this.minConfidence = minConfidence ? minConfidence === 0 ? 0 : minConfidence : 0.6;
            this.debugMode = debugMode || false;
        }
8
  • 1
    Who wrote this?? Double checking for falsy doesnt make sense. Commented Aug 11, 2017 at 14:43
  • 1
    It's nested ternary, it would have really benefited from some parentheses (at the very least) Commented Aug 11, 2017 at 14:44
  • 3
    minSupport === 0 ? 0 : minSupport makes no sense (except when caring for -0, but that should be noted in a comment) Commented Aug 11, 2017 at 14:47
  • 1
    @zzzzBov 0 is falsy, therefore it will exit at the first ternary and wont go into the nested one which checks for 0 ? Commented Aug 11, 2017 at 14:47
  • 1
    @DarrenYoung could, but shouldn't. I've seen (and made) this sort of mistake numerous times. In my view, the intent to preserve an explicit 0 while overriding implicit defaults (e.x. undefined). Commented Aug 11, 2017 at 15:01

4 Answers 4

7

This:

this.minSupport = minSupport ? minSupport === 0 ? 0 : minSupport : 0.15;

translates into:

if (minSupport) {
  if (minSupport === 0) {
    this.minSupport = 0;
  } else {
    this.minSupport = minSupport;
  }
} else {
  this.minSupport = 0.15;
}

Given this example the others should be easy to work out. Personally I don't like nested ternary expressions like you've posted. A nice if/then statement is much simpler to work out the flow of logic.

Sign up to request clarification or add additional context in comments.

4 Comments

That's some tremendous logic :)
The ternary expression actually is much simpler to work out because there's only one assignment to this.minSupport - you can easily see that the conditional flow affects only the value, not what happens with it.
I said "personally" :)
Oh thanks man, I didn't think this was permitted that's why I've started thinking it meant something different. Now I understand.
5

This is a case study on why writing code as tersely as possible does not make it better.

Shoving everything into a single line makes it hard to read and comprehend the flow. I find that adding a little bit of formatting makes things much more legible:

this.minSupport =
  minSupport
    ? minSupport === 0
      ? 0
      : minSupport
    : 0.15;

There are a variety of ways to format that code to make it easier to digest. At this point we can walk through the logic:

if minSupport is truthy:

check if minSupport is zero (literally can't happen because 0 is not truthy). If it is (it can't be) set this.minSupport to 0. Otherwise, set this.minSupport to whatever value minSupport contained.

else if minSupport is falsey:

set this.minSupport to 0.15

So with that logic digested, it's clear that there's a secondary check that intends to preserve the value of 0. The code is buggy, and the fix is to change the logic:

this.minSupport =
  minSupport
    ? minSupport
    : minSupport === 0
      ? minSupport
      : 0.15;

now with that reflow, we can look over the logic and see that it can be condensed. We want to set this.minSupport to minSupport if minSupport is truthy or if minSupport is 0.

The simplification looks like:

this.minSupport =
  minSupport || minSupport === 0
    ? minSupport
    : 0.15;

1 Comment

Possibly even closer to the intended meaning: this.minSupport = isNaN(minSupport) ? 0.15 : Number(minSupport) or this.minSupport = (typeof minSupport == "number" && !isNaN(minSupport)) ? minSupport : 0.15 - omit parts when knowing the type of the argument (as the parameter type annotation in the OP suggests)
3
this.minSupport = minSupport ? minSupport === 0 ? 0 : minSupport : 0.15;

What it actually does (leaving away the non working stuff):

this.minSupport = minSupport || 0.15;

So basically, if minSupport is 0 or not passed (aka undefined), itll be 0.15 instead.

3 Comments

Well, that code does work, it's just much more verbose than is required.
@andy in my opinion: work === does what it is supposed to
@andy So with that logic digested, it's clear that there's a secondary check that intends to preserve the value of 0. The code is buggy, and the fix is to change the logic
0

Here is a complete translation of the given snippet

constructor(minSupport: number, minConfidence: number, debugMode: boolean) {
  this.minSupport = (() => {
    if (minSupport) { 
      if (minSupport === 0) {
        // Interpreter will never reach this point because if minSupport is 0, it would straight away go to return 0.15 statement.
        return 0; 
      } else {
        return minSupport;
      }
    } else {
      return 0.15;
    }
  })();

  this.minConfidence = (() => {
    if (minConfidence) { 
      if (minConfidence === 0) {
        // Interpreter will never reach this point because if minConfidence is 0, it would straight away go to return 0.6 statement.
        return 0;
      } else {
        return minConfidence;
      }
    } else {
      return 0.6;
    }
  })();

  this.debugMode = (() => {
    if (debugMode) {
      return debugMode;
    } else {
      return false;
    }
  })();
}

The code snippet you shared, seems to be overdoing check for 0 which is already taken care of in the earlier if. You may probably want to rewrite your code to this.

constructor(minSupport: number, minConfidence: number, debugMode: boolean) {
  if (minSupport === 0 || minSupport) {
    this.minSupport = minSupport;
  } else {
    this.minSupport 0.15;
  }

  if (minConfidence === 0 || minConfidence) {
    this.minConfidence = minConfidence;
  } else {
    this.minConfidence = 0.15;
  }

  if (debugMode) {
    this.debugMode = debugMode;
  } else {
    this.debugMode = false;
  }
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.