I use Expression.Call to build MethodCallExpression dynamically. The call is for "First" method.
Then, I need to wrap it to Expression<Func<x,y>> (x and y are types, and it irrelevant to the question). I'm trying to do it with Expression.Lambda<Func<x,y>>, but get Incorrect number of parameters supplied for lambda declaration exception when passing
new ParameterExpression[]{} (i.e. empty array) in the ParameterExpression[] input parameter.
what should be provided to Expression.Lambda when the Lambda takes ZERO parameters?
Action is the delegate that corresponds to a void that accepts no parameters. Func<x, y> says that the method accepts an x and returns a y. All the Func delegates return values, and all the Action delegates are void.
Related
I'm trying to understand the Wire library in Golang and find that in the wire.go there's a function looks like this:
func NewSet(...interface{}) ProviderSet {
return ProviderSet{}
}
It looks foreign to me as to why the ...interface{}) parameter is unnamed (meaning not being used inside the function) but then the caller still passes meaningful values to it?
var Set = wire.NewSet(
wire.Value(Foo(41)),
provideFooBar)
Parameters being named or unnamed has nothing to do with whether the caller having to pass values for them. Being unnamed just means they cannot be used (cannot be referred to) inside the function.
NewSet has a variadic parameter, which means any number of arguments may be passed to it that can be assigned to the type, and any value can be assigned to interface{} (all value implements the empty interface).
The "empty" implementation of NewSet() you see is just a placeholder for documentation and compilers. The generated code will use the passed arguments.
If you have a function:
func dummy(int) {}
You can't call it like dummy(), that's a compile-time error. You can only call it by passing an int value to it, e.g. dummy(1).
See related: Is unnamed arguments a thing in Go?
In python, I can make a function that requires data to be passed in. For example, I can make a function like:
def functionName(x)
and can then use x within the function. When I try this in processing like:
void functionName(x)
it gives me the error message Error on "... VariableDeclaratorId".
Is there a way to pass in data in processing or java like in python?
You have to define the type of the parameter. For example, if the value you want to be passed in is a float, you would define your function as:
void funtionName(float x)
I checked few jenkins shared library examples and I found that in some of them the call method define as below:
def call (Map parameters) { .... }
and in other:
def call (Map parameters = [:]) { .... }
What is the difference between definition of parameters with =[:] and without it ?
Groovy supports a feature feature is called default arguments
The first example requires you to pass in a value for the parameter.
call(['key': 'value'])
The second example can be called that way, but it can also be called without specifying a value and it will use the default:
call()
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)
I would like to declare a function which last parameter is always a callback. However when i do:
interface Statement extends events.EventEmitter {
bind(...args, callback?:(err?:Error)=>void) : Statement;
}
I get an error
error TS1014: Rest parameter must be last in list
Is it possible in typescript to heve Rest parameter not as a last param in the argument list? Is there any hack that could help me solve this problem?
While a rest parameter needs to be the last one, you can now use variadic tuple types in TS 4.0:
type VarCallback<T extends any[]> = (...args: [...T, (err?: Error) => void]) => void
VarCallback ensures, the last function parameter is a callback type (err?: Error) => void.
For example, declare a function type with the first two parameters string and number:
type MyCallback = VarCallback<[string, number]>
// (a1: string, a2: number, a3: (err?: Error | undefined) => void) => void
const myCb: MyCallback = (s, n, cb) => {/* your implementation */ }
// s,n,cb are strongly typed now
Live code sample
This isn't supported in TypeScript. The best you can do is ...args: any[], or only use libraries with more sensible parameter orderings.
The TypeScript spec for the rest parameter is aligned with ES6's: it is the last arg in the param list. You should change your argument order.
from TypeScript Language Spec (#Parameter List):
A signature’s parameter list consists of zero or more required parameters, followed by zero or more
optional parameters, finally followed by an optional rest parameter.
from ES6: rest parameters - Semantics:
The last parameter in the [[FormalParameters]] List is used for the rest parameter. Of the standard built-in ECMAScript objects, only Function objects implement [[HasRestParameters]].