Applying default groovy method parameter value when passing null - groovy

In Groovy, if I have:
def say(msg = 'Hello', name = 'world') {
"$msg $name!"
}
And then call:
say() // Hello world!
say("hi") // Hi world!
say(null) // null world!
Why is the last one getting interpreted literally as null and not applying the default value? Doesn't this defeat the purpose of default method argument values? I do get that passing null is different from not passing anything w/r/t argument length.
My problem here is that if I now have a method that takes a collection as an argument:
def items(Set<String> items = []) {
new HashSet<>(items)
}
This will throw a NullPointerException if I call items(null) but work fine if I just say items(). In order for this to work right, I have to change the line to be new HashSet<>(items ?: []) which, again, seems to defeat the entire purpose of having default method argument values.
What am I missing here?

In Groovy, default parameters generates overloaded methods. Thus, this:
def items(Set<String> items = []) {
new HashSet<>(items)
}
Will generate these two methods (I used javap to get these values):
public java.lang.Object items(java.util.Set<java.lang.String>);
public java.lang.Object items();
So when you call items(null) you are, in fact, passing some value, and items(Set) method will be used.
You can also refer to this question about default parameters.

Related

How can I use Arrow-kt's Some() in Groovy code?

I'm trying to test my Kotlin code, which has Arrow-kt types, using Spock in Groovy. However, I'm not able to use Arrow-kt's additions such as Some. For example, I have a test as follows:
#Unroll
def "add returns #expected for queryRecord #queryRecord"() {
given:
def ip = "ip"
def rule = "rule"
when:
def result = unit.add(ip, rule)
then:
1 * dynamoDBMapperMock.load(ActionRecord.class, ip) >> queryRecord
result == expected
where:
queryRecord | expected
new ActionRecord() | None.INSTANCE
null | Some(new ActionInternal("ip"))
}
While the first data row succeeds with no problems, the second one fails with the following error:
groovy.lang.MissingMethodException: No signature of method: package.name.EventSpec.Some() is applicable for argument types: (package.name.ActionInternal) values: [ActionInternal(dropletIp=null)]
Possible solutions: Mock(), Spy(), Stub(), dump(), Mock(groovy.lang.Closure), Mock(java.lang.Class)
I've tried .some() as well, but not to avail. Apparently Groovy can't access Kotlin extensions, but Some is simply a data class[1], so I'm not sure why I cannot use it in Groovy.
Yes, you can use Arrow Datatypes in Groovy, the result is not as idiomatic as in Kotlin because the library heavily depends on extension functions and functions in the companion object
Example
import arrow.core.Option
import static arrow.core.OptionKt.getOrElse
static main(args){
println 'What is your name?'
def name = Option.#Companion.fromNullable(System.in.newReader().readLine())
.filterNot { it.isEmpty() }
.map { it.toUpperCase() }
println("Welcome ${getOrElse(name) { 'Anonymous' }}")
}
Output
'Welcome JOHN' (or 'Welcome Anonymous' if the provided name is null or empty)
As you can see, to be able to use getOrElse extension function, we need to import it as a static method
Hint
Do not use Some directly unless you are absolutely sure the value is not null, otherwise, you should rely on Option.fromNullable to safely lift the value to the Option context (i.e create Some or None depending if the value is null or not)

What does curly brackets syntax mean in Groovy?

What does this syntax mean in Groovy?
class CreateMessagePage extends Page {
static at = { assert title == 'Messages : Create'; true }
static url = 'messages/form'
static content = {
submit { $('input[type=submit]') }
MyVeryStrangeForm { $('form') }
errors(required:false) { $('label.error, .alert-error')?.text() }
}
}
(taken from Spring MVC Test HtmlUnit manual)
The question is about Groovy and I would like know the answer in Groovy terms.
What is content? Is it a static variable? Is its name is random or predefined by base class of Page?
What is = (equal sign) after it? Is it an assignment operator?
What is at the right hand side of =? Is this a closure? Or if this an anonymous class? Or if these are the same?
What is submit inside curly braces?
Is this a variable? Why there is no assignment operator after it then?
Is this a function definition? Can I define functions in arbitrary places in Groovy? If this is a function definition, then what is errors then?
Is submit is a function call, receiving { $('input[type=submit]') } as a parameter? If yes, then where is this function can be defined? For example, where is MyVeryStrangeForm defined (is nowhere)?
If this was function call, then it won't work since it's undefined...
Quick answer to all questions: it's a block of code, like anonymous function, called closure in Groovy.
See http://www.groovy-lang.org/closures.html
In Groovy you can reference/pass/set such closure, as in any Functional Language.
So this:
static at = { assert title == 'Messages : Create'; true }
means that class field at will be set to this closure (notice, not result of closure execution, but closure itself, as block of code). Type of at is omitted there, but it could be static def at or static Object at, or static Closure at
This code could be executed anytime later, in different context, with title defined, etc.
This:
submit { $('input[type=submit]') }
means calling a function submit with closure as argument.
If you want to write own function like this, it should be something like:
def submit(Closure code) {
code.call()
}
Brackets could be omitted, so it could be written as submit({$('input[type=submit]')}). Same for other function as well, it could be println 'hello world!' instead of println('hello world').
There's also a common practice to define closure as last argument, like:
def errors(Map opts, Closure code) {
....
}
at this case you could pass first arguments as usual, wrapped in brackets, and closure outside:
errors(required:false) { ...... }
same to:
errors([required: false], { ..... })

Properties in Groovy base scripts

I have a DSL where, if present, a closure called before will be called before every command.
In my setup I have 3 files: The script itself - Script, a ScriptBase, that is 'attached' to the script via a CompilerConfiguration, and a Handler.
In the script I may or may not have a closure called before.
before = {
//Do stuff.
}
Notice the lack of a type declaration, or def. If I understand Groovy correctly, this means that before is a in the binding, and accessible from outside code when evaluated with GroovyShell.evaluate().
In the ScriptBase I do the following:
class ProductSpecificationBase extends Script {
def before = null
}
This script base may or may not be overridden later on.
Then, in the Handler, I'm doing a check for whether a before closure is defined in the script:
def config = new CompilerConfiguration()
config.setScriptBaseClass(ScriptBase.class.name)
def shell = GroovyShell()
evaluatedScript = shell.evaluate(new File(thePathToScript))
if (evaluatedScript.before) {
theEvaluationOfMyScript.before()
}
The code works as expected if the script does contain a before closure, but if it doesn't it returns a MissingPropertyException. I've had a look at what this means, and it seems that my before in the ScriptBase isn't considered a property, and all the examples of using these ScriptBases I've found on the internet give examples of using methods. This is not feasible for my use case I'm afraid. How can I ensure that the closure in the ScriptBase is considered a property instead of a field(as I am assuming it is now).
To be paraphrase: I would like my code to not execute the if block if the script does not contain a before closure as well as not having been overridden in an extension of the ScriptBase. However, I would like the evaluation of evaluatedScript.before to be false as it is an empty/null Closure (i.e. it went all the way up to ScriptBase, and found the null closure)
I like to avoid a try/catch approach if possible.
in your example you would basically call the getter for the before property. To check, if there is a method with the name (and params) check with respondsTo. To see, if there is a property at all with that name use hasProperty (Thanks #dmahapatro for pointing this out)
class X {
void before() { println 'x' }
}
class Y { }
class Z {
def before = { println 'z' }
}
def x = new X()
def y = new Y()
def z = new Z()
assert x.respondsTo('before', null)
assert !y.respondsTo('before', null)
assert !z.respondsTo('before', null)
assert !x.hasProperty('before')
assert !y.hasProperty('before')
assert z.hasProperty('before')
x.before()
z.before()

dart method calling context

I used the below to see how dart calls methods passed in to other methods to see what context the passed in method would/can be called under.
void main() {
var one = new IDable(1);
var two = new IDable(2);
print('one ${caller(one.getMyId)}'); //one 1
print('two ${caller(two.getMyId)}'); //two 2
print('one ${callerJustForThree(one.getMyId)}'); //NoSuchMethod Exception
}
class IDable{
int id;
IDable(this.id);
int getMyId(){
return id;
}
}
caller(fn){
return fn();
}
callerJustForThree(fn){
var three = new IDable(3);
three.fn();
}
So how does caller manager to call its argument fn without a context i.e. one.fn(), and why does callerJustForThree fail to call a passed in fn on an object which has that function defined for it?
In Dart there is a difference between an instance-method, declared as part of a class, and other functions (like closures and static functions).
Instance methods are the only ones (except for constructors) that can access this. Conceptually they are part of the class description and not the object. That is, when you do a method call o.foo() Dart first extracts the class-type of o. Then it searches for foo in the class description (recursively going through the super classes, if necessary). Finally it applies the found method with this set to o.
In addition to being able to invoke methods on objects (o.foo()) it is also possible to get a bound closure: o.foo (without the parenthesis for the invocation). However, and this is crucial, this form is just syntactic sugar for (<args>) => o.foo(<args>). That is, this just creates a fresh closure that captures o and redirects calls to it to the instance method.
This whole setup has several important consequences:
You can tear off instance methods and get a bound closure. The result of o.foo is automatically bound to o. No need to bind it yourself (but also no way to bind it to a different instance). This is way, in your example, one.getMyId works. You are actually getting the following closure: () => one.getMyId() instead.
It is not possible to add or remove methods to objects. You would need to change the class description and this is something that is (intentionally) not supported.
var f = o.foo; implies that you get a fresh closure all the time. This means that you cannot use this bound closure as a key in a hashtable. For example, register(o.foo) followed by unregister(o.foo) will most likely not work, because each o.foo will be different. You can easily see this by trying print(o.foo == o.foo).
You cannot transfer methods from one object to another. However you try to access instance methods, they will always be bound.
Looking at your examples:
print('one ${caller(one.getMyId)}'); //one 1
print('two ${caller(two.getMyId)}'); //two 2
print('one ${callerJustForThree(one.getMyId)}'); //NoSuchMethod Exception
These lines are equivalent to:
print('one ${caller(() => one.getMyId())}');
print('two ${caller(() => two.getMyId())}');
print('one ${callerJustForThree(() => one.getMyId())}';
Inside callerJustForThree:
callerJustForThree(fn){
var three = new IDable(3);
three.fn();
}
The given argument fn is completely ignored. When doing three.fn() in the last line Dart will find the class description of three (which is IDable) and then search for fn in it. Since it doesn't find one it will call the noSuchMethod fallback. The fn argument is ignored.
If you want to call an instance member depending on some argument you could rewrite the last example as follows:
main() {
...
callerJustForThree((o) => o.getMyId());
}
callerJustForThree(invokeIDableMember){
var three = new IDable(3);
invokeIDableMember(three);
}
I'll try to explain, which is not necessarily a strength of mine. If something I wrote isn't understandable, feel free to give me a shout.
Think of methods as normal objects, like every other variable, too.
When you call caller(one.getMyId), you aren't really passing a reference to the method of the class definition - you pass the method "object" specific for instance one.
In callerJustForThree, you pass the same method "object" of instance one. But you don't call it. Instead of calling the object fn in the scope if your method, you are calling the object fn of the instance three, which doesn't exist, because you didn't define it in the class.
Consider this code, using normal variables:
void main() {
var one = new IDable(1);
var two = new IDable(2);
caller(one.id);
caller(two.id);
callerJustForThree(one.id);
}
class IDable{
int id;
IDable(this.id);
}
caller(param){
print(param);
}
callerJustForThree(param){
var three = new IDable(3);
print(three.id); // This works
print(param); // This works, too
print(three.param); // But why should this work?
}
It's exactly the same concept. Think of your callbacks as normal variables, and everything makes sense. At least I hope so, if I explained it good enough.

Mock static method with no parameters in Groovy

I need to mock a static method. I'm using the EMC approach described at Mocking static methods using groovy. Like this
TestDaemon.metaClass.'static'.newDownloadManager = {downloadManager}
The method newDownloadManager has no parameters and for some reason it is not replaced. The original code is called. In debug mode I can see that the closure that I define has a parameter. May be that's the reason? How can I define a closure without parameters? Or how can I mock a static method with no parameters?
Meta class changes aren't visible to Java code. Groovy can't help you to mock a static method that gets called from Java code. You will have to use something like JMockit instead (or refactor the code under test).
A closure written like that has an implicit parameter. Write the closure with { -> } syntax. Example:
x = { println "foo" }
y = { -> println "foo" }
assert x.parameterTypes as List == [Object]
assert y.parameterTypes as List == []

Resources