Loading ...
Sorry, an error occurred while loading the content.

Nested ?: operator values.

Expand Messages
  • pauanyu
    I understand that the ?: operator is supposed to be used to select between multiple values, rather than multiple actions. I ran into an interesting situation:
    Message 1 of 7 , Jul 8, 2009
    • 0 Attachment
      I understand that the ?: operator is supposed to be used to select between multiple values, rather than multiple actions.

      I ran into an interesting situation: I'm writing a function that will toggle a property. So if the property is "foo", it will now be "bar", and if it's "bar", it will now be "foo".

      There are essentially three simple ways to do this: a switch, if statements, and using the ?: operator. Here's an example of all three:


      switch (this[prop]) {
      case val1:
      return (this[prop] = val2);
      case val2:
      return (this[prop] = val1);
      }

      if (this[prop] === val1) {
      return (this[prop] = val2);
      } else if (this[prop] === val2) {
      return (this[prop] = val1);
      }

      return this[prop] = (this[prop] === val1) ? val2 :
      (this[prop] === val2) ? val1 : this[prop];


      I think you'd be hard-pressed to say the ?: version is less elegant and readable than the first two. There's just one problem: it uses nested ?: operators, so JSLint doesn't like it.

      The key point here is none of the values returned by either operator are actions: they are all values. As such, it doesn't break the "?: is used to select one of two values" rule.

      Your thoughts on this?
    • Michael Lorton
      Well, val1 and val2 are the only possible values, you could do this: var next = {}; next[val1]=val2; next[val2]=val1; return this[prop] = next[this[prop]] ; If
      Message 2 of 7 , Jul 8, 2009
      • 0 Attachment
        Well, val1 and val2 are the only possible values, you could do this:

        var next = {};
        next[val1]=val2;
        next[val2]=val1;
        return this[prop] = next[this[prop]] ;

        If the function is to be executed over and over, the first three statement are only needed at initialization time. Plus, this algorithm generalizes to any fixed, repeating sequence of values. Say you wanted to loop through 1, 4, 9 over and over (starting at 1 if the property is not already in the sequence):

        return this[prop] = { 1: 4, 4: 9, 9: 1} [this[prop]] || 1;

        Was this the question or did you want to talk about the ternary operator?

        M.



        ________________________________
        From: pauanyu <pcxunlimited@...>
        To: jslint_com@yahoogroups.com
        Sent: Wednesday, July 8, 2009 8:12:34 PM
        Subject: [jslint] Nested ?: operator values.

        I understand that the ?: operator is supposed to be used to select between multiple values, rather than multiple actions.

        I ran into an interesting situation: I'm writing a function that will toggle a property. So if the property is "foo", it will now be "bar", and if it's "bar", it will now be "foo".

        There are essentially three simple ways to do this: a switch, if statements, and using the ?: operator. Here's an example of all three:


        switch (this[prop]) {
        case val1:
        return (this[prop] = val2);
        case val2:
        return (this[prop] = val1);
        }

        if (this[prop] === val1) {
        return (this[prop] = val2);
        } else if (this[prop] === val2) {
        return (this[prop] = val1);
        }

        return this[prop] = (this[prop] === val1) ? val2 :
        (this[prop] === val2) ? val1 : this[prop];


        I think you'd be hard-pressed to say the ?: version is less elegant and readable than the first two. There's just one problem: it uses nested ?: operators, so JSLint doesn't like it.

        The key point here is none of the values returned by either operator are actions: they are all values. As such, it doesn't break the "?: is used to select one of two values" rule.

        Your thoughts on this?



        ------------------------------------

        Yahoo! Groups Links



        [Non-text portions of this message have been removed]
      • pauanyu
        ... That seems to be a good solution as well. However, that was not the question. I was indeed talking about the ?: operator, specifically about a JSLint error
        Message 3 of 7 , Jul 8, 2009
        • 0 Attachment
          --- In jslint_com@yahoogroups.com, Michael Lorton <mlorton@...> wrote:
          >
          > Well, val1 and val2 are the only possible values, you could do this:
          >
          > var next = {};
          > next[val1]=val2;
          > next[val2]=val1;
          > return this[prop] = next[this[prop]] ;
          >
          > If the function is to be executed over and over, the first three statement are only needed at initialization time. Plus, this algorithm generalizes to any fixed, repeating sequence of values. Say you wanted to loop through 1, 4, 9 over and over (starting at 1 if the property is not already in the sequence):
          >
          > return this[prop] = { 1: 4, 4: 9, 9: 1} [this[prop]] || 1;
          >
          > Was this the question or did you want to talk about the ternary operator?
          >
          > M.
          >

          That seems to be a good solution as well. However, that was not the question. I was indeed talking about the ?: operator, specifically about a JSLint error when nesting them. I appreciate the alternate solution, however.
        • Douglas Crockford
          ... The thing that JSLint did not like was the use of an assignment as an expression. It will accept this[prop] = (this[prop] === val1) ? val2 : (this[prop]
          Message 4 of 7 , Jul 9, 2009
          • 0 Attachment
            --- In jslint_com@yahoogroups.com, "pauanyu" <pcxunlimited@...> wrote:
            > return this[prop] = (this[prop] === val1) ? val2 :
            > (this[prop] === val2) ? val1 : this[prop];
            >
            >
            > I think you'd be hard-pressed to say the ?: version is less elegant and readable than the first two. There's just one problem: it uses nested ?: operators, so JSLint doesn't like it.


            The thing that JSLint did not like was the use of an assignment as an expression. It will accept

            this[prop] = (this[prop] === val1) ? val2 :
            (this[prop] === val2) ? val1 : this[prop];
            return this[prop];

            or

            return (this[prop] = (this[prop] === val1) ? val2 :
            (this[prop] === val2) ? val1 : this[pro
          • pauanyu
            ... Oh, I see! So this works: return (this[prop] = (this[prop] === val1) ? val2 : (this[prop] === val2) ? val1 : this[prop]); Thanks for your help. Nice to
            Message 5 of 7 , Jul 9, 2009
            • 0 Attachment
              --- In jslint_com@yahoogroups.com, "Douglas Crockford" <douglas@...> wrote:
              >
              > The thing that JSLint did not like was the use of an assignment as an expression. It will accept
              >
              > this[prop] = (this[prop] === val1) ? val2 :
              > (this[prop] === val2) ? val1 : this[prop];
              > return this[prop];
              >
              > or
              >
              > return (this[prop] = (this[prop] === val1) ? val2 :
              > (this[prop] === val2) ? val1 : this[pro
              >

              Oh, I see! So this works:

              return (this[prop] = (this[prop] === val1) ? val2 :
              (this[prop] === val2) ? val1 : this[prop]);

              Thanks for your help. Nice to know that JSLint handles nested ?: operators.
            • pauanyu
              ... I did a little tinkering, and here s what I came up with: return (this[prop] = ({ val1: val2, val2: val1 })[this[prop]]); What a fantastic construct.
              Message 6 of 7 , Jul 9, 2009
              • 0 Attachment
                --- In jslint_com@yahoogroups.com, Michael Lorton <mlorton@...> wrote:
                >
                > Well, val1 and val2 are the only possible values, you could do this:
                >
                > var next = {};
                > next[val1]=val2;
                > next[val2]=val1;
                > return this[prop] = next[this[prop]] ;
                >
                > If the function is to be executed over and over, the first three statement are only needed at initialization time. Plus, this algorithm generalizes to any fixed, repeating sequence of values. Say you wanted to loop through 1, 4, 9 over and over (starting at 1 if the property is not already in the sequence):
                >
                > return this[prop] = { 1: 4, 4: 9, 9: 1} [this[prop]] || 1;
                >
                > Was this the question or did you want to talk about the ternary operator?
                >
                > M.
                >

                I did a little tinkering, and here's what I came up with:

                return (this[prop] = ({ val1: val2, val2: val1 })[this[prop]]);

                What a fantastic construct. Create an anonymous object, then use it immediately! Unfortunately this doesn't work, because val1 and val2 are variables that are determined at run-time, so this will fail.

                Nonetheless, you have my gratitude for pointing out a wonderful construct that I plan to use more often in my code. For now, I'll stick with the ?: operator.
              • Michael Lorton
                Yeah, I did exactly that first too, but { val1 : val2 } is equivalent to { val1 : val2 }. The braces notation only works if the sequence is expressed as
                Message 7 of 7 , Jul 9, 2009
                • 0 Attachment
                  Yeah, I did exactly that first too, but { val1 : val2 } is equivalent to { "val1" : val2 }. The braces notation only works if the sequence is expressed as constants. Of course, most sequences you run across express an obvious relationship and it's better to encode the relationship. If you want true-false-true-false, return (this[prop] = !this[prop]); is much more sensible than return (this[prop] = { true: false, false: true}this[prop]).

                  Not terrible on topic, but how many people know about the !! operator? It converts truthy and falsy values to actual booleans. So !!1yields true and !!0yields false.

                  OK, I'm lying, there's no !! operator -- it's just the ! operator twice, but it does work.

                  M.


                  ________________________________
                  From: pauanyu <pcxunlimited@...>
                  To: jslint_com@yahoogroups.com
                  Sent: Thursday, July 9, 2009 9:38:16 AM
                  Subject: Re: [jslint] Nested ?: operator values.

                  --- In jslint_com@yahoogroups.com, Michael Lorton <mlorton@...> wrote:
                  >
                  > Well, val1 and val2 are the only possible values, you could do this:
                  >
                  > var next = {};
                  > next[val1]=val2;
                  > next[val2]=val1;
                  > return this[prop] = next[this[prop]] ;
                  >
                  > If the function is to be executed over and over, the first three statement are only needed at initialization time. Plus, this algorithm generalizes to any fixed, repeating sequence of values. Say you wanted to loop through 1, 4, 9 over and over (starting at 1 if the property is not already in the sequence):
                  >
                  > return this[prop] = { 1: 4, 4: 9, 9: 1} [this[prop]] || 1;
                  >
                  > Was this the question or did you want to talk about the ternary operator?
                  >
                  > M.
                  >

                  I did a little tinkering, and here's what I came up with:

                  return (this[prop] = ({ val1: val2, val2: val1 })[this[prop]]);

                  What a fantastic construct. Create an anonymous object, then use it immediately! Unfortunately this doesn't work, because val1 and val2 are variables that are determined at run-time, so this will fail.

                  Nonetheless, you have my gratitude for pointing out a wonderful construct that I plan to use more often in my code. For now, I'll stick with the ?: operator.



                  ------------------------------------

                  Yahoo! Groups Links



                  [Non-text portions of this message have been removed]
                Your message has been successfully submitted and would be delivered to recipients shortly.