What is the difference between ==~ and != in Groovy? - groovy

What is the difference between these?
Why use one over the other?
def variable = 5
if( variable ==~ 6 && variable != 6 ) {
return '==~ and != are not the same.'
} else {
return '==~ and != are the same.'
}

In groovy, the ==~ operator (aka the "match" operator) is used for regular expression matching. != is just a plain old regular "not equals". So these are very different.
cf. http://groovy-lang.org/operators.html

In Java, != is “not equal to” and ~ is "bitwise NOT". You would actually be doing variable == ~6.
In Groovy, the ==~ operator is "Regex match". Examples would be:
"1234" ==~ /\d+/ -> evaluates to true
"nonumbers" ==~ /\d+/ -> evaluates to false

In Groovy you also have to be aware that in addition to ==~, alias "Match operator", there is also =~, alias "Find Operator" and ~, alias "Pattern operator".
All are explained here.
==~ result type: Boolean/boolean (there are no primitives in Groovy, all is not what it seems!)
=~ result type: java.util.regex.Matcher
~ result type: java.util.regex.Pattern
I presume the Groovy interpreter/compiler can distinguish between ~ used as a Pattern operator and ~ used as a bitwise NOT (i.e. its use in Java) through context: the former will always be followed by a pattern, which will always be bracketed in delimiters, usually /.

Related

What is the closest to the reverse of the Elvis operator in Groovy?

So I can replace the old ternary operation:
def something = mainThing != null ? mainThing : "gone!"
with the Elvis operator:
def something = mainThing ?: "gone!"
but is there a groovy way to replace the reverse of that:
def keyValuePair = (mainThing != null ? mainThing + "." : "") + "specific=" + value
where I'm using a prefix plus a dot if the prefix exists?
You can use the ?. safe navigation operator to simplify that expression. The operator currently being used (+) makes this hardly relevant, but assuming a method access (which also happens to be more common), you can type:
def keyValuePair = mainThing?.concat('.') ?: "" + "specific=" + value
That uses .concat instead of + for string concatenation [you can use .plus() :-)], and then uses ?:. mainThing?.concat('.') returns null if mainThing is falsey (by Groovy truth terms), or the result of the method call if it is not.

What is the "?:" operator used for in Groovy?

Trying to understand this line of Groovy code:
return strat?.descriptor?.displayName ?: "null"
Is the ?: a shorthand if/else? Does this mean if strat?.descriptor?.displayName is not null, print it, or else print null ?
I'm confused because there isn't anything between the ? and : like I would normally expect in an if/else statement.
Just to add some more insight, the "?:" operator is known as the binary operator or commonly referred to as the elvis operator. The following code examples all produce the same results where x evaluates to true according to Groovy Truth
// These three code snippets mean the same thing.
// If x is true according to groovy truth return x else return y
x ?: y
x ? x : y // Standard ternary operator.
if (x) {
return x
} else {
return y
}
Click here for more info on Elvis Operator
Yes, the "?:" operator will return the value to the left, if it is not null. Else, return the value to the right.
The ? operator is the one you're asking about. That is the safe navigation operator. It is used to avoid null exception and return null value instead.
You can read more about it here:
https://groovy-lang.org/operators.html#_safe_navigation_operator

How will comparison operators (spaceship operator) be handled in ternary operators

This question is a little preemptive, as php 7 is not even released yet. I'm curious how the spaceship operator will be handled in the context of ternary operators.
so if I have a pre-spaceship ternary expression such as:
$foo = 1;
$bar = 0;
echo 'foo is ' . ( ($foo > $bar) ? 'greater than' : ( ($foo < $bar ) ? 'less than' : 'equal to' ) ) . ' bar.';
what would be the equivalent ternary operator using a comparison operator? Are ternaries going to have some means of handling this scenario? I use ternary operators quite a lot and am curious if there is some way to streamline the code in various instances where a comparison operator would be relevant.
The spaceship operator, as you can see from the documentation of its RFC, was though mainly to be used when having to deal with orderings.
I don't think it could be of help in shortening the code that you posted, mainly beacuse the ternary operator expects a boolean value and the ternary operator returns a "true" value (1 and -1) in both cases when the the values are different. In other words, when you cast its return value to a boolean, the spaceship operator is equivalent to the != operator.
Anyway, you could experiment with it on 3v4l.org, like I did here
Here's a clever approach for using the spaceship operator <=> as a poor man's three-way "ternary", also using an arrow function and array destructuring.
<?php
$relation = fn($a, $b) => [
-1 => 'less than',
0 => 'the same as',
1 => 'greater than'
][$a <=> $b];
$bar = 2;
// loop $foo from 1 through 3
foreach (range(1,3) as $foo) {
echo "foo is " . $relation($foo, $bar) . " bar.\n";
}
?>
Output:
foo is less than bar.
foo is the same as bar.
foo is greater than bar.
But watch out: it's clever, and clever code always requires more mental horsepower to understand, which makes it less maintainable. So there's the warning.

TCL use "eq" or "==" when the argument can be a list or a string

I have the following if loop:
if { expr { $Node_3 eq "BadAngle" } } {
return "BadAngle"
}
Node_3 can be a list containing coordinates, or the simple string "BadAngle"
I use TCLPro 1.4 for debugging and TCL 8.6. I get:
*syntax error in expression " expr { $Node_3 eq "BadAngle" } "*
I then also tried:
if { [ expr { $Node_3 eq "BadAngle" ] == 1 } } {
return "BadAngle"
}
But i get the same error.
Also: What is the better alternative in this case: To use "==" or "eq", I think "eq" because a list is a kind of a string..or?
You seem to be getting in a bit of a pickle there. Firstly, you probably don't want to use expr inside the if condition, so this will be enough:
if { $Node_3 eq "BadAngle" } {
return "BadAngle"
}
Since one of the things you are comparing against is definitely non-numeric, you'll be fine using the eq operator though the == operator is equivalent. The only time there is a difference is when both operands look like numbers, when == will compare them as numbers (parsing them into numbers if necessary). This means that "1" == "0x01" despite them being rather different strings; the eq operator always compares as strings.
How to choose which is best? It's actually pretty easy: do you think you are working with numbers at this point on both sides of the comparison? If yes, use ==, and otherwise use eq.
The one time you want to use expr inside if is when you're dynamically selecting the operator. This is not really recommended, but you'd do it like this:
set op "=="
if { [expr {$Node_3} $op {"BadAngle"} ]} {
return "BadAngle"
}
It's pretty ugly. (Notice that I put everything else inside its own braces to prevent double evaluation, and I'm careful with balancing all the brackets correctly, which is what was tripping you up in the code in your question.) Don't do it unless you really really need to.
You have two distinct problems in your attempts:
In the first example you're trying to call expr in a wrong way: if (and other commands which support conditions, such as while) use the same machinery to evaluate their condition the expr command does — to cite the manual:
The if command evaluates expr1 as an expression (in the same way that expr evaluates its argument).
Now that machinery sees a bare word "expr" and has no idea what to do with it.
There are two ways to fix the code:
Wrong way — properly call expr:
if {[expr {$Node_3 eq "BadAngle"}]} { ... }
This is wrong because the nested call to expr is purely superficial.
Correct way — just drop unneeded expr:
if {$Node_3 eq "BadAngle"} { ... }
In the second example you decided to make the situaton more complicated by introducing another boolean test (not needed as the eq and == operators already return a value of type boolean). But in this case you forgot to put the closing curly brace, }, which performs grouping, for the code should have been
if { [ expr { $Node_3 eq "BadAngle" } ] == 1 } } { ... }
In any case the correct solution is to simply use
if {$Node_3 eq "BadAngle"} { ... }

Groovy different results on using equals() and == on a GStringImpl

According to the Groovy docs, the == is just a "clever" equals() as it also takes care of avoiding NullPointerException:
Java’s == is actually Groovy’s is() method, and Groovy’s == is a clever equals()!
[...]
But to do the usual equals() comparison, you should prefer Groovy’s ==, as it also takes care of avoiding NullPointerException, independently of whether the left or right is null or not.
So, the == and equals() should return the same value if the objects are not null. However, I'm getting unexpected results on executing the following script:
println "${'test'}" == 'test'
println "${'test'}".equals('test')
The output that I'm getting is:
true
false
Is this a known bug related to GStringImpl or something that I'm missing?
Nice question, the surprising thing about the code above is that
println "${'test'}".equals('test')
returns false. The other line of code returns the expected result, so let's forget about that.
Summary
"${'test'}".equals('test')
The object that equals is called on is of type GStringImpl whereas 'test' is of type String, so they are not considered equal.
But Why?
Obviously the GStringImpl implementation of equals could have been written such that when it is passed a String that contain the same characters as this, it returns true. Prima facie, this seems like a reasonable thing to do.
I'm guessing that the reason it wasn't written this way is because it would violate the equals contract, which states that:
It is symmetric: for any non-null reference values x and y, x.equals(y) should return true if and only if y.equals(x) returns true.
The implementation of String.equals(Object other) will always return false when passed a GSStringImpl, so if GStringImpl.equals(Object other) returns true when passed any String, it would be in violation of the symmetric requirement.
In groovy a == b checks first for a compareTo method and uses a.compareTo(b) == 0 if a compareTo method exists. Otherwise it will use equals.
Since Strings and GStrings implement Comparable there is a compareTo method available.
The following prints true, as expected:
println "${'test'}".compareTo('test') == 0
The behaviour of == is documented in the Groovy Language Documentation:
In Java == means equality of primitive types or identity for objects. In Groovy == means equality in all cases. It translates to a.compareTo(b) == 0, when evaluating equality for Comparable objects, and a.equals(b) otherwise. To check for identity (reference equality), use the is method: a.is(b). From Groovy 3, you can also use the === operator (or negated version): a === b (or c !== d).
The full list of operators are provided in the Groovy Language Documentation for operator overloading:
Operator
Method
+
a.plus(b)
-
a.minus(b)
*
a.multiply(b)
/
a.div(b)
%
a.mod(b)
**
a.power(b)
|
a.or(b)
&
a.and(b)
^
a.xor(b)
as
a.asType(b)
a()
a.call()
a[b]
a.getAt(b)
a[b] = c
a.putAt(b, c)
a in b
b.isCase(a)
<<
a.leftShift(b)
>>
a.rightShift(b)
>>>
a.rightShiftUnsigned(b)
++
a.next()
--
a.previous()
+a
a.positive()
-a
a.negative()
~a
a.bitwiseNegate()
Leaving this here as an additional answer, so it can be found easily for Groovy beginners.
I am explicitly transforming the GString to a normal String before comparing it.
println "${'test'}".equals("test");
println "${'test'}".toString().equals("test");
results in
false
true

Resources