In the code below, I read from a redis queue and trigger callbacks on a local deferrable variable d when the redis operation completes.
It works fine, but I expected to get an error because when the method f returns the variable d goes out of scope. Or does it?
why does this work? is it because the blocks that use d create closures and these closures keep d alive?
require 'em-hiredis'
def f
d = EM::DefaultDeferrable.new
EM::Hiredis.connect.blpop('abcdef', 5).
callback {|x| d.succeed x}.
errback {|e| d.fail e}
d.
callback {|x| puts "value=#{x}"}.
errback {|e| puts "error #{e}"}
return nil
end
EM.run {f}
EDIT: Please notice that the EM::Hiredis instance is local too, and the blocks are attached to it. Are not the blocks supposed to go away with the redis connection when f returns?
Ruby blocks are interesting, because they include a binding to the scope they are defined within.
This means that your deferrable is bound within the block and available to the block, even when the block is executed elsewhere/later.