Groovy difference between 'any' and 'find' methods - groovy

In groovy, there are two methods namely any and find method that can be used in Maps.
Both these methods will "search" for the content that we are interested in (that is, both any and find method return whether the element is in Map or not, that is they need to search).
But within this search how do they differ?

They actually do different things. find returns the actual element that was found whereas any produces a bool value. What makes this confusing for you is the groovy truth.
Any unset (null?) value will resolve to false
def x
assert !x
So if you are just checking for false, then the returned values from both methods will serve the same purpose, since essentially all objects have an implicit existential boolean value.

(!list.find{predicate}) <> (!list.any{predicate})
However :
( list.find{predicate}) >< (list.any{predicate})
If any does not exist in Groovy API and you want to add this feature to List metClass, any implementation will be :
java.util.List.metaClass.any={Closure c->
return delegate.find(c) != null
}
Find is more general than any

Related

Kotlin expression giving different results (runtime vs IDE Evaluate expression)

val result: Boolean = aList.union(bList).any { it.something?.someOtherFlag == true }
I have two lists I need to join and check if any of the items has some flag set.
This has been giving me some bad results. During debugging:
the data before the line indicates result = true (true should be the right answer)
I get result = false by running the program
directly after the line, when I use the Evaluate expression tool, I get result = true
What is definitely NOT the problem is that there is NO change in the data in between.
Kotlin versions of my app/IDE plugin are different:
Kotlin Plugin: 203-1.5.0
App: 1.4.21
What I am looking for is an explanation: what can be the problem?
The union method returns a set that will keep only distinct elements, and it might discard different elements when running and when evaluating in debugger. I'm not sure how deterministic it's supposed to be, but the order could matter.
This could happen if equals() and/or hashCode() for your elements are defined without using something, or if equals()/hashCode() for something's class is defined without using someOtherFlag. How are these classes defined?
Note that for data classes, only the properties that are present in the primary constructor are taken into account for the generated equals and hashcode methods.

SOAPUI context variables - How does Groovy make this possible?

Sorry to all you Groovy dudes if this is a bit of a noob question.
In SOAPUI, i can create a Groovy script where i can define an arbitrary variable to the run context to retrieve at a later time.
context.previouslyUndefinedVariable = 3
def num = context.previouslyUndefinedVariable
What feature of Groovy allows previously undefined variables to be added to an object like this? I would like to learn more about it.
Many thanks in advance!
Groovy has the ability to dynamically add methods to a class through metaprogramming.
To learn more, see:
What is Groovy's MetaClass used for?
Groovy Goodness: Add Methods Dynamically to Classes with ExpandoMetaClass
Runtime and compile-time metaprogramming
The accepted answer is a bit of a poor explanation for how SoapUI is doing it.
In this case, context is always an instance of some SoapUI library java class (such as WsdlTestRunContext), and these are all implementations of Map. You can check context.getClass() and assert context in Map.
When you look up a property on a Map, Groovy uses the getAt and putAt methods. There are various syntaxes you can use. All of these are equivalent:
context.someUndef
context.'someUndef'
context[someUndef]
context['someUndef']
context.getAt('someUndef')
And
context.someUndef = 3
context.'someUndef' = 3
context[someUndef] = 3
context['someUndef'] = 3
context.putAt('someUndef', 3)
I like to use any of the above that include quote marks, so that Groovy-Eclipse doesn't flag it as a missing property.
It's also interesting that Groovy looks for a getAt() method before it checks for a get method being referred to as a property.
For example, consider evaluating "foo".class. The String instance doesn't have a property called class and it also doesn't have a method getAt(String), so the next thing it tries is to look for a "get" method with that name, i.e. getClass(), which it finds, and we get our result: String.
But with a map, ['class':'bar'].class refers to the method call getAt('class') first, which will be 'bar'. If we want to know what type of Map it is, we have to be more specific and write in full: ['class':'bar'].getClass() which will be LinkedHashMap.
We still have to specify getClass() even if that Map doesn't have a matching key, because ['foo':'bar'].class will still mean ['foo':'bar'].getAt('class'), which will be null.

How to express validity?

I am creating an Alloy model of the iCalendar data format.
An iCalendar file contains properties. There are a lot of codependencies among the properties. I want to see if anything breaks when a property is removed (i.e., when the property is constrained to zero occurrences).
I want to write an assert and have the Alloy Analyzer search for counterexamples, but I am struggling with how to write the assert. I want the assert to say something like this:
If property X is removed (i.e., property X is constrained to zero
occurrences), there are no instances that are invalid as a result of
removing X.
In pseudocode, I want this:
assert NoProblemFilteringX {
(no prop: X | prop in iCalendar.properties) => all instances are still valid
}
Would you provide some guidance on formulating the desired assert, please?
Suggestion:
Write your codependency checks in a predicate taking as parameter a
set of properties. The predicate holds iff the codependencies are satisfied amongst those properties given in parameter.
Rewrite your fact ensuring those codependencies so as to call this predicate with the set of all iCalendar properties as parameters.
Call this predicate in the assert while this time giving iCalendar.properties - X as parameter

Does groovy ignore the type of null values in method signatures?

To illustrate the following example I created a litte spock test (but it's about groovy itself, not spock):
void "some spock test"() {
given: String value = null
expect: someMethod(value) == 3
}
int someMethod(String s) {
return 3
}
int someMethod(Map s) {
return 5
}
There are two methods who's signatures only differ by the type of the given parameter. I thought that when I give it a null value that is explicitly typed as a string, the string-method will be called.
But that doesn't happen; the test fails, because the map-method is called! Why?
I guess groovy ignores the type and treats all nulls the same. There seems to be some kind of priority of types: When I use Object instead of Map as the parameter type of the wrong-method, its all the same, but when I for instance use Integer, the test succeeds.
But than again: If groovy really ignores the type of nulls, why can the following fix the original test:
expect: someMethod((String) value) == 3
If you read my answer to the question Tim already mentioned you will see that I talk there about runtime types. The static type plays normally no role in this. I also described there how the distance calculation is used and that for null the distance to Object is used to determine the best fitting method. What I did not mention is that you can force method selection by using a cast. Internally Groovy will use a wrapper for the object, that also transports the type. Then the transported type is used instead. But you surely understand, that this means a one additional object creation per method class, which is very inefficient. Thus it is not the standard. In the future Groovy maybe change to include that static type information, but this requires a change to the MOP as well. And that is difficult

Special Groovy magic re property access and collections / iterables?

I understand what is happening here with the spread operator *. in Groovy (2.4.3):
[].class.methods*.name
=> [add, add, remove, remove, get, ...
But why does the leaving the * out produce the same results?
[].class.methods.name
=> [add, add, remove, remove, get, ...
I'd have expected that to be interpreted as accessing the name property of the java.lang.reflect.Method[] returned by methods and so be an error. But it seems to work. Having then experimented a bit more, so do the following:
[*[].class.methods].name
=> [add, add, remove, remove, get, ...
([].class.methods.toList()).name
=> [add, add, remove, remove, get, ...
So it appears attempting to access a property of an array or list (perhaps even Iterable) actually returns a list of that property for each element of the list (as the spread operator would).
So this leaves me wondering:
Is this behaviour documented anywhere? (I don't see it here for example: http://www.groovy-lang.org/operators.html and haven't seen it noted elsewhere in the docs.)
Does this behaviour only apply to 'properties' (i.e. non-arg methods following the getFoo() naming convention)? This seems to be the case from some quick GroovyConsole tests.
Is the spread operator therefore only necessary/useful when calling non-getFoo() style methods or methods with arguments? (Since you can just use . otherwise.)
UPDATE:
It appears to be the case that spread *. works for any Iterable whereas the . only applies to collections. For example:
class Foo implements Iterable {
public Iterator iterator() { [Long.class, String.class].iterator() }
}
(new Foo())*.name
=> [java.lang.Long, java.lang.String]
(new Foo()).name
=> groovy.lang.MissingPropertyException: No such property: name for class: Foo
(I guess this is a good thing: if the Iterable itself later gained a property with the same name, the code would start returning that (single) property from the Iterable - rather than the list property values from the elements.)
That's the GPath expression documented (ish) here, and yes, it only works for properties. (There's an old blog post by Ted Naleid here about digging in to how it worked in 2008)
For methods, you need to use *. or .collect()
See also: Groovy spread-dot operator
Better docs link (as pointed out by #NathanHughes below

Resources