485

7
+15  Q:

## Is there a slicker way of doing this?

I seem to handle special cases like this somewhat frequently. There's got to be a more concise syntax or construct:

``````var x = solveForX(); /* some slow calculation here */
if (x < 0)
{
x = 0;
}
``````

This is equivalent, but doesn't feel any more elegant:

``````var x;
x = (x = solveForX()) < 0 ? 0 : x;
``````

Maybe there's a bit shift trick?

Update: I ran some benchmarks in Firefox to compare my two favorite answers - the one I accepted, and Peter Ajtai's. Turns out Peter's is quite a bit faster! Running 1,000,000 iterations of each (I also ran a version that caches `Math.max` to see how much time the lookup contributed) shows that Peter's runs in under half the time of the `Math.max` version, even with `max` caching.

That said, a million iterations even with the "slowest" method still takes only 0.25 seconds.

+27  A:

``````var x = Math.max(solveForX(), 0);
``````
This is *the* way.
FWIW, although this is more terse, as a reader of code, this form takes me several seconds longer to parse than the OP's original form.
Not the clearest thing ever, using `Math.max` to implement a minimum.
I *always* use max(x, 0). To me it is much more clear then the OP's original if-clause, which I need ~2 seconds to understand. To me min(x, 0) is a *very* standard thing.
Is it intentional that you typed `min(x, 0)` the second time in your comment? Looks like an easy idiom to accidentally reverse.
@Chris Burt-Brown: It is a typo. I meant "max(x, 0)" at both places.
@Andreas - hehe.... I believe that's what's known as "game, set, and match" to @Chris ;) since his point was that accidentally using `min` would be a common typo with this method..... even though it is a pretty good solution overall.
@Dave - [Your rep graph](http://stackoverflow.com/users/160300?tab=reputationhistory#tab-top) is pretty damn funny.
@Bears, I know, today's been a pretty sweet day. 215 rep and 6 badges. Whoo
Yes, I see what you mean. But I still think that the `max(0, x)` approach is standard, and I use it all the time. So I do not need to think when I see this, in contrast to the longer `if` statement, that I need to think about. And similarly, `min(100, x)` will provide an upper bound for the result, and, most importantly, I often use `max(0, min(360, colourHue))` to employ both upper and lower bounds, for instance (in this case) when working with colour hues (which can either be truncated to [0, 360] or used in a periodic (modulus) sense -- this is an example of the former case).
@Andraes Rejbrand, Why would you want an upper and lower bound on color hues? -360 degrees = 0 degrees = 360 degrees = 720 degrees. Wouldn't the modulus operator do the job more accurately? (i.e. `colorHue % 360`)
@kingjeffrey - depends on the use/needs. He did say truncation *or* modding.
+9  A:

Something like:

``````x = Math.max(0, solveForX());
``````
This is *the* way.
A:

Why do you have a problem with the first example? Although there's a few more lines, it's a lot easier to read and follow.

This is a comment, not an answer, but I'll bite - I'm just curious.
I think that `Math.max(0, solveForX());` is more clear and easier to read.
This is a fine answer and does not belong as a comment. The question was: "Is there a better way". The answer is "No" (although admittedly passive-agressive in its wording).
@kingjeffrey - except that, as it turns out, there are multiple better/different ways.
If the browser compiles both examples the same way, the example with less code is superior, because it will download faster. (Hmm... Occam's JavaScript razor?)
@Bears will eat you, Different? Yes. Better? That is a judgement call. I very much like Peter Ajtai solution. It's pretty slick. But for long-term maintainability by unknown future developers, Ash Burlaczenko has a point. Your original code communicates your logic in a very clear, understandable way. The `Math.max` solution (and Peter Ajtai's solution for that matter), while cool and concise, require future developers to grok a lower limit (Math.max) or a unusual assignment (Peter). This may not be initially obvious, and certainly requires more thought. I'd opt for obvious.
Sorry if i came across a bit agressive, i wasn't meaning to be :( @kingjeffrey, that was my initial thought. On projects that my span years it's expected that different developers will work on the same piece of code. That's why it's important to follow one standard and make you code and understandable as possible.
@Ash Burlaczenko, "passive agressive" is quite different than "agressive". Perhaps "indirect" is more accurate. Regardless, your answer is the best one here, even if it is not reflected in the upvotes or the checkmark.
+6  A:
``````(x < 0) && (x = 0);
``````

Edit: Removed the if statement. Thanks Andreas.

This is one line, and it's clear what it does (in my personal opinion) - if you're familiar with boolean short circuit evaluation.

The above makes use of boolean short circuit evaluation. This can be very useful in certain situations (especially pointer arithmetic in C++, but boolean short circuit evaluation also works in Javascript).

`x = 0` only evaluates if `x < 0`.

Here are two examples:

``````<script type="text/javascript">
var x = 1;
(x < 0) && (x = 0);
</script>
``````

``````<script type="text/javascript">
var x = -1;
(x < 0) && (x = 0);
</script>
``````
Seeing that made my eyes hurt!
x = 0 will always assign never evaluate
negative ghostrider
@Woot4Moo - Maybe in javascript but not in all languages. @PeterM - Agreed. The statement will never be true!!!!!
I was pretty confused about this one. Also, it's an if statement with an empty body - so there would be no point in testing it anyway.
@Ash @Woot4Moo What are you talking about? I put two examples up to prove that things evaluate as they should.
@Peter Ajtai your original post was only that ghastly if statement. @Ash in what language is == not comparison?
@Peter, this is less clear to most people than a one-line version of the `if` in my question, e.g. `if (x < 0) x = 0;`.
@Bears will eat you - Well... apparently... wow... I guess I'm the only one that thinks this is clear.
This one should work perfectly (as long as JavaScript employs boolean short-circuit evaluation -- I do not know JS very well). But it is *much* less clear than the **standard** `max(x, 0)` approach. I'll give a +1 just to compensate for the unexplainable downvote, though.
@Peter: Well, I just don't know why you'd ever use that kind of short-circuiting combined with an empty `if` body instead of the usual structure. But hey - I didn't downvote your answer.
@Bears - Well, I really thought it was clearer. Guess most people don't think so ;)
Please leave an explanation if you down vote. OP asked for more concise, and I reduced 4 lines into 1.
@Andreas - Thanks, that's a good suggestion. It does work.... changed the code to reflect it.
+1 This is much more common in Ruby than JavaScript, but I like it!
@kingjeffre: This is much more common in Lisp than Ruby, and I like it.
+1  A:

I'd decorate the original `solveForX` function.

``````function returnNonNegative(fn) {
function _f() {
var x = fn();
if (x < 0) {
x = 0;
}
return x;
}
return _f;
}

solveForX = returnNonNegative(solveForX);
``````

In this particular case, using `Math.max` seems to be fine, but this pattern provides a generic solution for this type of problems.

I think that this question is about the `x = (x = solveForX()) < 0 ? 0 : x;` statement by itself, not about the `solveForX` function or the OP's context.
@Andreas Rejbrand: the question was "is there a slicker way" of writing the construct above that consists of a function call and some additional behavior. I think this is the typical case for the decorator pattern. Syntax can be improved several ways but this makes semantics more clear.
A:

If you want to get real geeky with this, make a prototype for the number object. You will maintain the value, but the special formatted output for negatives could be managed easily with some output method.

http://www.w3schools.com/jsref/jsref_prototype_num.asp

Please don't do this! Avoid altering the native objects' prototype.
@Török: agreed.
Except when doing super fun things like creating a frameworkhttp://www.prototypejs.org/api/number
@user257493: some frameworks do it, others not. It can be a design choice when creating a framework but should not be used for such a problem like this.
A:

The accepted answer is perfect. If you want to accomplish the same without a function call, I believe that this is most concise:

``````var x;
(x = solveForX()) > 0 || (x = 0);
``````

(In Safari, this implementation is a whole 7% faster than `Math.max()`, which is probably not worth caring about)

Math.max(beyond,thunderdome) has better fight scenes.