Re: Address of a lambda

2017-07-07 Thread Ali Çehreli via Digitalmars-d-learn

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



Re: Address of a lambda

2017-07-07 Thread ag0aep6g via Digitalmars-d-learn

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();
}


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

2017-07-07 Thread FoxyBrown via Digitalmars-d-learn

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

2017-07-07 Thread Ali Çehreli via Digitalmars-d-learn

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

2017-07-07 Thread NoIdeaForaGoodPseudo via Digitalmars-d-learn

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.


Address of a lambda

2017-07-07 Thread FoxyBrown via Digitalmars-d-learn
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?


Fine:
void main()
{
bool windowDelete(Event event, Widget widget) {	Main.quit(); 
return false; }

MainWindow.addOnDelete();
}

Invalid:

void main()
{
MainWindow.addOnDelete(&((Event event, Widget widget) 
{	Main.quit(); return false; }));

}


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. 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.


Invalid:

bool windowDelete(Event event, Widget widget) {	Main.quit(); 
return false; }


void main()
{
MainWindow.addOnDelete();
}



I do know the difference between a delegate and a function, and I 
suppose addOnDelete should be defined to take a function instead? 
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?


And aside, shouldn't all functions really be delegates? Having a 
closure of the outer scope still holds at the module root 
level(the scope is the module root). While it's an extra argument 
to pass, it could simplify live a bit. The corner cases could be 
handled by explicitly forcing it to be a function.