Cord
is a module that emulates the abilities of coroutines but allows you to wait
within Cords. It uses Events instead of using coroutines directly, so it works within the scheduler.
Github: Source and Documentation
Roblox Module: 1381006055 (require
compatible)
Differences from coroutines in Roblox
- If the Cord yields, so does the caller. The caller always waits until the Cord calls
:yield
, returns, or errors. - If you want to run a Cord in parallel, you can use the
:parallel
method instead of:resume
.- This will make Cord work like a coroutine
- You’ll have to check
cord.state
orcord:resumable()
to make sure the cord can be resumed. If you try to resume a running or finished Cord, it will error. - You can get the arguments passed to
:yield
or the return values usingcord:returned()
orcord.outArguments
- If the Cord errors, so does whatever resumed it.
- You can change this behavior by providing an
ErrorBehavior
when you create a Cord. If you do this, you can use Cord.error to check if an error occured.-
Cord:new(function() end, Cord.WARN)
to warn on errors -
Cord:new(function() end, Cord.NONE)
to do nothing on errors -
Cord:new(func, function(cord) --[[handle error]] end)
where the result of the error handler is returned to:resume
-
- You can change this behavior by providing an
Examples
Also available on Github.
-- basics
local cord = Cord:new(function()
Cord:yield(5)
Cord:yield(7)
Cord:yield(9)
end)
print(cord:resume()) -- 5
print(cord:resume()) -- 7
print(cord:resume()) -- 9
-- parameters
local cord = Cord:new(function(i)
Cord:yield(i)
Cord:yield(i + 2)
Cord:yield(i + 4)
end)
print(cord:resume(10)) -- 10
print(cord:resume()) -- 12
print(cord:resume()) -- 14
-- passing things into `:resume`
local cord = Cord:new(function(num1)
local num2 = Cord:yield(num1)
local num3 = Cord:yield(num1 + num2)
return num1 + num2 + num3
end)
-- pass `2` in as `num1`: we get `num1`
print(cord:resume(2)) -- 2
-- pass `3` in as `num2`: we get `num1 + num2`
print(cord:resume(3)) -- 5
-- pass `5` in as `num3`: we get `num1 + num2 + num3`
print(cord:resume(5)) -- 10
-- infinite loops and resume
-- this accumulates numbers: every time you give it a number,
-- it adds your number to its value and returns its value
local cord = Cord:new(function(num)
while true do
local nextNum = Cord:yield(num)
num = num + nextNum
end
end)
print(cord:resume(2)) -- 2
print(cord:resume(3)) -- 5
print(cord:resume(5)) -- 10
-- syntax sugar: we can make things look nicer!
local accumulate = Cord(function(num)
while true do
num = num + Cord:yield(num)
end
end)
print(accumulate(2)) -- 2
print(accumulate(3)) -- 5
print(accumulate(5)) -- 10
-- cords as loop handlers
local cord = Cord(function()
for i = 1, 10 do
Cord:yield(i)
end
end)
for num in cord do
print(num) -- will print 1 through 10
end
-- cords as loop handlers 2
local getNums = function(start, count)
return Cord:new(function()
for i = start, count do
Cord:yield(i)
end
end)
end
for num in getNums(10, 20) do
print(num) -- will print 10 through 20
end
I recently updated Cord to…
- Use string enums instead of integers. This will be easier to read.
- Remove the weird partially-running state that
:running
could check for. You have to yield the Cord from inside the Cord’s main coroutine - Add a
:parallel
method to run the Cord in parallel.
This uses a new module since its changes are not backwards-compatible. I’ve kept the same Github link, though, and you can look in the commit history for the old version.