lua-users home
lua-l archive

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


Tony:

On Sun, Jan 28, 2018 at 7:34 PM, Tony Papadimitriou <tonyp@acm.org> wrote:
...
>>> The current method (or hack) of implementing co-routines is unnecessarily
>>> verbose and often resulting in hard to understand code.
>> How do you think this will improve?
> Re-read the sentence just above your question to see how.

Did it before, and thought the only proposal was changing
cortoutine.yield by yield, which can already be done with a local.

Or, if changing to be the python way, mutilating it to have generators.


>> In Lua? Coroutines are what they have been in nearly every other
>> system I've used, same functions as packages I've used in C, C++,
>> Pascal and even assembler ( 8 bit one ). Nothing especial to be done
>> in any function used in a coroutine heavy program, just a couple
>> function calls.
> An what more 'special' is done with Python's `yield`?  You just
> replace `return` with `yield` and you turn any function into a
> co-routine.  Can't get much simpler.

No. You turn a function into a generator. A generator is not a
coroutine, as you are very restricted in what you can do with it.

It's been a time since I used it, as generators where not able to do
what I wanted. And TFM (
https://docs.python.org/3/reference/expressions.html#yieldexpr )
states "The yield expression is used when defining a generator
function or an asynchronous generator function and thus can only be
used in the body of a function definition. Using a yield expression in
a function’s body causes that function to be a generator, and using it
in an async def function’s body causes that coroutine function to be
an asynchronous generator.", and a little later "All of this makes
generator functions quite similar to coroutines; they yield multiple
times, they have more than one entry point and their execution can be
suspended. The only difference is that a generator function cannot
control where the execution should continue after it yields; the
control is always transferred to the generator’s caller.". This only
difference is subtle, but very important when using coroutines for
serious work.


Try to take an event loop and move it to coroutine processing, with
the simple "yield" it's a nightmare, that's why they are trying to put
all the "async" stuff in place. With "yield" you have to write all the
code in a single function, not with coroutines. Of course you can add
things like async def / async for, await , but then you are no longer
simple.


> I didn't talk about changing how co-routines are implemented internally,
> (and, as a user, it's none of my business), just how one has to implement
> them in their own Lua code.  Call it 'syntactic sugar' if you like.
> Same as having `a = function() end` be (almost) equivalent to
> `function a() end`

The thing is in lua a coroutine can run any function. You could add
syntactic sugar like...

>
> In other words, I prefer this:
>
> function xxx(n)
>  for i = 1, n do yield i*i end
> end
>
> to this:
>
> function xxx(n)
>  return coroutine.wrap(function() for i = 1, n do coroutine.yield(i*i) end end)
> end


That is an example of basically a very simple generator. Of course
python syntax is better for this, it is what it was dessigned for.

But the problem is, if you make it functionally equivalent to the
second variant, it is not a particularly useful lua idiom, as lua
loops work differently than python ones, in lua you would not even use
a coroutine for that. How are you going to use it, define a function
which returns 1, xxx(n) and coroutine.resume, or sme variant of it, to
be able to use them in a loop?

> Now, if the latter is more appealing to you, good for you.
> "In matters of taste, there can be no disputes."

No dispute, just trying to see your point. Now I think you want
generators, not coroutines, so you prefer generator syntax.

Now try something like the stuff I do in one of my programs. I'm doing
an IVR. When a call comes in I build an object and call it's main
method in a coroutine. The main method eventually calls one "wait for
whatever" method deep in the library, which yields some context info
which I store, and then the IVR creator exits. Then an event, say a
dtmf, comes. From the handler I locate the ivr object based on the
call and resume it, wait method deep in the library returns and IVR
continues. This is not so easy to do if every function in the library
containing a yield is magically turned into a coroutine. In python
they even need yield from to be able to do that, IIRC, another
keyword.

Those kind of things need real coroutines, not generators.


Francisco Olarte.