The following code attempts to react to one Supply
and then, based on the content of some message, change its mind and react to messages from a different Supply
. It's an attempt to provide similar behavior to Supply.migrate but with a bit more control.
my $c1 = Supplier.new;
my $c2 = Supplier.new;
my $s = supply {
my $currently-listening-to = $c1.Supply;
my $other-var = 'foo';
whenever $currently-listening-to {
say "got: $_";
if .starts-with('3') {
say "listening to something new";
$currently-listening-to = $c2.Supply;
$other-var = 'bar';
say $other-var;
}
}
}
$s.tap;
for ^7 {
$c1.emit: "$_ from \$c1";
$c2.emit: "$_ from \$c2";
}
sleep 10;
If I understand the semantics of supply
blocks correctly (highly doubtful!), this block should have exclusive and mutable access to any variables declared inside the supply
block. Thus, I expected this to get the first 4 values from $c1
and then switch to $c2
. However, it doesn't. Here's the output:
ot: 0 from $c1
got: 1 from $c1
got: 2 from $c1
got: 3 from $c1
listening to something new
bar
got: 4 from $c1
got: 5 from $c1
got: 6 from $c1
As that output shows, changing $other-var
worked just as I expected it to, but the attempt to change $currently-listening-to
failed (silently).
Is this behavior correct? If so, what am I missing about the semantics of supply
blocks/other constructs that explains this behavior? I got the same results with react
blocks and when using a Channel
instead of a Supply
, so the behavior is consistent across several multiple concurrency constructs.
(In the interest of avoiding an X-Y problem, the use case that triggered this question was an attempt implement Erlang-style error handling. To do so, I wanted to have a supervising supply
block that listened to its children and could kill/re-launch any children that got into a bad state. But that means listening to the new children – which led directly to the issue described above.)
whenever
as the reactive equivalent offor
". Thanks, that's very helpful – I was thinking ofsupply
/whenever
as the reactive equivalent offor
/when
, so I was expecting to be able to change the "condition" of thewhenever
the way I can change the one for thewhen
. But I see now thatwhenever
is actually doing the (reactive) "iteration", not just matching on the iteration's result the waywhen
does – Dunite