Groovy Optional parameter omit center value - methods

I have a method in groovy. This method has second parameter as param?. I want to omit this parameter and pass only first and third parameter. Is there any way to do it.

Not without changing your class
Why not add a new method that only takes 2 parameters?
Or move the optional parameter to the end and give it a default value?
Or you could define a method that returns a closure that only takes 2 params (and sticks a default value in for the middle parameter)
String threeParams(String a, int b, String c) {
"$a:$b:$c"
}
Closure midCurry(int b) {
{ String a, String c -> threeParams(a, b, c) }
}
def twoParams = midCurry(1)
assert twoParams('tim', 'yates') == 'tim:1:yates'

Related

Method Reference - passing Function to method with Consumer argument

I'm learning about Method References from Java 8 and I have difficulties understanding why does this work?
class Holder {
private String holded;
public Holder(String holded) {
this.holded = holded;
}
public String getHolded() {
return holded;
}
}
private void run() {
Function<Holder, String> getHolded = Holder::getHolded;
consume(Holder::getHolded); //This is correct...
consume(getHolded); //...but this is not
}
private void consume(Consumer<Holder> consumer) {
consumer.accept(null);
}
As you can see in run method - Holder::getHolded returns unbound method reference which you can invoke by passing object of type Holder as an argument. Like this: getHolded.apply(holder)
But why it casts this unbound method reference to Consumer when it is invoked directly as an method argument, and it does not doing it when I'm passing Function explicitly?
Two things here, lambda expressions are poly expressions - they are inferred by the compiler using their context (like generics for example).
When you declare consume(Holder::getHolded);, compiler (under the so-called special void compatibility rule) will infer it to Consumer<Holder>.
And this might not look obvious, but think of a simplified example. It is generally more than ok do call a method and discard it's return type, right? For example:
List<Integer> list = new ArrayList<>();
list.add(1);
Even if list.add(1) returns a boolean, we don't care about it.
Thus your example that works can be simplified to:
consume(x -> {
x.getHolded(); // ignore the result here
return;
});
So these are both possible and valid declarations:
Consumer<Holder> consumer = Holder::getHolded;
Function<Holder, String> function = Holder::getHolded;
But in this case we are explicitly telling what type is Holder::getHolded,, it's not the compiler inferring, thus consume(getHolded); fails, a Consumer != Function after all.
Java 8 introduced 4 important "function shapes" in the package java.util.function.
Consumer -> accepts a method reference (or a lambda expression) that takes one argument but doesn't return anything
Supplier -> accepts a method reference (or a lambda expression) that takes no argument and returns an object.
Function -> accepts a method reference (or a lambda expression) that takes one argument and returns an object.
Predicate -> accepts a method reference (or a lambda expression) that takes one argument and returns a boolean.
Read the Java docs for more detail.
To answer your question on why the first one works but the second one errors out, read following:
The second statement
consume(getHolded);
doesn't work because the type of the argument getHolded is Function<Holder, String> whereas the consume method expects an argument of type Consumer<Holder>. Since there is no parent-child relationship between Function and Consumer, it requires an explicit cast without which the compiler rightly errors out.
The first statement
consume(Holder::getHolded);
works because the method getHolded is declared as public String getHolded() meaning that it doesn't take any argument and returns a String. As per the new void compatibility rule, void types are inferred as the class containing the referenced method. Consider the following statement:
Consumer<Holder> consumer = Holder::getHolded;
This is a valid statement even though the method getHolded doesn't accept any arguments. This is allowed to facilitate inferring void types. Yet another example is the one you have mentioned yourself:
Function<Holder, String> getHolded = Holder::getHolded;
This is also a valid statement where you have said that the function object getHolded is a Function that returns String and accepts a type Holder even though the assigned method reference doesn't take any argument.
Sharing just a summary of the four types of Method References under the hood:
Reference to a static method:
Type::staticMethod ===>>> x -> Type.staticMethod(x)
Reference to an instance method of a particular object:
instance::instanceMethod ===>>> x -> instance.instanceMethod(x)
Reference to an Instance Method of an Arbitrary Object of a Particular Type:
Type::instanceMethod ===>>> x -> x.instanceMethod() OR (x, y) -> x.instanceMethod(y)
Reference to a constructor:
Type::new ===> x -> new Type(x)

Spring AOP get method parameter value based on parameter name

Is it possible to get the method parameter value based on parameter name in Spring AOP.
MethodSignature signature = (MethodSignature) proceedingJoinPoint.getSignature();
Method method = signature.getMethod();
method.getParameters().getName()
// possible to get the paramater names
This approach will get parameter names, not value.
proceedingJoinPoint.getArgs()
will return values not names
Then is it possible to get the value based on a parameter name?
As I searched everywhere does not exist a function that gives parameter value by name and I wrote a simple method that makes this work.
public Object getParameterByName(ProceedingJoinPoint proceedingJoinPoint, String parameterName) {
MethodSignature methodSig = (MethodSignature) proceedingJoinPoint.getSignature();
Object[] args = proceedingJoinPoint.getArgs();
String[] parametersName = methodSig.getParameterNames();
int idx = Arrays.asList(parametersName).indexOf(parameterName);
if(args.length > idx) { // parameter exist
return args[idx];
} // otherwise your parameter does not exist by given name
return null;
}
I searched for the same thing when I had to use AOP for logging function arguments and their values but it seems there is no direct way to get value based on argument name.
What I noticed however us that value returned by method.getParameters().getName() and proceedingJoinPoint.getArgs() was always in sync., i.e., for function
public void foo(String a, String b)
called as
foo("hello", "world");
method.getParameters().getName() returned ["a", "b"] and proceedingJoinPoint.getArgs() returned ["hello", "world"], in order. So you can iterate over the array by index and for each index i, the i'th argument name would correspond to i'th argument value.
I couldn't find a supporting documentation for this behavior but hey, this code has been running on production servers for about an year it never has produced incorrect result. Though I'd be glad if someone can link to a documentation of this behavior. You may even dig into reflectiion's code to verify this behavior.

How do I use [TypeArguments] with a constructor reference in Java 8?

Section 15.13 of the Java Language Specification for Java 8 describes this form of the method reference syntax for creating a constructor reference:
ClassType :: [TypeArguments] new
For example:
String s = "abc";
UnaryOperator<String> test0 = String::new; // String(String) constructor.
String s0 = test0.apply(s);
System.out.println("s0 = " + s0); // Prints "abc".
char[] chars = {'x','y','z'};
Function<char[], String> test1 = String::new; // String(char[]) constructor.
String s1 = test1.apply(chars);
System.out.println("s1 = " + s1); // Prints "xyz"
That all works fine, but it seems that absolutely anything (excluding primitives) can be also supplied for the [TypeArguments] and everything still works:
Here's a silly example to prove the point:
Function<String, String> test2 = String::<LocalDateTime, Thread[]>new; // Compiles !!!???
String s2 = test2.apply("123");
System.out.println("s2 = " + s2); // Prints "123"
A few questions arising:
[1] Since the String class doesn't even use generics, is it valid that the compiler allows the creation of that test2 constructor reference with those meaningless [TypeArguments]?
[2] What would be a meaningful example of using [TypeArguments] when creating a constructor reference?
[3] Under what conditions is it essential to specify [TypeArguments] when creating a constructor reference?
1 15.13.1. Compile-Time Declaration of a Method Reference
If the method reference expression has the form ClassType :: [TypeArguments] new, the potentially applicable methods are a set of notional methods corresponding to the constructors of ClassType.
...
Otherwise, the candidate notional member methods are the constructors of ClassType, treated as if they were methods with return type ClassType. Among these candidates, the methods with appropriate accessibility, arity (n), and type argument arity (derived from [TypeArguments]) are selected, as specified in ยง15.12.2.1.
JLS 15.12.2.1. Identify Potentially Applicable Methods
This clause implies that a non-generic method may be potentially applicable to an invocation that supplies explicit type arguments. Indeed, it may turn out to be applicable. In such a case, the type arguments will simply be ignored.
2 Whenever a constructor is parameterized. I've never stumbled upon one.
public class Foo {
public <T> Foo(T parameter) {
...
Function<String, Foo> test = Foo::<String>new
3 When the compiler can't infer the type.

TDD: What to test in code where is 800 and more possible outputs?

I have class that have properties IsMacro, Value, Visible, DataType and one method GetResolvedValue. I dont know what to test. I do some math and I figure out that there is over 800 possible outputs for that method.
enum DataTypeEnum:
Bool,
String,
DateTime,
Integer,
LongInteger,
Decimal,
...
class Macro
property bool IsMacro;
property string Value;
property bool Visible;
property DataTypeEnum DataType;
function GetResolvedValue(Resolver) {
string value = Value;
if (IsMacro && Visilbe) {
value = Resolver.resolve(value);
}
switch (DataType){
case String:
// returns value if is string e.g.: "text"
// othervise returns empty string
case Bool:
// returns value if is bool string e.g.: "true"
// othervise returns empty string
case DateTime:
// returns value if is DateTime string e.g.: "2/2/2010"
// othervise returns empty string
...
}
}
So it must always return string with value that is valid for associated datatype or empty string.
With this code there is a lot of combinations and I dont know how to test it. Shoud I test all posible solutions?
Listen to your tests!
Even now, before even being written, your tests tell you that this method massively violates the SRP and needs to be refactored.
You should probably extract a whole hierarchy of classes from this one method.

Object method does not receive variadic parameters

This works.
string = <div>foo</div><br /><div>bar</div><br />
ModifyText(string, {"<br\s\/?>": "REPLECED`r`n", "<div>": "<p>", "</div>": "</p>"}*)
msgbox % string
ModifyText(ByRef strHaystack, oParams*) {
for k, v in oParams
strHaystack := RegexReplace(strHaystack, k, v)
}
However, when I do the same thing with a class method, it fails. The class method does not receive the passed object.
string = <div>foo</div><br /><div>bar</div><br />
o := new ByrefTest
o.ModifyText(string, {"<br\s\/?>": "REPLECED`r`n", "<div>": "<p>", "</div>": "</p>"}*)
msgbox % string
class ByrefTest
{
ModifyText(ByRef strHaystack, oParams*) {
for k, v in oParams
strHaystack := RegexReplace(strHaystack, k, v)
}
}
Why is it?
The manual seems to imply something.
This syntax cannot be used when setting properties of objects, since
the last physical parameter is actually the value being assigned.
But it does not sound like it's about this limitation.
The manual says:
The array of parameters may contain named items when directly calling a user-defined function.
The implication is that named items/parameters are not supported in other situations.
When you directly call the user-defined variadic function ModifyText, the named items ("<br\s\/?>", "<div>" and "</div>") are copied into oParams. Note that the object itself is not passed to the function.
When you indirectly call the ByrefTest.ModifyText function by invoking the o object, only numbered items within the array are used (but there aren't any in this case). The named items are ignored.

Resources