The program below prints 6 times the value 3.
I want it to print 1 2 3 1 2 3 , because the sleep takes 1 second , and that is longer than going throug the loop. I must have missed something .
puts "start"
channel = Channel(String).new
n = 0
3.times do
n = n + 1
spawn {
m = n
channel.send m.to_s
sleep 1
channel.send m.to_s
}
end
6.times do
puts channel.receive
end
puts "stop"
My guess is the variable “n” is being overridden (those fibers don’t start till much later, after it’s already been overridden). You can get some details by reading through https://crystal-lang.org/reference/guides/concurrency.html (you can work around it with “block arguments” for example).
Would also be grand if the compiler could warn for cases like this. Or maybe even incorporate ameba into the standard compiler? (though to be fair it also missed this particular case) :)
Yes, that’s the reason. spawn just captures the block and executes it eventually, not immediately. By the time it runs, n is already 3 and m is assigned that.
If you move m = n to just above spawn it does what you want. The reason is that m gets a different value of n in each block invocation.