Re: Address of a lambda
On Friday, 7 July 2017 at 17:33:33 UTC, FoxyBrown wrote: In gtk, we routinly have to use delegates for callbacks. But the methods that accept these delegates want the address of the delegate, this prevents us from being able to pass a lambda in directly, but there really is not reason why we shouldn't be able to do this? [...] Lambdas are for very localized and small delegates, typically in algorithms and functional programming. Delegates assigned to events in GUI toolkits are often meant to be reusable, e.g assignable to different listeners and also must be known (have addresses) to be usable in GUI designers. That's not what lambda are made for.
Re: Address of a lambda
On 07/07/2017 10:33 AM, FoxyBrown wrote: > In gtk, we routinly have to use delegates for callbacks. But the methods > that accept these delegates want the address of the delegate, I'm not a user but I don't think it's right. According to the following, it takes a delegate: https://github.com/gtkd-developers/GtkD/blob/42ef854f7cd975519926900fe326e220410c028a/demos/gtkD/DemoMultiCellRenderer/DemoMultiCellRenderer.d#L124 wnd.addOnDelete( delegate bool (Event event, Widget widget) { widget.destroy(); Main.quit(); return false; }); > this > prevents us from being able to pass a lambda in directly, but there > really is not reason why we shouldn't be able to do this? I think that's because the lambda is a 'function' if can be for efficiency reasons. > Invalid: > > void main() > { > MainWindow.addOnDelete(&((Event event, Widget widget) {Main.quit(); > return false; })); > } It makes it very difficult to help if there is no code that demonstrates the problem. Here is my attempt and a solution with the addition of the keyword 'delegate': alias Event = int; alias Widget = int; struct MainWindow { static void quit() { } static void addOnDelete(bool delegate(Event, Widget)) { } } MainWindow Main; void main() { // ADDED 'delegate': MainWindow.addOnDelete(delegate (Event event, Widget widget) { Main.quit(); return false; }); } So, there is no need to take the address of a lambda. It's already either a 'function' or a delegate. > I > suppose addOnDelete should be defined to take a function instead? That would limit the users if they wanted to maintain state for the function. > But > how can we create a "delegate function" similar to the nested delegate > in the first case that works so that we can pass them as delegates? Being explicit like above is one way. There is also toDelegate: https://dlang.org/phobos/std_functional.html#toDelegate > And aside, shouldn't all functions really be delegates? Not in a system language like D that tries to avoid unnecessary cost. :) Ali
Re: Address of a lambda
On Friday, 7 July 2017 at 17:52:25 UTC, Ali Çehreli wrote: On 07/07/2017 10:33 AM, FoxyBrown wrote: > [...] the methods > [...] I'm not a user but I don't think it's right. According to the following, it takes a delegate: [...] Thanks, I guess one doesn't need to pass the address(I copied the code from somewhere and it was so I made an assumption). One doesn't need the delegate keyword or &, but the question then is why does & work? Seems to have done not affect the behavior.
Re: Address of a lambda
On 07/07/2017 07:33 PM, FoxyBrown wrote: In gtk, we routinly have to use delegates for callbacks. But the methods that accept these delegates want the address of the delegate, I don't think that's true. As far as I can tell, this is the signature of addOnDelete [1]: gulong addOnDelete(bool delegate(Event, Widget) dlg, ConnectFlags connectFlags=cast(ConnectFlags)0) `dlg` is just a delegate, not a pointer to a delegate. this prevents us from being able to pass a lambda in directly, but there really is not reason why we shouldn't be able to do this? Fine: void main() { bool windowDelete(Event event, Widget widget) {Main.quit(); return false; } MainWindow.addOnDelete(&windowDelete); } Here you're "taking the address" of a method. The result is a delegate, not a pointer to a delegate. The delegate is the address/pointer (plus another pointer to some related context). Invalid: void main() { MainWindow.addOnDelete(&((Event event, Widget widget) {Main.quit(); return false; })); } Remove the `&` operator and it should work. The function literal [2] already makes a delegate. and yet, the only difference is a copy and paste(i.e., a rewrite rule, at most). Surely the compiler can figure out that we can take such an address because anything that actually exists must have an address somewhere. Stuff can exist in registers only. In a function call `f(42)`, 42 likely goes directly into a register, not into memory. Seems like an arbitrary blocker? Even if it saves us from some obscure problems, it should work in most cases and be allowed when used in those cases. What's even stranger is that the function windowDelete must be declared in some type of object, such as another function, so it is actually a delegate, if one has it in the module root then it is a normal function and cannot be passed to addOnDelete, even though, again, there is very little difference. Yeah, that's an interesting oddity. The problem is that the parameters of a `void delegate(int foo, int bar)` are possibly passed differently from those of a `void function(int foo, int bar)`. Related thread: http://forum.dlang.org/post/ofc0lj$2u4h$1...@digitalmars.com [...] I do know the difference between a delegate and a function, and I suppose addOnDelete should be defined to take a function instead? If anything, it should accept both. Not a function instead of a delegate. But how can we create a "delegate function" similar to the nested delegate in the first case that works so that we can pass them as delegates? http://dlang.org/phobos/std_functional.html#toDelegate [1] https://github.com/gtkd-developers/GtkD/blob/5c2ee83aae7425b683709593c5fd44a7ab1db067/generated/gtkd/gtk/Widget.d#L6793 [2] https://dlang.org/spec/expression.html#function_literals
Re: Address of a lambda
On 07/07/2017 10:52 AM, Ali Çehreli wrote: > a solution with the addition of the > keyword 'delegate': As ag0aep6g explained, the 'delegate' keyword was not necessary there. A case where it's needed is when defining a variable. The following code compiles if 'delegate' keyword is present: void foo(int delegate (int)) { } void main() { // 'delegate' keyword needed to compile: auto f = delegate (int i) => i * 2; foo(f); } Ali