can I combine below closures into one or do this in a more functional and elegant way in groovy. I am using the sortMethod in some other places( for testing purpose) too.
for eg : countAndMap should take
["a b c a a c" , "b b c"] and return[x1 : [a:3,c:2,b:1] , x2 : [b:2,c:1]]
def countAndMap(List<String> stringList) {
stringList.withIndex().collect { String s, Integer i -> [(num.call(i)): count.call(s)] }
}
Closure count = {sortMethod.call(it.split().countBy {it}) }
Closure sortMethod = { it.sort { x, y -> x.value <=> y.value } }
Closure num = { "x ${it + 1}".toString()}
there are no errors but I wonder if it's possible to do it in a more functional way
I am not sure what you mean with "more functional", but you could use a fold operation (called inject in groovy):
list = ["a b c a a c" , "b b c"]
def createSortedHistogram(String toCount) {
toCount
.split() // Create list of words
.inject([:]){ acc, word -> acc[word] = 1 + (acc[word] ?: 0);acc} // create histogram
.sort{-it.value} // sort histogram map by value desc
}
def countAndMap(List<String> list) {
list.withIndex().collectEntries{ sublist, i -> ["x ${i+1}": createSortedHistogram(sublist)] }
}
countAndMap(list)
I think the most interesting part is the inject method.
This solution uses the initial value [:] in order to use a map as result. In each iteration the inject operation either adds a new entry with value 1 to the map (if the word/key does not exist in the map) or increases the value of the word/key if it is already present in the map.
See the inject definition from Collections GroovyDoc.
public Object inject(Object initialValue, Closure closure) - Iterates through the given Collection, passing in the initial value to the 2-arg closure along with the first item. The result is passed back (injected) into the closure along with the second item. The new result is injected back into the closure along with the third item and so on until the entire collection has been used. Also known as foldLeft or reduce in functional parlance.
Related
What is idiomatic pattern for TclOO object equals implementation?
Perhaps compare concatenated sorted lists of all properties?
Are there analogs to Scala case classes?
TclOO defines no equality system for you by design; as the objects are in general modifiable, there's no automatic notion that would apply other than object identity, and you can just compare the name of the object to get that (or the results of info object namespace $theObj, if you're being very paranoid; I think Tcl 8.7 will provide more options, but that's not yet accepted).
If you want to define an equality system such as you are proposing, you could do this:
oo::class create PropertyEquals {
method equals {other} {
try {
set myProps [my properties]
set otherProps [$other properties]
} on error {} {
# One object didn't support properties method
return 0
}
if {[lsort [dict keys $myProps]] ne [lsort [dict keys $otherProps]]} {
return 0
}
dict for {key val} $myProps {
if {[dict get $otherProps $key] ne $val} {
return 0
}
}
return 1
}
}
Then you just need to define a properties method on the class you might be comparing, and mix in the equals method from the above.
oo::class create Example {
mixin PropertyEquals
variable _x _y _z
constructor {x y z} {
set _x $x; set _y $y; set _z $z
}
method properties {} {
dict create x $_x y $_y z $_z
}
}
set a [Example new 1 2 3]
set b [Example new 2 3 4]
set c [Example new 1 2 3]
puts [$a equals $b],[$b equals $c],[$c equals $a]; # 0,0,1
Note that Tcl doesn't provide complex collection classes like some other languages (because it has array-like and mapping-like open values) and so doesn't need an object equality (or content hashing) framework to support that.
Normally I think of Groovy's inject method as equivalent to Java 8's reduce, but I seem to have hit an unusual situation.
Say I have a POJO (or POGO) called Book
class Book {
int id
String name
}
If I have a collection of books and want to convert them to a map where the keys are the ids and the values are the books, then in Groovy it's easy enough to write:
Map bookMap = books.inject([:]) { map, b ->
map[b.id] = b
map
}
i.e., for each book, add it to the map under the book's id and return the map.
In Java 8, the same operation would take a completely different approach. Either this:
Map<Integer, Book> bookMap = books.stream()
.collect(Collectors.toMap(Book::getId, b -> b));
or, equivalently,
bookMap = books.stream()
.collect(Collectors.toMap(Book::getId, Function.identity()));
the difference being a matter of style.
What I'm wondering, however, is if there is a reduce operation in Java 8 that would be similar to the inject from Groovy. I can't just mimic what I did in Groovy, because in Java 8 the signature for reduce is:
T reduce(T identity, BinaryOperator<T> accumulator)
The BinaryOperator means that both elements of the lambda expression must be of the same type. If it was a BiFunction, I could make the lambda's first argument a HashMap<Integer, Book> and the second argument a Book, but I can't do that with a BinaryOperator. I know there's a three-argument version of reduce, but that doesn't seem to help either.
Am I missing something obvious? Is it just that inject is more general that reduce? Since I already have an idiomatic way of solving the problem in Java, this isn't critical, but I was struck by the differences here.
Yo Ken! :-D
You need the 3 parameter form of reduce, so given:
List<Book> books = Arrays.asList(
new Book(1, "Book One"),
new Book(2, "Tim's memoirs"),
new Book(3, "Harry Potter and the sarcastic cat")
);
You can do:
Map<Integer, Book> reduce = books.stream().reduce(
new HashMap<Integer, Book>(),
(map, value) -> {
map.put(value.id, value);
return map;
},
(a, b) -> {
a.putAll(b);
return a;
}
);
To give:
{
1=Book{id=1, name='Book One'},
2=Book{id=2, name='Tim's memoirs'},
3=Book{id=3, name='Harry Potter and the sarcastic cat'}
}
The first parameter is the thing to collect into:
new HashMap<Integer, Book>(),
The second parameter is a BiFunction that takes the current accumulator, and the next element in the stream, and combines them somehow:
(map, value) -> {
map.put(value.id, value);
return map;
},
The third binary operator in that reduce call:
(a, b) -> {
a.putAll(b);
return a;
}
Is how to join all the resulting maps back together assuming you are running a parallel stream...
put and putAll returning void make it a fugly mess :-( But I guess chaining wasn't a popular thing back in the late 90s...
I'm trying to write a mini DSL for some specific task. For this purpose I've been trying to solve a problem like this below (without using parantheses):
give me 5 like romanLetter
give me 5 like word
where the first line would return "V" and the second "five"
My definitions for the first part give me 5 look like this
def give = { clos -> clos() }
def me = { clos -> [:].withDefault { it
println it}
}
and then give me 5 prints 5
The problem is how to add more metaclass methods on the right. E.g.
give me 5 like romanLetter -> prints V OR
give me 5 like word -> prints five
my intuition is that I define like as
Object.metaClass.like = {orth -> if (orth.equals("roman")){ println "V"}
else {println "five"} }
this metaClass method like works only if there is a returned value from the left to be applied to, right? I tried adding a return statement in all of the closures which are on the left side but I always receive
groovy.lang.MissingPropertyException: No such property: like
for class: com.ontotext.paces.rules.FERulesScriptTest ...
do you have an idea how shall I do?
========================================
Here is the application of what I'm asking for.
I want to make a rule as follows
add FEATURE of X opts A,B,C named Y
where add is a closure, of, opts and named are MetaClass methods (at least that's how i imagine it), X, A, B, C, Y are parameters most probably strings and FEATURE is either a MetaClass property, or a closure without arguments or a closure with arguments.
If FEATURE does not take arguments then it is enough that add takes FEATURE as argument and returns a value on which
Object.metaClass.of will be executed with parameter X
Object.metaClass.opts will be executed on the returned by OF value with parameters A, B, C
Object.metaClass.named will be executed on the returned by opts value with parameter Y
each one of these metaclass methods sets its parameter as a value in a map, which is passed to a JAVA method when named is called.
I'm not sure this is the best solution for such a problem, but it seems to me such for the moment. The problem is if FEATURE is not a property itself but a closure which takes argument (e.g. feature1 ARG1). Then
add feature1 ARG1 of X opts A,B,C named Y
and this is the case which I'm stuck with. add feature1 ARG1 is the give me 5 part and I'm trying to add the rest to it.
========================================================
EXAMPLES:
I need to have both of the following working:
add contextFeature "text" of 1,2,3 opts "upperCase" named "TO_UPPER"
add length named "LENGTH"
where in the first case by parsing the rule, whenever each metaclass method of, opts, named is called I fill in the corresponding value in the following map:
params = [feature: "text",
of: 1,2,3,
opts: "upperCase",
named: "TO_UPPER"]
ones this map is filled in, which happens when named is parsed, I call a java method
setFeature(params.of, params.named, params.opts, params.feature)
In the second case length is predefined as length = "length", params values will be only
params = [feature : length,
of: null,
opts: null,
named: "LENGTH"]
and since of is null another java method will be called which is addSurfaceFeature(params.feature, params.named). The second case is more or less streight forward, but the first one is the one I can't manage.
Thanks in advance! Iv
You can do this sort of thing... Does that get you close?
def contextFeature( type ) {
"FEATURE_$type"
}
// Testing
new IvitaParser().parse {
a = add text of 1,2,3 opts "upperCase" named "TO_UPPER"
b = add length named "LENGTH"
c = add contextFeature( "text" ) of 1,2,3 opts "upperCase" named "TO_UPPER"
}
assert a == [feature:'text', of:[1, 2, 3], opts:'upperCase', named:'TO_UPPER']
assert b == [feature:'length', of:null, opts:null, named:'LENGTH']
assert c == [feature:'FEATURE_text', of:[1, 2, 3], opts:'upperCase', named:'TO_UPPER']
// Implementation
class IvitaParser {
Map result
def parse( Closure c ) {
c.delegate = this
c.resolveMethod = Closure.DELEGATE_FIRST
c()
}
def propertyMissing( String name ) {
name
}
def add( String param ) {
result = [ feature:param, of:null, opts:null, named:null ]
this
}
def of( Object... values ) {
result.of = values
this
}
def named( String name ) {
result.named = name
result
}
def opts( String opt ) {
result.opts = opt
this
}
}
You can even get rid of the quotes on the definition:
a = add text of 1,2,3 opts upperCase named TO_UPPER
b = add length named LENGTH
As the propertyMissing method just converts unknown properties into a String of their name
I am trying to understand how currying works in functional programming. I have gone through wiki and a couple of questions about the same on SO.
Need help understanding lambda (currying)
What is 'Currying'?
I understand that currying is all about splitting a function that takes n arguments into n or less functions with one argument each. I theoretically comprehend it but I am not able to connect the dots while coding for the same. Perhaps it is my lack of knowledge in functional programming languages or C# (as many answers in the above questions deal with).
Anyway, I understand groovy & java. So I tried to get an outline for the standard add(a,b) function in groovy but I couldn't finish it.
def closure = { arg ->
// ??
}
def add(anotherClosure , a){
return closure // ??
}
Can someone help me understand currying using groovy closures?
You can roll your own currying functionality by writing a closure that takes another closure and a curried parameter to set, and returns a closure that uses this value.
// Our closure that takes 2 parameters and returns a String
def greet = { greeting, person -> "$greeting $person" }
// This takes a closure and a default parameter
// And returns another closure that only requires the
// missing parameter
def currier = { fn, param ->
{ person -> fn( param, person ) }
}
// We can then call our currying closure
def hi = currier( greet, 'Hi' )
// And test it out
hi( 'Vamsi' )
But you're better sticking with the inbuilt Groovy curry method as shown by jalopaba. (there is also rcurry and ncurry which curry from the right, and at a given position respectively)
It should be said, that the Groovy curry method is a misnomer as it is more a case of partial application as you do not need to get down to a closure requiring only a single parameter, ie:
def addAndTimes = { a, b, c -> ( a + b ) * c }
println addAndTimes( 1, 2, 3 ) // 9
def partial = addAndTimes.curry( 1 )
println partial( 2, 3 ) // 9
You can set a fixed value for one or more arguments to a closure instance using the curry() method:
def add = { a, b -> a + b }
def addFive = add.curry(5)
addFive(3) // 5 + 3 = 8
Another example:
def greeter = { greeting, name -> println "${greeting}, ${name}!" }
def sayHello = greeter.curry("Hello")
sayHello("Vamsi") // Hello, Vamsi!
def sayHi = greeter.curry("Hi")
sayHi("Vamsi") // Hi, Vamsi!
I am new to groovy and I've been facing some issues understanding the each{} and eachwithindex{} statements in groovy.
Are each and eachWithIndex actually methods? If so what are the arguments that they take?
In the groovy documentation there is this certain example:
def numbers = [ 5, 7, 9, 12 ]
numbers.eachWithIndex{ num, idx -> println "$idx: $num" } //prints each index and number
Well, I see that numbers is an array. What are num and idx in the above statement? What does the -> operator do?
I do know that $idx and $num prints the value, but how is it that idx and num are automatically being associated with the index and contents of the array? What is the logic behind this? Please help.
These are plain methods but they follow quite a specific pattern - they take a Closure as their last argument. A Closure is a piece of functionality that you can pass around and call when applicable.
For example, method eachWithIndex might look like this (roughly):
void eachWithIndex(Closure operation) {
for (int i = 0; this.hasNext(); i++) {
operation(this.next(), i); // Here closure passed as parameter is being called
}
}
This approach allows one to build generic algorithms (like iteration over items) and change the concrete processing logic at runtime by passing different closures.
Regarding the parameters part, as you see in the example above we call the closure (operation) with two parameters - the current element and current index. This means that the eachWithIndex method expects to receive not just any closure but one which would accept these two parameters. From a syntax prospective one defines the parameters during closure definition like this:
{ elem, index ->
// logic
}
So -> is used to separate arguments part of closure definition from its logic. When a closure takes only one argument, its parameter definition can be omitted and then the parameter will be accessible within the closure's scope with the name it (implicit name for the first argument). For example:
[1,2,3].each {
println it
}
It could be rewritten like this:
[1,2,3].each({ elem ->
println elem
})
As you see the Groovy language adds some syntax sugar to make such constructions look prettier.
each and eachWithIndex are, amongst many others, taking so called Closure as an argument. The closure is just a piece of Groovy code wrapped in {} braces. In the code with array:
def numbers = [ 5, 7, 9, 12 ]
numbers.eachWithIndex{ num, idx -> println "$idx: $num" }
there is only one argument (closure, or more precisely: function), please note that in Groovy () braces are sometime optional. num and idx are just an optional aliases for closure (function) arguments, when we need just one argument, this is equivalent (it is implicit name of the first closure argument, very convenient):
def numbers = [ 5, 7, 9, 12 ]
numbers.each {println "$it" }
References:
http://groovy.codehaus.org/Closures
http://en.wikipedia.org/wiki/First-class_function
Normally, if you are using a functional programing language such as Groovy, you would want to avoid using each and eachWithIndex since they encourage you to modify state within the closure or do things that have side effects.
If possible, you may want to do your operations using other groovy collection methods such as .collect or .inject or findResult etc.
However, to use these for your problem, i.e print the list elements with their index, you will need to use the withIndex method on the original collection which will transform the collection to a collection of pairs of [element, index]
For example,
println(['a', 'b', 'c'].withIndex())
EachWithIndex can be used as follows:
package json
import groovy.json.*
import com.eviware.soapui.support.XmlHolder
def project = testRunner.testCase.testSuite.project
def testCase = testRunner.testCase;
def strArray = new String[200]
//Response for a step you want the json from
def response = context.expand('${Offers#Response#$[\'Data\']}').toString()
def json = new JsonSlurper().parseText(response)
//Value you want to compare with in your array
def offername = project.getPropertyValue("Offername")
log.info(offername)
Boolean flagpresent = false
Boolean flagnotpresent = false
strArray = json.Name
def id = 0;
//To find the offername in the array of offers displayed
strArray.eachWithIndex
{
name, index ->
if("${name}" != offername)
{
flagnotpresent= false;
}
else
{
id = "${index}";
flagpresent = true;
log.info("${index}.${name}")
log.info(id)
}
}