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;
}
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;
}
Share
Improve this question
asked Aug 11, 2017 at 14:42
FjallbackaFjallbacka
4744 silver badges16 bronze badges
8
- 1 Who wrote this?? Double checking for falsy doesnt make sense. – Jonas Wilms Commented Aug 11, 2017 at 14:43
- 1 It's nested ternary, it would have really benefited from some parentheses (at the very least) – zero298 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 ment) – Bergi 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 ? – Jonas Wilms 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
). – zzzzBov Commented Aug 11, 2017 at 15:01
4 Answers
Reset to default 7This:
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.
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 prehend 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;
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.
Here is a plete 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;
}
}