Why is lambda expression used in DOTween? - unity3d

I'm using a lambda expression in my C# script in my Unity project to call a function with a parameter when a DOTween callback is called.
It simply looks like this: animation.OnComplete(() => DestroyOnCompleted(children));
It works just fine, but I am note sure why a lambda expression is used in this case. I know it has something to do with delegates, but other than that, I'm not too sure; and I would like to explain it to my exam, if I get asked about it.
Could anyone enlighten me? :-)

Why not? ;)
I don't know that API too much but it seems like it is simply expecting something like
OnComplete(TweenCallback callback)
where TweenCallback from your usage basically seems to equal the c# built-in Action delegate and basically simply a parameter less void
public delegate void TweenCallback();
so whether you pass in this callback as a lambda like
animation.OnComplete(() => DestroyOnCompleted(children));
or anonymous method using the delegate operator like
animation.OnComplete(delegate { DestroyOnCompleted(children); });
or using a method
animation.OnComplete(OnCompletedAnimation);
...
private void OnCompletedAnimation()
{
DestroyOnCompleted(children);
}
is basically equivalent.
The main difference between the first two and the last one is: Where does children come from?
The lambda and delegate way allows you to pass in children from the current scope variables without having to store it in any field!

If you look at the documentation of DotTween, you see that row:
Now looking at the Source Code of DotTween, you can see the definition of TweenCallback:
public delegate void TweenCallback();
So the question now is, what is a delegate void in c#?
A delegate in c# is basically an object that "represent" a function.
But functions are not all the same, they can have parameters in input and return something (or return void).
To understand what kind of function does a delegate represent, try to just remove the keyword delegate.
For example, the TweenCallback without the keyboard delegate is:
public void TweenCaalback()
So the delegate represent a void function that has no parameters in input! (And it is Public).
What does it means represent a function?
It means that this is valid code:
void DoNothing()
{
}
TweenCallback x = DoNothing;
x();
So you can "assign functions" to a delegate that has the same function signature.
In this case, TweenCallback is a delegate void (), so you can assign to it a void() function.
What is a lambda?
A lambda is an expression of that style:
(string name, int age) => { return 3 };
you can read that as "string name and int age go in return 3"
That's a more concise way to describe that function:
int AnonymousFunction (string name, int age) {}
The main difference is that lambdas do not have any name. If you have not any parameter in input the lambda become like this:
() => {return 3;}
If you have only one statement inside the {} you are allowed to write it more shortly as
() => 3;
Final step
Is this valid code?
void DoNothing()
{
}
TweenCallback x = () => DoNothing();
Yes it is! Tween callback is expects a void () function.
() => DoNothing(); Is a lambda (un-named function) that takes nothing in input and calls some other function. It's the shorter version of () => {DoNothing();} that you have to think as void () {DoNothing();}
So when writing
animation.OnComplete(() => DestroyOnCompleted(children));
You are just passing a void () function to OnComplete Method, that makes sense because TweenCallback is a void () delegate.
Notes
As you can see, functions and lambdas expression can be converted implicitly to delegates. But you have to understand that they are all different things, and in more advanced coding scenarios that distinction is not just pure theory.

Related

Difference between Function and Function() in flutter [duplicate]

This question already has an answer here:
Function and Function()
(1 answer)
Closed 5 months ago.
I have a doubt where I'm passing a function as a parameter, for onPressed, like event, I would declare a field like final void Function() onPressed, There are some code where I have seen declarring fields like Function someFunction, I would like to know what is the differnce between using Function and Function(). Thanks,
The main() function came from Java-like languages so it's where all programs started, without it, you can't write any program on Flutter even without UI.
The runApp() function should return a widget that would be attached to the screen as a root of the widget Tree that will be rendered
As we can see in doc, Function is:
part of dart.core;
/// The base class for all function types.
///
/// The run-time type of a function object is subtype of a function type,
/// and as such, a subtype of [Function].
Now, Function(), is literally a function, see the example:
Here you can use this:
final Function() func = () {};
ElevatedButton(
onPressed: func;
)
But you can not:
final Function func = () {};
ElevatedButton(
onPressed: func;
)
Here you get the following error:
The argument type 'Function' can't be assigned to the parameter type 'void Function()?'.dartargument_type_not_assignable
Otherwise, you can use:
Function func() {
return () {};
}
ElevatedButton(
onPressed: func;
)
Use Function somename when you need to return a function from a method.
Use Function() somename when you need to use this, literally, as a function.
As per Flutter docs:
Function is the base class of all the function types. It means it represents all the functions.
Adding parenthesis like: Function() makes it one without any parameter.
To sum up: Function is general and Function() is more specific.
Yep, lets take a look whats is braces actualy means.
The main difference between Method(); and Method, is that in first case, you call a method instant and its all. If you'l try to do var someStuff = Method(), someStuff will get a returning value of Method();
In second case, when you use Method, you actually do not call it, because its a link to a method. Because of it is a link, you cant pass an arguments (which places in braces), and if you try to make set variable like this: var someStuff = Method;, variable someStuff will contains a link to a original Method(), and you can call it in code, and it'l work same.
That means, when you pass a link to a onPressed:, and if link has right signature (in and out param), you haven't write whats goes in method and out, all what you should to do will looks like: onPressed: Method. Dart automatically understand, what params in and out, by comparing theirs signature.

Why can't I create a callback for the List Find method in Moq?

I created an extension method that lets me treat a List as DbSet for testing purposes (actually, I found this idea in another question here on stack overflow, and it's been fairly useful). Coded as follows:
public static DbSet<T> AsDbSet<T>(this List<T> sourceList) where T : class
{
var queryable = sourceList.AsQueryable();
var mockDbSet = new Mock<DbSet<T>>();
mockDbSet.As<IQueryable<T>>().Setup(m => m.Provider).Returns(queryable.Provider);
mockDbSet.As<IQueryable<T>>().Setup(m => m.Expression).Returns(queryable.Expression);
mockDbSet.As<IQueryable<T>>().Setup(m => m.ElementType).Returns(queryable.ElementType);
mockDbSet.As<IQueryable<T>>().Setup(m => m.GetEnumerator()).Returns(queryable.GetEnumerator());
mockDbSet.Setup(d => d.Add(It.IsAny<T>())).Callback<T>(sourceList.Add);
mockDbSet.Setup(d => d.Find(It.IsAny<object[]>())).Callback(sourceList.Find);
return mockDbSet.Object;
}
I had been using Add for awhile, and that works perfectly. However, when I try to add the callback for Find, I get a compiler error saying that it can't convert a method group to an action. Why is sourceList.Add an Action, but sourceList.Find is a method group?
I'll admit I'm not particularly familiar with C# delegates, so it's likely I'm missing something very obvious. Thanks in advance.
The reason Add works is because the List<T>.Add method group contains a single method which takes a single argument of type T and returns void. This method has the same signature as an Action<T> which is one of the overloads of the Callback method (the one with a single generic type parameter, Callback<T>), therefore the List<T>.Add method group can be converted to an Action<T>.
With Find, you are trying to call the Callback method (as opposed to Callback<T>) which expects an Action parameter (as opposed to Action<T>). The difference here is that an Action does not take any parameters, but an Action<T> takes a single parameter of type T. The List<T>.Find method group cannot be converted to an Action because all the Find methods (there is only one anyway) take input parameters.
The following will compile:
public static DbSet<T> AsDbSet<T>(this List<T> sourceList) where T : class
{
var mockDbSet = new Mock<DbSet<T>>();
mockDbSet.Setup(d => d.Find(It.IsAny<object[]>())).Callback<Predicate<T>>(t => sourceList.Find(t));
return mockDbSet.Object;
}
Note that I have called .Callback<Predicate<T>> because the List<T>.Find method expects and argument of type Predicate. Also note I have had to write t => sourceList.Find(t) instead of sourceList.Find because Find returns a value (which means it doesn't match the signature of Action<Predicate<T>>). By writing it as a lambda expression the return value will be thrown away.
Note that although this compiles it will not actually work because the DbSet.Find method actually takes an object[] for it's parameter, not a Predicate<T>, so you will likely have to do something like this:
public static DbSet<T> AsDbSet<T>(this List<T> sourceList) where T : class
{
var mockDbSet = new Mock<DbSet<T>>();
mockDbSet.Setup(d => d.Find(It.IsAny<object[]>())).Callback<object[]>(keyValues => sourceList.Find(keyValues.Contains));
return mockDbSet.Object;
}
This last point has more to do with how to use the Moq library that how to use method groups, delegates and lambdas - there is all sorts of syntactic sugar going on with this line which is hiding what is actually relevant to the compiler and what isn't.

D: Delegates or callbacks?

I found conception of Delegates pretty hard for me. I really do not understand why I can't simply pass one function to another and need to wrap it to Delegate. I read in docs that there is some cases when I do not know it's name and Delegate is only way to call it.
But now I have trouble in understanding conception of callbacks. I tried to find more information, but I can't understand is it's simply call of other function or what is it.
Could you show examples of D callbacks and explain where they can be helpful?
import vibe.d;
shared static this()
{
auto settings = new HTTPServerSettings;
settings.port = 8080;
listenHTTP(settings, &handleRequest);
}
void handleRequest(HTTPServerRequest req,
HTTPServerResponse res)
{
if (req.path == "/")
res.writeBody("Hello, World!", "text/plain");
}
&handleRequest is it callback? How it's work and at what moment it's start?
So within memory a function is just a pile of bytes. Like an array, you can take a pointer to it. This is a function pointer. It has a type of RETT function(ARGST) in D. Where RETT is the return type and ARGST are the argument types. Of course attributes can be applied like any function declaration.
Now delegates are a function pointer with a context pointer. A context pointer can be anything from a single integer (argument), call frame (function inside of another) or lastly a class/struct.
A delegate is very similar to a function pointer type at RETT delegate(ARGST). They are not interchangeable, but you can turn a function pointer into a delegate pointer pretty easily.
The concept of a callback is to say, hey I know you will know about X so when that happens please tell me about X by calling this function/delegate.
To answer your question about &handleRequest, yes it is a callback.
You can pass functions to other functions to later be called.
void test(){}
void receiver(void function() fn){
// call it like a normal function with 'fn()'
// or pass it around, save it, or ignore it
}
// main
receiver(&test); // 'test' will be available as 'fn' in 'receiver'
You need to prepend the function name as argument with & to clarify you want to pass a function pointer. If you don't do that, it will instead call that function due to UFCS (calling without braces). It is not a delegate yet.
The function that receives your callable may do whatever it wants with it. A common example is in your question, a web service callback. First you tell the framework what should be done in case a request is received (by defining actions in a function and making that function available for the framework), and in your example enter a loop with listenHTTP which calls your code when it receives a request. If you want to read more on this topic: https://en.wikipedia.org/wiki/Event_(computing)#Event_handler
Delegates are function pointers with context information attached. Say you want to add handlers that act on other elements available in the current context. Like a button that turns an indicator red. Example:
class BuildGui {
Indicator indicator;
Button button;
this(){
... init
button.clickHandler({ // curly braces: implicit delegate in this case
indicator.color = "red"; // notice access of BuildGui member
});
button.clickHandler(&otherClickHandler); // methods of instances can be delegates too
}
void otherClickHandler(){
writeln("other click handler");
}
}
In this imaginary Button class all click handlers are saved to a list and called when it is clicked.
There were several questions in the OP. I am going to try to answer the following two:
Q: Could you show examples of D callbacks and explain where they can be helpful?
A: They are commonly used in all languages that support delegates (C# for an example) as event handlers. - You give a delegate to be called whenever an event is triggered. Languages that do not support delegates use either classes, or callback functions for this purpose. Example how to use callbacks in C++ using the FLTK 2.0 library: http://www.fltk.org/doc-2.0/html/group__example2.html. Delegates are perfect for this as they can directly access the context. When you use callbacks for this purpose you have to pass along all the objects you want to modify in the callback... Check the mentioned FLTK link as an example - there we have to pass a pointer to the fltk::Window object to the window_callback function in order to manipulate it. (The reason why FLTK does this is that back FLTK was born C++ did not have lambdas, otherwise they would use them instead of callbacks)
Example D use: http://dlang.org/phobos/std_signals.html
Q: Why I can't simply pass one function to another and need to wrap it to Delegate?
A: You do not have to wrap to delegates - it depends what you want to accomplish... Sometimes passing callbacks will just work for you. You can't access context in which you may want to call the callback, but delegates can. You can, however pass the context along (and that is what some C/C++ libraries do).
I think what you are asking is explained in the D language reference
Quote 1:
A function pointer can point to a static nested function
Quote 2:
A delegate can be set to a non-static nested function
Take a look at the last example in that section and notice how a delegate can be a method:
struct Foo
{
int a = 7;
int bar() { return a; }
}
int foo(int delegate() dg)
{
return dg() + 1;
}
void test()
{
int x = 27;
int abc() { return x; }
Foo f;
int i;
i = foo(&abc); // i is set to 28
i = foo(&f.bar); // i is set to 8
}
There are already excellent answers. I just want to try to make simple summary.
Simply: delegate allows you to use methods as callbacks.
In C, you do the same by explicitly passing the object (many times named context) as void* and cast it to (hopefully) right type:
void callback(void *context, ...) {
/* Do operations with context, which is usually a struct */
doSomething((struct DATA*)context, ...);
doSomethingElse((struct DATA*)context, ...);
}
In C++, you do the same when wanting to use method as callback. You make a function taking the object pointer explicitly as void*, cast it to (hopefully) right type, and call method:
void callback(void* object, ...) {
((MyObject*)object)->method(...);
}
Delegate makes this all implicitly.

Timer Thread with passed Function* and Param

I'm working on finishing up my server for my first iPhone application, and I want to implement a simple little feature.
I would like to run a function (perhaps method as well), if another function returns a certain value after a certain waiting period. Fairly simple concept.... right?
Here's my basic foundation.
template <typename T,class TYP>
struct funcpar{
T (*function)(TYP);
TYP parameter;
funcpar(T (*func)(TYP),TYP param);
funcpar& operator=(const funcpar& fp);
};
The goal here is to be able to call funcpar::function(funcpar::parameter) to run the stored function and parameter, and not have to worry about anything else...
When I attempted to use a void* parameter instead of the template, I couldn't copy the memory as an object (because I didn't know what the end object was going to be, or the beginning for that matter) and when I tried multiple timers, every single object's parameter would change to the new parameter passed to the new timer... With the previous struct I have a
question:
Is it possible to make an all-inclusive pointer to this type of object inside a method of a class? Can I templatize a method, and not the whole class? Would it work exactly like a function template?
I have a managing class that holds a vector of these "jobs" and takes care of everything fairly well. I just don't know how to use a templatized function with the struct, or how to utilize templates on a single method in a class..
I'm also utilizing this in my custom simple threadpool, and that's working fairly well, and has the same problems...
I have another question:
Can I possibly store a function with a parameter before it's run? Something like toRun = dontrunmeyet(withThisParameter);? Is my struct even necessary?
Am I going about this whole thing incorrectly?
If this is overly ambiguous, I can set you up with my whole code for context
In order to create a class method that takes a template parameter, yes, it would work almost exactly like a function template. For example:
class A
{
public:
template<typename T>
void my_function(const T& value) { }
};
int main()
{
A test;
test.my_function(5);
return 0;
}
Secondly, for your structure, you can actually turn that into a functor-object that by overloading operator(), lets you call the structure as-if it were a function rather than having to actually call the specific function pointer members inside the structure. For instance, your structure could be re-written to look like this:
#include <iostream>
template <class ReturnType, class ParameterType>
class funcpar
{
private:
ReturnType (*function)(ParameterType);
ParameterType parameter;
public:
funcpar(ReturnType (*func)(ParameterType),ParameterType param):
function(func), parameter(param) {}
funcpar& operator=(const funcpar& fp);
//operator() overloaded to be a function that takes no arguments
//and returns type ReturnType
ReturnType operator() ()
{
return function(parameter);
}
};
int sample_func(int value)
{
return value + 1;
}
int main()
{
funcpar<int, int> test_functor(sample_func, 5);
//you can call any instance of funcpar just like a normal function
std::cout << test_functor() << std::endl;
return 0;
}
BTW, you do need the functor object (or your structure, etc.) in order to bind a dynamic parameter to a function before the function is called in C/C++ ... you can't "store" a parameter with an actual function. Binding a parameter to a function is actually called a closure, and in C/C++, creating a closure requires a structure/class or some type of associated data-structure you can use to bind a function with a specific parameter stored in memory that is used only for a specific instance of that function call.

What does () => mean in C#?

I've been reading through the source code for Moq and I came across the following unit test:
Assert.Throws<ArgumentOutOfRangeException>(() => Times.AtLeast(0));
And for the life of me, I can't remember what () => actually does. I'm think it has something to do with anonymous methods or lambdas. And I'm sure I know what it does, I just can't remember at the moment....
And to make matters worse....google isn't being much help and neither is stackoverflow
Can someone give me a quick answer to a pretty noobish question?
Search StackOverflow for "lambda".
Specifically:
() => Console.WriteLine("Hi!");
That means "a method that takes no arguments and returns void, and when you call it, it writes the message to the console."
You can store it in an Action variable:
Action a = () => Console.WriteLine("Hi!");
And then you can call it:
a();
()=> is a nullary lambda expression. it represents an anonymous function that's passed to assert.Throws, and is called somewhere inside of that function.
void DoThisTwice(Action a) {
a();
a();
}
Action printHello = () => Console.Write("Hello ");
DoThisTwice(printHello);
// prints "Hello Hello "
It's a lambda expression. The most common syntax is using a parameter, so there are no parentheses needed around it:
n => Times.AtLeast(n)
If the number of parameters is something other than one, parentheses are needed:
(n, m) => Times.AtLeast(n + m)
When there are zero parameters, you get the somewhat awkward syntax with the parentheses around the empty parameter list:
() => Times.AtLeast(0)
() => Times.AtLeast(0)
() indicates that the lambda function has no parameters or return value.
=> indicates that a block of code is to follow.
Times.AtLeast(0) calls the Times class's static method AtLeast with a parameter of 0.
That's the definition of a lambda (anonymous) function. Essentially, it's a way to define a function inline, since Assert.Throws takes a function as an argument and attempts to run it (and then verify that it throws a certain exception).
Essentially, the snippet you have there is a unit test that makes sure Times.AtLeast(0) throws a ArgumentOutOfRangeException. The lambda function is necessary (instead of just trying to call the Times.AtLeast function directly from Assert.Throws) in order to pass the proper argument for the test - in this case 0.
MSDN KB article on the topic here: http://msdn.microsoft.com/en-us/library/bb882516.aspx
I don't program in C#, but Googling "C# Lambda" provided this link that answers your question!!!