perl6 how to get specific identity of promises?

2019-06-25 14:34发布

问题:

I am trying to code 3 echo servers running in promises, but I want to know which promise is doing the echoing. Is there a way to do that?

no strict;

for 0 .. 2 -> $index {
    @result[$index] = start {
        $myID = $index; 
        say "======> $myID\n";

        my $rsSocket = IO::Socket::INET.new:
            localhost => 'localhost',
            localport => 1234 + $index,
            listen    => 1;

        while $rsSocket.accept -> $rsConnection {
            say "Promise $myID accepted connection";
            while $rsConnection.recv -> $stuff {
                say "promise $myID Echoing $stuff";
                $rsConnection.print($stuff);
            }
            $rsConnection.close;
        }
    }
}

await @result;

The echo servers run ok; tested with "nc";

The problem is $myID becomes 2 after the promises are created, and there is no way for me to tell which promise is doing the current echoing. It seems that $myID is used by all the promises; is there a way to create variables that are specific to an individual promise?

回答1:

You don't really need to have a $myID at all. You can just use $index in the promise because it has already been scoped to the loop block. Here's a working modification (..with strict on):

my @result = do for 0 .. 2 -> $index {
    start {
        say "======> $index\n";

        my $rsSocket = IO::Socket::INET.new:
            localhost => 'localhost',
            localport => 1234 + $index,
            listen    => 1;

        while $rsSocket.accept -> $rsConnection {
            say "Promise $index accepted connection";
            while $rsConnection.recv -> $stuff {
                say "promise $index Echoing $stuff";
                $rsConnection.print($stuff);
            }
            $rsConnection.close;
        }
    }
}

await @result;

With that taken care of I feel the urge to point out that using no strict seems very unnecessary. Not only does it leave you open to weird scope issues like these, but you gain basically nothing from doing it in your example.

Re-enabling strict on your unmodified code and fixing the two compile errors shows have only saved a total of four keystrokes -- at the expense of however many keys you used typing up your question here.



回答2:

That's one of the thing you "lose" by going with no strict.

What you need is lexical scoping. Using my will give you a different variable each time the block ({ ... }) is entered.

If you do this:

for 0 .. 2 -> $index {
    @result[$index] = start {
        my $myID = $index; 

Then $myID will be local to the start block, and each time that block is called, it'll remember its id. So you'll get the correct ID whenever the socket receives data.