You are viewing a plain text version of this content. The canonical link for it is here.
Posted to users@groovy.apache.org by Henrik Martin <he...@netgate.net> on 2016/04/12 00:41:59 UTC

What am I missing with this Elvis operator expression?

Greetings. I ran into this little surprise with the Elvis operator 
today. I guess it must boil down to my misunderstanding of how the 
operator work. I have a method that tries to calculate a value based on 
an input. If the input value is set to -1, I'd like to change it to a 
positive value (which is calculated, but in the test I just hard coded 
it to 10). In the process of doing so, I ran into a surprise. Here's a 
Spock test case that illustrates it:

import spock.lang.Specification

class ElvisTest extends Specification {
   def "test"() {
     setup:
     def sleepFor = -1
     sleepFor = sleepFor > 0 ?: 10
     println sleepFor
     sleepFor = 972
     sleepFor = sleepFor > 0 ?: 10
     println sleepFor
   }
}
When sleepFor is initialized to -1, the operator works as I expected it 
and my println statement prints 910. If I initialize sleepFor to some 
other value like the one in the test, all of a sudden the result of the 
Elvis operator is true instead of an integer. I naïvely thought that ?: 
would yield the numeric value of the sleepFor variable in the left hand 
expression instead of the boolean result of it (as in sleepFor > 0). 
What am I missing? In this case, I could always use the Java style of:

sleepFor = sleepFor > 0 ? sleepFor : 10

but the whole point of the Elvis operator is brevity, and this behavior 
was a small surprise to me. Thanks,

-H


Re: What am I missing with this Elvis operator expression?

Posted by Tankerbay <ta...@gmail.com>.
I suggest reading up on Groovy Truthiness:
http://groovy-lang.org/semantics.html#Groovy-Truth

There are a few things the resolve to boolean "false" when you put a
non-boolean into a boolean space.


On Mon, Apr 11, 2016 at 4:27 PM, Henrik Martin <he...@netgate.net> wrote:

> Sure, it makes sense. I guess my confusion originated in other uses with
> Strings. Like this:
>
> foo = 'hello'
> foo = foo ?: 'goodbye' // foo == 'hello'
>
> where foo ends up being set to 'hello'. I guess a String as the left hand
> side expression of the Elvis operator evaluates to itself instead of
> boolean true. While it seems to be true that if it's null, it's the same as
> false? Like this:
>
> foo = null
> foo = foo ?: 'goodbye'  // foo == 'goodbye'
>
> So a null reference is equivalent to boolean false. I guess that makes
> sense. The cases that surprise me the most are these:
>
> foo = '' // empty string
> foo = foo ?: 'goodbye' // foo == 'goodbye'
>
> and
>
> foo = ' ' // single space
> foo = foo ?: 'goodbye' // foo = ' '
>
> I guess I should RTFM a little more thoroughly :-)
>
> -H
>
>
> On 4/12/16 12:54 AM, Tankerbay wrote:
>
> Well, you seem to know what's happening.
> sleepFor = sleepFor > 0 ?: 10
> is equivalent to:
> sleepFor = (sleepFor > 0 ) ?: 10
>
> So the entire expression (sleepFor > 0) is evaluated and, if found to be
> true, returned as the result of the elvis expression.
>
> Elvis operator like this:
> Z = X ?: Default
> is equivalent to:
> Z = X ? X : Default
> not
> Z = X ? (some part of X) : Default
>
>
> On Mon, Apr 11, 2016 at 3:43 PM, Henrik Martin <he...@netgate.net> wrote:
>
>> And of course I meant to say "... and my println statement prints 10",
>> not 910. :-)
>>
>> -H
>>
>>
>> On 4/12/16 12:41 AM, Henrik Martin wrote:
>>
>>> Greetings. I ran into this little surprise with the Elvis operator
>>> today. I guess it must boil down to my misunderstanding of how the operator
>>> work. I have a method that tries to calculate a value based on an input. If
>>> the input value is set to -1, I'd like to change it to a positive value
>>> (which is calculated, but in the test I just hard coded it to 10). In the
>>> process of doing so, I ran into a surprise. Here's a Spock test case that
>>> illustrates it:
>>>
>>> import spock.lang.Specification
>>>
>>> class ElvisTest extends Specification {
>>>   def "test"() {
>>>     setup:
>>>     def sleepFor = -1
>>>     sleepFor = sleepFor > 0 ?: 10
>>>     println sleepFor
>>>     sleepFor = 972
>>>     sleepFor = sleepFor > 0 ?: 10
>>>     println sleepFor
>>>   }
>>> }
>>> When sleepFor is initialized to -1, the operator works as I expected it
>>> and my println statement prints 910. If I initialize sleepFor to some other
>>> value like the one in the test, all of a sudden the result of the Elvis
>>> operator is true instead of an integer. I naïvely thought that ?: would
>>> yield the numeric value of the sleepFor variable in the left hand
>>> expression instead of the boolean result of it (as in sleepFor > 0). What
>>> am I missing? In this case, I could always use the Java style of:
>>>
>>> sleepFor = sleepFor > 0 ? sleepFor : 10
>>>
>>> but the whole point of the Elvis operator is brevity, and this behavior
>>> was a small surprise to me. Thanks,
>>>
>>> -H
>>>
>>>
>>
>
>

Re: What am I missing with this Elvis operator expression?

Posted by Henrik Martin <he...@netgate.net>.
Sure, it makes sense. I guess my confusion originated in other uses with 
Strings. Like this:

foo = 'hello'
foo = foo ?: 'goodbye' // foo == 'hello'

where foo ends up being set to 'hello'. I guess a String as the left 
hand side expression of the Elvis operator evaluates to itself instead 
of boolean true. While it seems to be true that if it's null, it's the 
same as false? Like this:

foo = null
foo = foo ?: 'goodbye'  // foo == 'goodbye'

So a null reference is equivalent to boolean false. I guess that makes 
sense. The cases that surprise me the most are these:

foo = '' // empty string
foo = foo ?: 'goodbye' // foo == 'goodbye'

and

foo = ' ' // single space
foo = foo ?: 'goodbye' // foo = ' '

I guess I should RTFM a little more thoroughly :-)

-H

On 4/12/16 12:54 AM, Tankerbay wrote:
> Well, you seem to know what's happening.
> sleepFor = sleepFor > 0 ?: 10
> is equivalent to:
> sleepFor = (sleepFor > 0 ) ?: 10
>
> So the entire expression (sleepFor > 0) is evaluated and, if found to 
> be true, returned as the result of the elvis expression.
>
> Elvis operator like this:
> Z = X ?: Default
> is equivalent to:
> Z = X ? X : Default
> not
> Z = X ? (some part of X) : Default
>
>
> On Mon, Apr 11, 2016 at 3:43 PM, Henrik Martin <henrik@netgate.net 
> <ma...@netgate.net>> wrote:
>
>     And of course I meant to say "... and my println statement prints
>     10", not 910. :-)
>
>     -H
>
>
>     On 4/12/16 12:41 AM, Henrik Martin wrote:
>
>         Greetings. I ran into this little surprise with the Elvis
>         operator today. I guess it must boil down to my
>         misunderstanding of how the operator work. I have a method
>         that tries to calculate a value based on an input. If the
>         input value is set to -1, I'd like to change it to a positive
>         value (which is calculated, but in the test I just hard coded
>         it to 10). In the process of doing so, I ran into a surprise.
>         Here's a Spock test case that illustrates it:
>
>         import spock.lang.Specification
>
>         class ElvisTest extends Specification {
>           def "test"() {
>             setup:
>             def sleepFor = -1
>             sleepFor = sleepFor > 0 ?: 10
>             println sleepFor
>             sleepFor = 972
>             sleepFor = sleepFor > 0 ?: 10
>             println sleepFor
>           }
>         }
>         When sleepFor is initialized to -1, the operator works as I
>         expected it and my println statement prints 910. If I
>         initialize sleepFor to some other value like the one in the
>         test, all of a sudden the result of the Elvis operator is true
>         instead of an integer. I naïvely thought that ?: would yield
>         the numeric value of the sleepFor variable in the left hand
>         expression instead of the boolean result of it (as in sleepFor
>         > 0). What am I missing? In this case, I could always use the
>         Java style of:
>
>         sleepFor = sleepFor > 0 ? sleepFor : 10
>
>         but the whole point of the Elvis operator is brevity, and this
>         behavior was a small surprise to me. Thanks,
>
>         -H
>
>
>


Re: What am I missing with this Elvis operator expression?

Posted by Tankerbay <ta...@gmail.com>.
Well, you seem to know what's happening.
sleepFor = sleepFor > 0 ?: 10
is equivalent to:
sleepFor = (sleepFor > 0 ) ?: 10

So the entire expression (sleepFor > 0) is evaluated and, if found to be
true, returned as the result of the elvis expression.

Elvis operator like this:
Z = X ?: Default
is equivalent to:
Z = X ? X : Default
not
Z = X ? (some part of X) : Default


On Mon, Apr 11, 2016 at 3:43 PM, Henrik Martin <he...@netgate.net> wrote:

> And of course I meant to say "... and my println statement prints 10", not
> 910. :-)
>
> -H
>
>
> On 4/12/16 12:41 AM, Henrik Martin wrote:
>
>> Greetings. I ran into this little surprise with the Elvis operator today.
>> I guess it must boil down to my misunderstanding of how the operator work.
>> I have a method that tries to calculate a value based on an input. If the
>> input value is set to -1, I'd like to change it to a positive value (which
>> is calculated, but in the test I just hard coded it to 10). In the process
>> of doing so, I ran into a surprise. Here's a Spock test case that
>> illustrates it:
>>
>> import spock.lang.Specification
>>
>> class ElvisTest extends Specification {
>>   def "test"() {
>>     setup:
>>     def sleepFor = -1
>>     sleepFor = sleepFor > 0 ?: 10
>>     println sleepFor
>>     sleepFor = 972
>>     sleepFor = sleepFor > 0 ?: 10
>>     println sleepFor
>>   }
>> }
>> When sleepFor is initialized to -1, the operator works as I expected it
>> and my println statement prints 910. If I initialize sleepFor to some other
>> value like the one in the test, all of a sudden the result of the Elvis
>> operator is true instead of an integer. I naïvely thought that ?: would
>> yield the numeric value of the sleepFor variable in the left hand
>> expression instead of the boolean result of it (as in sleepFor > 0). What
>> am I missing? In this case, I could always use the Java style of:
>>
>> sleepFor = sleepFor > 0 ? sleepFor : 10
>>
>> but the whole point of the Elvis operator is brevity, and this behavior
>> was a small surprise to me. Thanks,
>>
>> -H
>>
>>
>

Re: What am I missing with this Elvis operator expression?

Posted by Henrik Martin <he...@netgate.net>.
And of course I meant to say "... and my println statement prints 10", 
not 910. :-)

-H

On 4/12/16 12:41 AM, Henrik Martin wrote:
> Greetings. I ran into this little surprise with the Elvis operator 
> today. I guess it must boil down to my misunderstanding of how the 
> operator work. I have a method that tries to calculate a value based 
> on an input. If the input value is set to -1, I'd like to change it to 
> a positive value (which is calculated, but in the test I just hard 
> coded it to 10). In the process of doing so, I ran into a surprise. 
> Here's a Spock test case that illustrates it:
>
> import spock.lang.Specification
>
> class ElvisTest extends Specification {
>   def "test"() {
>     setup:
>     def sleepFor = -1
>     sleepFor = sleepFor > 0 ?: 10
>     println sleepFor
>     sleepFor = 972
>     sleepFor = sleepFor > 0 ?: 10
>     println sleepFor
>   }
> }
> When sleepFor is initialized to -1, the operator works as I expected 
> it and my println statement prints 910. If I initialize sleepFor to 
> some other value like the one in the test, all of a sudden the result 
> of the Elvis operator is true instead of an integer. I naïvely thought 
> that ?: would yield the numeric value of the sleepFor variable in the 
> left hand expression instead of the boolean result of it (as in 
> sleepFor > 0). What am I missing? In this case, I could always use the 
> Java style of:
>
> sleepFor = sleepFor > 0 ? sleepFor : 10
>
> but the whole point of the Elvis operator is brevity, and this 
> behavior was a small surprise to me. Thanks,
>
> -H
>