Enhanced collections methods on an Iterator - groovy

Is it possible to use the enhanced Collections methods that Groovy provides, like findAll and Collect with an iterator (of class java.util.Iterator) ?

Most of the enhanced methods (including findAll and collect) do work with iterators. You can test it out in the console:
assert [1,2,3].iterator().findAll{ it % 2 } == [1,3]
assert [1,2,3].iterator().collect{ it * 2 } == [2,4,6]
Check out DefaultGroovyMethods for a list of the extra methods groovy provides. In general, whenever your class is an instance of the first arg's type, that method applies to your class. In the case of collect and findAll, iterator uses the Object version. Others, like collectMany have an iterator specific version.

Related

Python Iterable vs Sequence

I don't understand the difference when hinting Iterable and Sequence.
What is the main difference between those two and when to use which?
I think set is an Iterable but not Sequence, are there any built-in data type that is Sequence but not Iterable?
def foo(baz: Sequence[float]):
...
# What is the difference?
def bar(baz: Iterable[float]):
...
The Sequence and Iterable abstract base classes (can also be used as type annotations) follow Python's definition of sequence and iterable. To be specific:
Iterable is any object that defines __iter__ or __getitem__.
Sequence is any object that defines __getitem__ and __len__. By definition, any sequence is an iterable. The Sequence class also defines other methods such as __contains__, __reversed__ that calls the two required methods.
Some examples:
list, tuple, str are the most common sequences.
Some built-in iterables are not sequences. For example, reversed returns a reversed object (or list_reverseiterator for lists) that cannot be subscripted.
When writing a function/method with an items argument, I often prefer Iterable to Sequence.
Hereafter is why and I hope it will help understanding the difference.
Say my_func_1 is:
from typing import Iterable
def my_func_1(items: Iterable[int]) -> None:
for item in items:
...
if condition:
break
return
Iterable offers the maximum possibilities to the caller. Correct calls include:
my_func_1((1, 2, 3)) # tuple is Sequence, Collection, Iterator
my_func_1([1, 2, 3]) # list is MutableSequence, Sequence, Collection, Iterator
my_func_1({1, 2, 3}) # set is Collection, Iterator
my_func_1(my_dict) # dict is Mapping, Collection, Iterator
my_func_1(my_dict.keys()) # dict.keys() is MappingKeys, Set, Collection, Iterator
my_func_1(range(10)) # range is Sequence, Collection, Iterator
my_func_1(x**2 for x in range(100)) # "strict' Iterator, i.e. neither a Collection nor a Sequence
...
... because all areIterable.
The implicit message to a function caller is: transfer data "as-is", just don't transform it.
In case the caller doesn't have data as a Sequence (e.g. tuple, list) or as a non-Sequence Collection (e.g. set), and because the iteration breaks before StopIteration, it is also more performing if he provides an 'strict' Iterator.
However if the function algorithm (say my_func_2) requires more than one iteration, then Iterable will fail if the caller provides a 'strict' Iterator because the first iteration exhausts it. Hence use a Collection:
from typing import Collection
def my_func_2(items: Collection[int]) -> None:
for item in items:
...
for item in items:
...
return
If the function algorithm (my_func_3) has to access by index to specific items, then both Iterable and Collection will fail if the caller provides a set, a Mapping or a 'strict' Iterator.
Hence use a Sequence:
from typing import Sequence
def my_func_3(items: Sequence[int]) -> None:
return items[5]
Conclusion: The strategy is: "use the most generic type that the function can handle". Don't forget that all this is only about typing, to help a static type checker to report incorrect calls (e.g. using a set when a Sequence is required). Then it's the caller responsibility to transform data when necessary, such as:
my_func_3(tuple(x**2 for x in range(100)))
Actually, all this is really about performance when scaling the length of items.
Always prefer Iterator when possible. Performance shall be handle as a daily task, not as a firemen task force.
In that direction, you will probably face the situation when a function only handles the empty use case and delegates the others, and you don't want to transform items into a Collection or a Sequence. Then do something like this:
from more_itertools import spy
def my_func_4(items: Iterable[int]) -> None:
(first, items) = spy(items)
if not first: # i.e. items is empty
...
else:
my_func_1(items) # Here 'items' is always a 'strict' Iterator
return

How to properly use Iterators w/in Python? Python Beginner

I'm trying to clarify some confusion on the use of __iter__() and __next__() methods. Here's an example provided from the reading:
Create an iterator that returns numbers, starting with 1, and each sequence will increase by one (returning 1,2,3,4,5 etc.):
class MyNumbers:
def __iter__(self):
self.a = 1
return self
def __next__(self):
x = self.a
self.a += 1
return x
myclass = MyNumbers()
myiter = iter(myclass)
print(next(myiter))
print(next(myiter))
print(next(myiter))
print(next(myiter))
print(next(myiter))
I'm trying to learn general patterns here, and am confused by myiter = iter(myclass). First the object myclass is created, and belongs to the class MyNumbers. This I understand.
Q: But what's going on with the way myiter is defined? It's a new object myiter set equal to an iter function I don't see defined, and including an entire class as a parameter? How does this work exactly? The reading further suggests these iteration methods to be analogous to __init__ but I don't see the relation. Hows the interpreter exactly go through this code?
Much thank for the time and help.
First of all, let's see the difference between iterable and iterator
In our day-to-day programming life, we use for-loop for often.
In below snippet you see that sampleList is iterable.
sampleList = [5,8,90,1,2]
for num in sampleList:
print num
How the above statement works: (steps involved in for-loop when it's executing)
for-loop gets/receives the iterator
if the iterator has the next item then sets the current index to next available item's index and execute code statement
if the iterator doesn't have the next item break the loop and come out of it
So now we understand that iterator can take action on the next item.
But how much information do we know about the iterator() and iterable() functions?
Iterator:
This contains a method iter() and next()
Here the iterator itself returns iter(). The primary key element to implement for num in sampleList
Iterable:
This contains a method iter(). Here this calls sampleList.iter() to get an iterator.
Now comes the next() definition. difference between the iterable and iterator object is next(). next() has the two action items on it whenever it called.
Update the iterator and point the index to the next item
return the current item.
First off, you're not "passing a classing as an argument". myclass is not a class, it's an instance of the class MyNumbers.
In this case, iter() calls the __iter__() method on thr object you pass, which you defined in the object's class. However, since your __iter__() implementation just returns the object itself, the call to iter() has no effect here.

Get Parameter list of a closure dynamically in Groovy

I have a Closure defined in a groovy file that load with the shell.evaluate() method.
I need to call this closure in by calling program using the shell."$closurename".call(arguments) call.
However to formulate the closure parameters ( argument above) I'd need to now what are the arguments and arguments names that the closure $Closurename accepts. Is there a way of dynamically knowing this in Groovy? I checked in the metaClass.method property but this does not work in my example below.
Below is the example code.
def arguments;
shell.evaluate(new File("/tmp/myGroovyClosureFile.groovy"))
testBlock = "myClosureName"
//Code here to find the parameters for myClosureName and create
//the arguments variable
shell."$testBlock".call(arguments)
As Jeff mentioned, it seems like groovy when generating code for closures anonymizes somehow the parameter names. However, you can still use reflection to get as much information as you can:
def cl = { int a, String b ->
println(a)
println(b)
}
def callMethod = cl.class.methods.find {
it.name == "call"
}
println callMethod.parameterTypes
println callMethod.parameters.name
and outputs:
[int, class java.lang.String]
[arg0, arg1]
Is there a way of dynamically knowing this in Groovy?
You can't really do it dynamically at runtime.

What is the use of "use" keyword/method in groovy?

I read use keyword in Groovy. But could not come out with, for what it has been exactly been used. And i also come with category classes, under this topic,what is that too? And from, Groovy In Action
class StringCalculationCategory {
static def plus(String self, String operand) {
try {
return self.toInteger() + operand.toInteger()
} catch (NumberFormatException fallback) {
return (self << operand).toString()
}
}
}
use (StringCalculationCategory) {
assert 1 == '1' + '0'
assert 2 == '1' + '1'
assert 'x1' == 'x' + '1'
}
With the above code, can anyone say what is the use of use keyword in groovy? And also what the above code does?
See the Pimp My Library Pattern for what use does.
In your case it overloads the String.add(something) operator. If both Strings can be used as integers (toInteger() doesn't throw an exception), it returns the sum of those two numbers, otherwise it returns the concatenation of the Strings.
use is useful if you have a class you don't have the source code for (eg in a library) and you want to add new methods to that class.
By the way, this post in Dustin Marx's blog Inspired by Actual Events states:
The use "keyword" is actually NOT a keyword, but is a method on
Groovy's GDK extension of the Object class and is provided via
Object.use(Category, Closure). There are numerous other methods
provided on the Groovy GDK Object that provide convenient access to
functionality and might appear like language keywords or functions
because they don't need an object's name to proceed them. I tend not
to use variables in my Groovy scripts with these names (such as is,
println, and sleep) to avoid potential readability issues.
There are other similar "keywords" that are actually methods of the Object class, such as with. The Groovy JDK documentation has a list of such methods.
A very good illustration is groovy.time.TimeCategory. When used together with use() it allows for a very clean and readable date/time declarations.
Example:
use (TimeCategory) {
final now = new Date()
final threeMonthsAgo = now - 3.months
final nextWeek = now + 1.week
}

How does the Groovy in operator work?

The Groovy "in" operator seems to mean different things in different cases. Sometimes x in y means y.contains(x) and sometimes it seems to call y.isCase(x).
How does Groovy know which one to call? Is there a particular class or set of classes that Groovy knows about which use the .contains method? Or is the behavior triggered by the existence of a method on one of the objects? Are there any cases where the in operator gets changed into something else entirely?
I did some experimentation and it looks like the in operator is based on the isCase method only as demonstrated by the following code
class MyList extends ArrayList {
boolean isCase(Object val) {
return val == 66
}
}
def myList = new MyList()
myList << 55
55 in myList // Returns false but myList.contains(55) returns true
66 in myList // Returns true but myList.contains(66) returns false
For the JDK collection classes I guess it just seems like the in operator is based on contains() because isCase() calls contains() for those classes.
It's actually all based on isCase. Groovy adds an isCase method to Collections that is based on the contains method. Any class with isCase can be used with in.
in is the "Membership operator".
From the documentation for Groovy 3 (emphasis mine):
8.6. Membership operator
The membership operator (in) is equivalent to calling the isCase
method. In the context of a List, it is equivalent to calling
contains, like in the following example:
def list = ['Grace','Rob','Emmy']
assert ('Emmy' in list) # (1)
(1) equivalent to calling list.contains('Emmy') or list.isCase('Emmy')
So, Groovy always calls isCase, which in case of a List maps to contains.

Resources