Re: [Vala] Implicit lamdas/closures



I justed noted that my main requirement in all this has been that I want it possible to use the same function body whether or not the functions it calls turn out to be synchronous or asynchronous in it's response; this will help me get rid of a load of duplicate function bodies in samba.

So far I've re-moved the sync response handler and just call the async response handler manually to handle sync responses, but thats not nice anyway as I've got no lambda support in C so I have to do my "local vars" struct manually, but in any case it doesn't help with the more complex state machines that do protocol negotiation.

I mention this because I just realised that some of you are coming from a different position in this with different requirements.

I also forgot to reply-to-all so some of you weren't cc'd to my previous message (below)

Sam

Sam Liddicott wrote:
Christian Hergert wrote:

    Christian, when you said:
    var value = yield obj.do_something ();
    Did you mean that the lamda continuation address be implicitly
    passed to do_something()?

    When you talk of the yield returning a value, do you mean to the
    caller? So that yield is equivalent to "return" but just doesn't
    free the local vars?


I'm thinking that if a method uses the yield syntax, that calling method itself would need to be an asynchronous method.


In samba4, A proxied close request of a read-only file would be synchronous because the response could be given to the client immediately without waiting for the response from the server being proxied, but if the file had been written to then it would be an asynchronous request. Similarly for cached file reads, credential fetches etc. So the caller could not always know in advance if the full response will be given synchronously or asynchronously.

Also the caller may be in-process and request a synchronous response precisely because a state-machine setup was too complicated, and this samba code would really benefit from continuation capabilities in vala.

So sometimes, synchronous-ness is not a property of a method itself but of it's execution. A method may-or-may not give a synchronous response, and the caller would have to know how to interpret that (and does).

It also depends on the semantic context (ugh) of the caller; if it's intended only to have a distant effect then it can be said to be synchronous, even if that effect requires multi-stage processing using yield. Even a synchronous request to file-read may use yield in order to process some additionally requested read-ahead blocks, so I think your case doesn't hold in a general sense.

I can see that asynchronous methods might be meaningful to some event driven frameworks but it seems very specific.

I don't think we need (or I don't need) to especially introduce a concept of asynchronous methods, just another way to express and implement lambdas. If the lambda can be implemented as a function pointer and a void* pointer (and with libffi's trampolines we can get by with just a function pointer !) then we can cope with all cases including specific frameworks.

I'm now pressing for concensus on some aspects

Does anyone have concern with the implementation that has
* the message body with a load of goto's at the top, and then
* an entry-wrapper for the main function to setup the local vars struct,
* an entry-wrapper for each callback entry point to process additional arguments and set the goto-point
?

Are people happy that the continuation lambdas should accept parameters as lambdas currently do? Do people prefer the [out] notation of a fake yield function call to receive the extra parameters or some other notation?

If labels are out of favour (reminder)

something.callback=label_name;
return STATUS_ASYNC;
label_name(int extra_param):
do_something_with(extra_param);

is this preferred:

something.callback=yield([out] int extra_param) {
 return STATUS_ASYNC;
};
do_something_with(extra_param);


I prefer the label, because yield() isn't really a function call and making it look line one doesn't help, it's confusing that all it's arguments MUST be [out] and it only allows one callback to be setup; consider this which is possible with normal lambdas and so should be possible with continuation lambdas.

something=send_request();
if (something.async) {
 something.callback=got_result;
 something.error_handler=failed_result;
 return STATUS_ASYNC;
}
got_result:
 stash(something.result);
 result;
failed_result(int error_code):
 log_error(error_code);
 return;
}

The requirement to have "return" looks unclean only if you think that the called function is always asynchronous, which needn't be true even for non-error responses.

I'm not opposed to a yield command or a concept of asynchronous methods to do some of this automatically in simple cases, but I'm pressing for the same capabilities that lambdas currently have, as this would be prefereable to a mass of nested lambda which could do mostly the same thing (not quite) in an ugly way.

Sam

_______________________________________________
Vala-list mailing list
Vala-list gnome org
http://mail.gnome.org/mailman/listinfo/vala-list




[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]