Using MetaProgramming to Add collectWithIndex and injectWithIndex similar to eachWithIndex - groovy

Please help with a metaprogramming configuration such that I can add collections methods called collectWithIndex and injectWithIndex that work in a similar manner to eachWithIndex but of course include the base functionality of collect and inject. The new methods would accept a two (three with maps) argument closure just like eachWithIndex. I would like to have the capability to utilize these methods across many different scripts.
Use case:
List one = [1, 2, 3]
List two = [10, 20, 30]
assert [10, 40, 90] == one.collectWithIndex { value, index ->
value * two [index]
}
Once the method is developed then how would it be made available to scripts? I suspect that a jar file would be created with special extension information and then added to the classpath.
Many thanks in advance

I'm still sure, it's not a proper SO question, but I'll give you an example, how you can enrich metaclass for your multiple scripts.
Idea is based on basescript, adding required method to List's metaClass in it's constructor. You have to implement collect logic yourself, through it's pretty easy. You can use wrapping
import org.codehaus.groovy.control.CompilerConfiguration
class WithIndexInjector extends Script {
WithIndexInjector() {
println("Adding collectWithIndex to List")
List.metaClass.collectWithIndex {
int i = 0
def result = []
for (o in delegate) // delegate is a ref holding initial list.
result << it(o, i++) // it is closure given to method
result
}
}
#Override Object run() {
return null
}
}
def configuration = new CompilerConfiguration()
configuration.scriptBaseClass = WithIndexInjector.name
new GroovyShell(configuration).evaluate('''
println(['a', 'b'].collectWithIndex { it, id -> "[$id]:$it" })
''')
// will print [[0]:a, [1]:b]
If you like to do it in more functional way, without repeating collect logic, you may use wrapping proxy closure. I expect it to be slower, but maybe it's not a deal. Just replace collectWithIndex with following implementation.
List.metaClass.collectWithIndex {
def wrappingProxyClosure = { Closure collectClosure, int startIndex = 0 ->
int i = startIndex
return {
collectClosure(it, i++) // here we keep hold on outer collectClosure and i, and use call former with one extra argument. "it" is list element, provided by default collect method.
}
}
delegate.collect(wrappingProxyClosure(it))
}
offtopic: In SO community your current question will only attract minuses, not answers.

Related

Object definition or method call?

In the documentation/section 14.4 I came accross with the following example of code:
task configure << {
def pos = configure(new java.text.FieldPosition(10)) {
beginIndex = 1
endIndex = 5
}
println pos.beginIndex
println pos.endIndex
}
It's not quite clear what the pos and the configure means. I thought configure is just a property, so we can write something like
println configure.beginIndex
but the line causes compile-time error. And
{
beginIndex = 1
endIndex = 5
}
is just a closure, is it?
configure() is a method of the gradle Project object. The documentation of this method explains what it does:
Object configure(Object object, Closure configureClosure)
Configures an object via a closure, with the closure's delegate set to the supplied object. This way you don't have to specify the context of a configuration statement multiple times.
Instead of:
MyType myType = new MyType()
myType.doThis()
myType.doThat()
you can do:
MyType myType = configure(new MyType()) {
doThis()
doThat()
}
So the manual snippet defines an object of type FieldPosition, assigns it to the variable pos, sets its beginIndex and endIndex properties using a closure, thanks to the configure() method of Project, and then prints these properties.
It's a pointless example showing how to use the gradle DSL to configure several properties of an object.

Threadsafe mutable collection with fast elements removal and random get

I need a thread safe data structure with three operations: remove, getRandom, reset.
I have only two ideas by now.
First: Seq in syncronized var.
val all: Array[String] = ... //all possible.
var current: Array[String] = Array.empty[String]
def getRandom(): = {
val currentAvailable = current
currentAvailable(Random.nextInt(currentAvailable.length))
}
def remove(s: String) = {
this.syncronized {
current = current diff Seq(s)
}
}
def reset(s: String) = {
this.syncronized {
current = all
}
}
Second:
Maintain some Map[String,Boolean], there bool is true when element currently is present. The main problem is to make a fast getRandom method (not something like O(n) in worst case).
Is there a better way(s) to implement this?
Scala's Trie is a lock free data structure that supports snapshots (aka your currentAvailable) and fast removals
Since I'm not a Scala expert so this answer is general as an example I used Java coding.
in short the answer is YES.
if you use a map such as :
Map<Integer,String> map=new HashMap<Integer,String>(); //is used to get random in constant time
Map<String,Integer> map1=new HashMap<String,Integer>(); //is used to remove in constant time
to store date,
the main idea is to keep the key( in this case the integer) synchronized to be {1 ... size of map}
for example to fill this structure, you need something like this:
int counter=0; //this is a global variable
for(/* all your string (s) in all */ ){
map.put(counter++, s);
}
//then , if you want the removal to be in constant time you need to fill the second map
for(Entry e : map.EntrySet(){
map1.put(e.getValue(),e.getKey());
}
The above code is the initialization. everytime you want to set things you need to do that
then you can achieve a random value with O(1) complexity
String getRandom(){
int i; /*random number between 0 to counter*/
return map.get(i);
}
Now to remove things you use map1 to achive it in constant time O(1);
void remove(String s){
if(!map1.containsKey(s))
return; //s doesn't exists
String val=map.get(counter); //value of the last
map.remove(counter) //removing the last element
int thisCounter= map1.get(s); //pointer to this
map1.remove(s); // remove from map1
map.remove(counter); //remove from map
map1.put(thisCounter,val); //the val of the last element with the current pointer
counter--; //reducing the counter by one
}
obviously the main issue here is to keep the synchronization ensured. but by carefully analyzing the code you should be able to do that.

Groovy ExcelBuilder - help to understand example

I'am trying to understand how this code example works. Unfortunately isn't commented at all.
HSSFRow.metaClass.getAt = { int idx ->
def cell = delegate.getCell(idx)
if(!cell) {
return null
}
def value
switch(cell.cellType) {
case HSSFCell.CELL_TYPE_NUMERIC:
if(HSSFDateUtil.isCellDateFormatted(cell)) {
value = cell.dateCellValue
} else {
value = cell.numericCellValue
}
break
case HSSFCell.CELL_TYPE_BOOLEAN:
value = cell.booleanCellValue
break
default:
value = cell.stringCellValue
break
}
return value
}
}
Can some one please explain me
Why need to override the MetaClass.getAt() method? It's not used directly. How does it work?
What's the cellType, dateCellValue, numericCellValue etc (methods or variables)? Where are they defined?
You don't need to override getAt method but it's overridden to make coding easier. When getAt is overridden it enables using [] syntax when You refer to object as in this line of code return row[idx] (taken from the example). It's operator overloading, see here. Summing up it's not used directly via getAt but with [] syntax.
In groovy when getXXX() method is provided (no arguments) on object x You can just refer to it omitting get so: x.getXXX() is the same as x.XXX. cell is just invocation of getCell() on HSSFRow object, the other methods are invoked on HSSFCell object and exactly the same rule applies.

groovy dsl - is infix operator possible?

Is it possible to create a dsl with infix operators in Groovy ?
I've researched the builder pattern, invokeMethod, propertyInvoke and the MetaClass and I can only see how to use it to create tree structures using prefix operators (polish notation). What I want to do is build tree structures with infix operators that have binding precedence rules.
eg: if this pseudo code evaluates to 8:
add(2,multiply(3, 2))
I want to express it as:
2 add 3 multiply 2
where multiply binds more tightly than add. I'm using arithmetic just as an example - my application is something quite different.
I don't want to write and support my own parser so I'm hoping groovy has a mechanism for this ???
EDIT: While searching for solutions I've found this is possible and well documented in Scala (see chapter 33: Combinator Parsers in Programming in Scala by Martin Odersky).
I see you found an answer in Scala, but anyway, in Groovy, although it needs the dot (or an AST to insert it automatically), it's not hard to do the command tree:
UPDATE: added a floatNode method, whose precedence is based in the precedence list. The nodes with higher precedence "float" upward:
class Operation {
static final precedence = ['minus', 'add', 'multiply', 'divide']
def left, right, method
Operation parent
def invokeMethod(String method, args) {
def o = new Operation(
parent: this, left: right, method: method, right: args[0])
this.floatNode(o)
}
def floatNode(Operation op) {
if (op.hasHigherPrecedenceThan(this)) {
op.parent = this.parent
this.parent = op
if (op.parent) { this.parent = op.parent.floatNode(op) }
return this
}
else {
return op
}
}
def hasHigherPrecedenceThan(Operation o) {
return precedence.indexOf(this.method) > precedence.indexOf(o.method)
}
String toString() { "Operation($left $method $right, parent=$parent)" }
}
Tests:
Integer.metaClass.invokeMethod = { String method, args ->
new Operation(parent: null, method: method, left: delegate, right: args.head())
}
a = 2.add 3 multiply 4 minus 5 divide 6 add 7
println a
The println will output:
Operation(3 minus 5,
parent=Operation(5 add 7,
parent=Operation(2 add 3,
parent=Operation(3 multiply 4,
parent=Operation(5 divide 6, parent=null)))))

Remove key/value from map while iterating

I'm creating a map like this:
def myMap = [:]
The map is basically an object for a key and an int for a value. When I iterate over the map, I decret the value, and if it's 0, I remove it. I already tried myMap.remove(), but I get a ConcurrentModificationError - which is fair enough. So I move on to using it.remove(), which is giving me weird results.
Basically, my code is this:
myMap.each {
it.value--;
if( it.value <= 0 )
it.remove();
}
Simple enough. My problem is, if I print myMap.size() before and after the remove, they're the same. If I call myMap.containsKey( key ), it gives me true, the key is still in there.
But, if I print out the map like this:
myMap.each { System.out.println( "$it.key: $it.value" ); }
I get nothing, and calling myMap.keySet() and myMap.values() return empty.
Anyone know what's going on?
This should be a bit more efficient than Tim's answer (because you only need to iterate over the map once). Unfortunately, it is also pretty verbose
def map = [2:1, 3:4]
def iterator = map.entrySet().iterator()
while (iterator.hasNext()) {
if (iterator.next().value - 1 <= 0) {
iterator.remove()
}
}
// test that it worked
assert map == [3:4]
Can you do something like this:
myMap = myMap.each { it.value-- }.findAll { it.value > 0 }
That will subtract one from every value, then return you a new map of only those entries where the value is greater than zero.
You shouldn't call the remove method on a Map Entry, it is supposed to be a private method used internally by the Map (see line 325 for the Java 7 implementation), so you calling it yourself is getting the enclosing Map into all sorts of bother (it doesn't know that it is losing entries)
Groovy lets you call private methods, so you can do this sort of trickery behind the back of the Java classes
Edit -- Iterator method
Another way would be:
myMap.iterator().with { iterator ->
iterator.each { entry ->
entry.value--
if( entry.value <= 0 ) iterator.remove()
}
}

Resources