Scripting HelpersARCHIVE
A little piece of Roblox history. Preserved for everyone, one question at a time.Read about the archive →
✓ ANSWER ACCEPTED

What's the difference between coroutine and spawn?

They both seem to achieve the same thing? So what's the difference between the two?

spawn(function()
	while wait(1) do
		print("spawned")
	end
end)
coroutine.resume(coroutine.create(function()
	while wait(1) do
		print("coroutine")
	end
end))

I find it easier to type spawn() over coroutine so I just use it instead.

2 comments

0

I'll just let BlueTalesm answer it.

0

You forgot a parenthasi on the last line.

2 answers

✓ Accepted answer

TL;DR

If you just want two things to happen at once, use spawn. If you want this, make sure you really want this -- usually, you don't need it.

Full Answer

When you just want to spawn a new "thread", you should use spawn.

Coroutines are a really powerful feature of Lua. If your code doesn't make use of coroutine.yield, though, there's no difference from just using spawn.


The Programming in Lua book has a lot of examples on coroutines.

In particular, coroutines make nice iterators.


Let's say we want to print out all of the fibonacci numbers:

function fib(n)
	if n <= 1 then
		return n
	else
		return fib(n - 1) + fib(n - 2)
	end
end

for i = 1, 100 do
	print(fib(i))
end

While it might be nice to do it this, way, the way we have fib written is really, really slow (try it out...!)

A faster fib would look like this:

function fib(n)
	local a, b = 0, 1
	for i = 1, n do
		a, b = b, a + b
	end
	return a
end

But if we use this, we'll still be wasting a bunch of work, because we'll count all the way up each time.

Instead, we can make a coroutine that we repeatedly ask for numbers:

function fibGenerator()
	return coroutine.create(function()
		local a, b = 0, 1
		while true do
			a, b = b, a + b
			coroutine.yield(a)
		end
	end)
end

local fibs = fibGenerator()
for i = 1, 10 do
	local success, value = coroutine.resume(fibs)
	print( value )
end

EDIT: coroutine.resume also returns a success boolean. This will be false if the coroutine is dead, e.g., won't be calling yield ever again. In this case, the coroutine keeps working forever, so there's no point in paying attention to what success is.

Essentially, coroutine.resume is like "calling" the function, and coroutine.yield is like "returning" from the function, but picking up from the same spot as last time.

6 comments

0

That's strange, it works for me.

0

No, you did it right, I am wondering why you need that line: "local fibs = fibGenerator()"

0

fibs has state. If you ask fibGenerator() over and over again, you'll only ever get the first value. But if you ask a saved version, each time you ask you'll get the next one. Alternatively, I could have just made fibGenerator be the function that coroutine.create is given, and then do fib = coroutine.create(fibGenerator) 

0

Oh, fibs is being changed because the coroutine's spot changes each time it is run. Thanks BlueTaslem!

0

local fiveRoot = math.sqrt(5)*.5 local function fibonacci(n) return ((.5 + fiveRoot)^n - (.5 - fiveRoot)^n) / fiveRoot / 2 end

0

What do you mean "usually you don't need it" when talking about spawn()? Do you mean you can find a way around using spawn() and concurrency? Or am I mistaken?

This discussion is preserved as it was. New answers, comments, and votes are closed.