-
Notifications
You must be signed in to change notification settings - Fork 1
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Coroutines As A Core Language Feature #4
Comments
I'll have to look into coroutines, as I know absolutely nothing about them. I do know that Ruby has coroutines as Fibers, and Scheme has proper coroutines, so I'll look at that. |
I was already considering supporting thunks. How does this relate? |
how would you write the examples using ruby fibers? I'm having trouble doing this and getting the same output as lua. |
Never mind, I got it. fiber = Fiber.new do
state = 1
1.upto 10 do
state = state + Fiber.yield(state)
end
end
while true do
puts fiber.resume(20)
end |
Mmm, the one thing I don't like about the Ruby or Lua coroutine syntax is that it excepts coroutines as a special type of function (you have to use a special class/method), when it's the exact opposite. A function is a subroutine, a subclass of coroutine; every function is equivalent to a single-step coroutine. (Which is one bit the python syntax gets correct) |
As an aside about 'thunks'... thunks are lazy functions? Let me go make a thunk in Lua for my own reference... local thunk = {
__call = function(self, ...)
return self.__func(unpack(self.__params))
end
}
function lazy(f, ...)
return setmetatable({__func = f, __params = {...}}, thunk)
end
local add = lazy(function(a,b)
return a+b
end, 5, 10)
print(add()) --not evaluated until called
--Or equivalently...
function lazy(f, ...)
local a = {...}
return coroutine.wrap(function()
coroutine.yield(f(unpack(a)))
end)
end
local add = lazy(function(a,b)
return a+b
end, 5, 10)
print(add())
--Or, you know...
function curry(f, ...)
local a = {...}
return function (...)
for k,v in ipairs({...}) do
table.insert(a, v)
end
return f(unpack(a))
end
end
local add = curry(function(a,b)
return a+b
end, 5, 10)
print(add()) Yeah, thunks don't seem all too different from currying. Really the main language feature that makes it different is when I have function
If |
A function with no call parameters ( When you do When |
You already have everything you need for 'thunks' then, from what I can tell. Anyway! Back to coroutines. Coroutines would be nice to have at the language level, preferably with some nice native syntax support. Just having the functions that enable them (yield and resume at a minimum) on the base function class would really be all you need, I think. |
I agree. This should be pretty simple. Let's make note of this in the docs somewhere. |
Co-routines are baby threads. Or perhaps super threads. In effect, they are threads whose scheduling is undecided. Python and Lua both implement co-routines at a language level, and for good reason. In python, they are used as an extension to generators, whereas in Lua they are used to model more complex iterator patterns and to handle concurrency issues in non-concurrent systems.
So, more to the point, the language should probably implement co-routines at the language level (for syntax prettiness purposes). A co-routine is a superclass of a function; any function is at least a one-step co-routine. What makes a co-routine different from a generator is that it can consume new inputs on every step (rather than just yielding outputs).
Since Brick is statically typed, co-routines may yield a problem - a co-routine may not want to yield the same type in all cases, and determining if the caller is expecting the correct ones can be difficult.
So, on to the actual syntax. In Python, coroutines were kind of hacked onto generators, so I'm going to ignore its ugly syntax for them:
Lua's syntax is a bit less unnatural, but still cumbersome.
(Lua has some more functions, such as
resume
, if you want to avoid thewrap
shortcut)So, what variety of coroutine syntax would fit in well with the language...?
I think something like
Which has none of the yield-keyword-ambiguity that python has, while avoiding the high verbosity of lua's coroutines. Additionally, using ^ to store a function's state (if we view a function has a state machine) makes sense in this context, also making coroutine 'trampolining' (yielding all the way down to the initial thread/scheduler so it can schedule/start the next task) un-needed, since the child can simply go
(This is actually one of the major problems in a coroutine-based system, the need to trampoline back down to the scheduler to pass inputs around. Being able to avoid that is pretty cool.)
The text was updated successfully, but these errors were encountered: