Groovy - strange Collection#intersect behaviour - groovy

I have code like that:
def a1 = [[1],[2],[3]]
def a2 = [[2],[3],[4]]
a1.intersect(a2)
and as result got:
[]
After some time of research i found out that elements of lists must be instance of Comparable. In DefaultGroovyMethods we can see implementation of intersect method. First thing i noted was the collection (TreeSet) used for checking existence of objects in one of our lists (btw. if HashSet used it worked fine).
I checked the NumberAwareComparator there are two options for checking in compareTo method. The first is the delegation of comparison to another class (eaten exception ?!) and the second is hashCode checking.
The first option DefaultTypeTransformation explained us the behavior.
We can see that only allowed object to be compare are Comparable in other case we got exception eaten later.
My question is why is it like that? There is lack of information in documentation (or am i wrong?) about it. Did i missed something?

Can't find it documented.
Feels like a great pull request contribution to the project on github with a change to the existing documentation/javadoc to make this more explicit?
The elements have to be comparable, as otherwise you can't compare them to check for an intersection, but you're right the documentation isn't explicit.
You could write your own implementation like so:
Collection.metaClass.equalityIntersect = { Collection other ->
delegate.findAll { a -> other.find { it == a } }
}
So that a1.equalityIntersect(a2) == [[2], [3]]

This behavior has been introduced somewhere down the line - haven't pin-pointed it, maybe 2.4.2 or 2.4.2 as per this commit. It used to work in 2.2.1 and 2.4.0 and is broken on 2.4.6... but it's fixed in 2.4.7.
$ groovy -v
Groovy Version: 2.4.7 JVM: 1.8.0_92 Vendor: Oracle Corporation OS: Mac OS X
$ groovy intersect.groovy
[[2], [3]]
How can such breaking change roll out to a release is a mystery to me. Lack of testing?

Related

Where can I find an overview of how the ec2.instancesCollection is built

In boto3 there's a function:
ec2.instances.filter()
The documentation:
http://boto3.readthedocs.org/en/latest/reference/services/ec2.html#instance
Say it returns a list(ec2.Instance) I wish...
when I try printing the return I get this:
ec2.instancesCollection(ec2.ServiceResource(), ec2.Instance)
I've tried searching for any mention of an ec2.instanceCollection, but the only thing I found was something similar for ruby.
I'd like to iterate through this instanceCollection so I can see how big it is, what machines are present and things like that.
Problem is I have no idea how it works, and when it's empty iteration doesn't work at all(It throws an error)
The filter method does not return a list, it returns an iterable. This is basically a Python generator that will produce the desired results on demand in an efficient way.
You can use this iterator in a loop like this:
for instance in ec2.instances.filter():
# do something with instance
or if you really want a list you can turn the iterator into a list with:
instances = list(ec2.instances.filter())
I'm adding this answer because 5 years later I had the same question and went round in circles trying to find the answer.
First off, the return type in the documentation is wrong (still). As you say, it states that the return type is: list(ec2.Instance)
where it should be:ec2.instancesCollection.
At the time of writing there's an open issue in github covering this - https://github.com/boto/boto3/issues/2000.
When you call the filter method a ResourceCollection is created for the particular type of resource against which you called the method. In this case the resource type is instance which gives an instancesCollection. You can see the code for the ResourceCollection superclass of instancesCollection here:
https://github.com/boto/boto3/blob/develop/boto3/resources/collection.py
The documentation here gives an overview of the collections: https://boto3.amazonaws.com/v1/documentation/api/latest/guide/collections.html
To get to how to use it and actually answer your question, what I did was to turn the iterator into a list and iterate over the list if the size is > 0.
testList = list(ec2.instances.filter(Filters=filters))
if len(testList) > 0;
for item in testList;
.
.
.
This may well not be the best way of doing it but it worked for me.

Pharo Smalltalk Quick Reference Card

I am trying to introduce some PHP developers Smalltalk.
I seem to remember that the old Pharo website had a link to a Pharo Smalltalk Quick Reference card. If you printed it out it would print on a 8.5 x 11 page - front and back. I can't seem to find this link anymore. Does anyone know where to find this?
This post is probably what you are looking for. It seems unclear who the original author is or which version (there seem to be multiple ones) is the original one. See also this thread on the pharo-dev mailing list for a recent discussion on the topic (you'll find more references in that thread).
I'm copying the postcard code from that post here for completeness:
exampleWithNumber: x
"A method that illustrates every part of Smalltalk method syntax
except primitives. It has unary, binary, and keyboard messages,
declares arguments and temporaries, accesses a global variable
(but not an instance variable), uses literals (array, character,
symbol, string, integer, float), uses the pseudo variables
true, false, nil, self, and super, and has sequence, assignment,
return and cascade. It has both zero argument and one argument blocks."
| y |
true & false not & (nil isNil) ifFalse: [self halt].
y := self size + super size.
#($a #a "a" 1 1.0)
do: [ :each |
Transcript show: (each class name);
show: ' '].
^x < y
I think you are referring to Flyer Cheat Sheet
They sure love to brag about that postcard, but heaven help finding anything but a blurred .png version of it on their website!
Here's the double-sided Pharo Smalltalk cheat sheet / quick reference:
2018 version (pdf)
2013 version (pdf)
P.S. This is from where I found them, in case there is an updated version in the future.

util/Natural unexpected behavior in alloy

I tried the following snippet of Alloy4, and found myself confused by the behavior of the util/Natural module. The comments explain more in detail what was unexpected. I was hoping someone could explain why this happens.
module weirdNatural
private open util/natural as nat
//Somehow, using number two obtained from incrementing one works as I expect, (ie, there is no
//number greater than it in {0,1,2}. but using number two obtained from the natrual/add function
//seems to work differently. why is that?
let twoViaAdd = nat/add[nat/One, nat/One]
let twoViaInc = nat/inc[nat/One]
pred biggerAdd {
some x: nat/Natural | nat/gt[x, twoViaAdd]
}
pred biggerInc {
some y: nat/Natural | nat/gt[y, twoViaInc]
}
//run biggerAdd for 10 but 3 Natural //does not work well, it does find a number gt2 in {0,1,2}
run biggerInc for 10 but 3 Natural //works as expected, it finds a number gt2 in {0,1,2,3}, but not in {0,1,2}
Thanks for this bug report. You are absolutely right, that is a weird behavior.
Alloy4.2 introduced some changes to how integers are handled; namely, the + and - operators in Alloy4.2 are always interpreted as set union/difference, so built-in functions plus/minus have to be used to express arithmetic addition/subtraction. On the other side, the util/natural module (mistakenly) hasn't been updated to use the latest syntax, which was the root cause of the weird behavior you experienced (specifically, the nat/add function uses the old + operator instead of plus, whereas nat/inc doesn't).
To work around this issue, you can either
open the util/natural module (choose "File -> Open Sample Models" from the main menu)
edit the file and replace the two occurrences of <a> + <b> with plus[<a>, <b>]
save the new file in the same folder with your model als file (e.g., as "my_nat.als")
open it from your main module (e.g., open my_nat as nat)
or
download the latest unofficial version where this bug is fixed (you might need to manually delete the Alloy temp folder to make sure that the Alloy Analyzer is not using the old (cached) version of the util/natural library).

JUnit AssertSame fails on object.toString in groovy

I am trying to test the overridden toString() in groovy (I know it is trivial but that is what you get after reading kent beck's TDD book).
I assertSame on the expected string and the actual
Here is the code block:
#Test void testToString(){
def study = new Study(identifier:"default-study", OID:"S_DEFAULTS1", name:"Default Study")
def expected = "org.foo.oc.model.bar(OID:S_DEFAULTS1, name:Default Study, identifier:default-study)"
assertSame "Should be equal", expected, study.toString()
}
Here is the stack trace for the failed test:
junit.framework.AssertionFailedError: Should be equal expected same:org.foo.oc.model.bar(OID:S_DEFAULTS1, name:Default Study, identifier:default-study) was not:org.foo.oc.model.bar(OID:S_DEFAULTS1, name:Default Study, identifier:default-study)
at junit.framework.Assert.fail(Assert.java:47)
at junit.framework.Assert.failNotSame(Assert.java:273)
at junit.framework.Assert.assertSame(Assert.java:236)
Just to add that assertEquals works well with the same parameters.
I know it is no biggie but I want to understand why it fails.
Thanks
Why aren't you using assertEquals which uses .equals()? assertSame compares object references (== operator). Even though the strings are the same, they are two different objects, hence the assertion is failing.
UPDATE: This is a very common mistake in Java: String.equals() and == operator work differently. This has been discussed several times:
How do I compare strings in Java?
Java String.equals versus ==
Difference between Equals/equals and == operator?
I know you are using Groovy which does not suffer this problem, but JUnit is written in Java and behaves according to the rules above.
UPDATE: actually, your string are different:
org.foo.oc.model.bar(OID:S_DEFAULTS1, name:Default Study, identifier:default-study)
org.foo.oc.model.bar(OID:S_DEFAULTS1, name:Default Study, identifier:default-study)
Your original uses lowercase d in "default Study" but your expected string does not.
EDIT: when comparing strings you should always use equals() rather than comparing references. Two strings that pass the equals() test may or may not also be the same object.
BTW, in Groovy == is the same as equals().

groovy list spreading

If you run the following Groovy code, the assertion passes
def foo(a, b) {
a + b
}
assert 'aaabbb' == foo(['aaa', 'bbb'])
This suggests that if a method is called with a List parameter that contains X elements, then the List will be spread and a method with X arguments will be invoked.
Of course, this will only happen if there isn't a method defined with a single parameter of type List (or ancestor thereof).
I only discovered this quite recently when reading another SO Groovy answer. I've never seen it mentioned in the Groovy docs, release notes, or books. Is it a hidden feature, a bug, or just something I've missed?
Going to be removed in Groovy 2 apparently:
http://groovy.329449.n5.nabble.com/removing-features-in-Groovy-2-td4422494.html
JT's first on the to-remove list and it seems everyone (with clout) on Groovy User agrees.

Resources