Re: [Vala] Implicit lamdas/closures



Thanks for your responses everyone.

Christian, in relation to ownership of mutable strings and other ref counting within the closure; I understod that local vars will all be declared on a struct which is allocated on the heap in order to preserve the local vars for when the closure (or closures) are entered. Surely this struct (which must endure for the lifetime of the closures) will have ownership; when the struct is free'd all it's members will be un-ref'd or free'd just as local variables are when a function exits.

Precisely HOW it can be known that the closure is finished with is hard to say. I guess we can say that closures used as linear continuations must only occur once (what if they are nevr used?) but normal closures could be used as often as the subsystem wants to make a callback. It's a problem but not particular to linear continuations

Jürg, I like the yield idea. However it can't dispense with the may_async which was an rpc-server specific control feature; although if the entire rpc server and framework were written in vala with linear continuations, maybe it would not be needed.

It seems like yield only deals with functions that would block, and can't handle actual callbacks, especially if they have additional arguments - something which closures do support.

It seems like the yield mechanism is dependant on features of the underlying event dispatcher like twisted or gnome, and requires the blocking function to integrate with that.

My example permitted non blocking calls that organize a callback "somehow", more like signals I suppose. How would yield deal with a callback from a timer?

Its not that a sync and async version of a function need generating but that the function itself may want to mke multiple async (or not) calls.

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?

Samuel; I looked at having a separate genrated function for each continuation point as you suggested but its only simply possible if the points are at the top level of a function. To have the yield be able to resume inside any code block like loops (and I guess try blocks, I haven't seem how the C is generated) the generated C function really needs to be 1 big body with goto's at the top so as to be able to resume halfway through.

The idea that a function could be marked "asyncable" intreagues me, but I don't like it; it is merely a particular form of delegate lambda, and in my example there was no asyncable blocking function, it is clearly a "request a callback" operation, and the lambda delegate address was not passed as a function argument but asigned to an object delegate field.

I think we all agree that "rest of function as a lambda" is useful and simplifies some async programming knots

I'm suggesting that such "rest of function" lambdas still be able to take additional arguments; if the C label syntax is unpleasant we could express the yield as a function call with [out] arguments to receive the parameters.
E.g.

Instead of:

something.callback=do_more;
return: (or yield)
do_more(FileInfoList f):

We could have

something.callback=yield([out] FileInfoList f);

Where yield returns the name of the generated wrapper function that will re-enter the method body and goto a label that will be emitted in C right after this vala statement has emitted it's C.

Of course that means that assigning the delegate also returns and seems to lose control of the non-final return value. Also in my case there is other setup that needs doing before this non-final return so I don't like the idea that taking the addres of the continuation lambda implies a return. I can see why people don't like labels though.

Maybe the return preamble could be enclosedlike this:

Something.callback=yield([out] FileInfoList f) { request.did-async=true;
Return NT_STATUS_OK; }

So that the resume point wil unambiguously be after any exit code.

I don't just want to do "something" to help async coding, but I want to be able to take the address of and jump back into a lambda.

I posted the "generated" c code seperately:
www.liddicott.com/~sam/sam/rpc_server.html
So it will be easy to see that the wrapper functions for each return type can have different calling signtures and how they can still jump to the right part of the lambda.

Sam



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