New features of the generator in PHP7: Generator delegate (Yield-from) & return value (Return-value)

Source: Internet
Author: User
This article introduces to you about the new features of the generator in PHP7: Generator delegate (Yield-from) & return Value (Return-value), there is a certain reference value, the need for friends can refer to, I hope to help you.

Builder delegate

Simply translate the description of the official document:

In PHP7, with the generator delegate (yield from), you can delegate other generators, objects that can be iterated, and arrays to the outer generator. The outer generator orders the value of the yield delegate first, and then proceeds to the value defined in the yield itself.

Using yield from allows us to write relatively clear generator nesting, and code nesting calls are required to write complex systems.
above example:

<?phpfunction echotimes ($msg, $max) {for    ($i = 1; $i <= $max; + + $i) {        echo "$msg iteration $i \ n";        yield;    }} function Task () {    yield from echotimes (' foo ', ten);//print Foo ten times    echo "---\ n";    Yield from echotimes (' Bar ', 5); Print Bar five Times}foreach (Task () as $item) {    ;}

The above will output:

Foo Iteration 1foo Iteration 2foo Iteration 3foo Iteration 4foo Iteration 5foo Iteration 6foo Iteration 7foo Iteration 8fo o Iteration 9foo Iteration---bar iteration 1bar Iteration 2bar Iteration 3bar Iteration 4bar Iteration 5

Naturally, the internal generator can also accept information or exceptions sent by its parent generator, because yield from creates a two-way channel for the parent-child generator. Not much to say, on the example:

<?phpfunction echomsg ($msg) {    while (true) {        $i = yield;        if ($i = = = null) {break            ;        }        if (!is_numeric ($i)) {            throw new Exception ("Hoo! Must give me a number ");        }        echo "$msg iteration $i \ n";    }} function Task2 () {    yield from echomsg (' foo ');    echo "---\ n";    Yield from echomsg (' Bar ');} $gen = Task2 (), foreach (Range (1,10) as $num) {    $gen->send ($num);} $gen->send (null), foreach (range (1,5) as $num) {    $gen->send ($num);} $gen->send ("Hello World"); Try it, gay

The output is the same as the previous example.

Generator return value

If the generator is completed by iteration, or if it runs to the return keyword, it will return a value to the generator.
There are two ways to get this return value:

    1. Use the $ret = Generator::getreturn () method.

    2. Use the $ret = yield from Generator () expression.

above example:

<?phpfunction echotimes ($msg, $max) {for    ($i = 1; $i <= $max; + + $i) {        echo "$msg iteration $i \ n";        Yield;    }    Return "$msg the end value: $i \ n";} function Task () {    $end = yield from echotimes (' foo ', ten);    echo $end;    $gen = Echotimes (' Bar ', 5);    Yield from $gen;    echo $gen->getreturn ();} foreach (Task () as $item) {    ;}

The output will not be posted, presumably we all guessed.

You can see that yield from and return combine to make the writing of yield more like the usual code of the synchronization mode we write, after all, this is one of the reasons for the PHP generator characteristics.

A non-blocking Web server

Now we are using these two new features in PHP7 to rewrite this web server with just over 100 lines of code.

The code is as follows:

<?phpclass cosocket{protected $masterCoSocket = null;    Public $socket;    protected $handleCallback;    Public $streamPoolRead = [];    Public $streamPoolWrite = [];        Public function __construct ($socket, cosocket $master = null) {$this->socket = $socket; $this->mastercosocket = $master??    $this;        Public Function Accept () {$isSelect = yield from $this->onread ();        $acceptS = null; if ($isSelect && $as = stream_socket_accept ($this->socket, 0)) {$acceptS = new Cosocket ($as, $this)        ;    } return $acceptS;        The public function read ($size) {yield from $this->onread ();        Yield ($data = fread ($this->socket, $size));    return $data;        Public function Write ($string) {yield from $this->onwriter ();    Yield fwrite ($this->socket, $string); The public function close () {unset ($this->mastercosocket->streampoolread[(int) $this->socket]);        Unset ($this->mastercosocket->streampoolwrite[(int) $this->socket]);        Yield ($success = @fclose ($this->socket));    return $success; Public Function onRead ($timeout = null) {$this->mastercosocket->streampoolread[(int) $this->socket        ] = $this->socket;        $pool = $this->mastercosocket->streampoolread;        $rSocks = [];        $wSocks = $eSocks = null;        foreach ($pool as $item) {$rSocks [] = $item;        Yield ($num = Stream_select ($rSocks, $wSocks, $eSocks, $timeout));    return $num; Public Function onwriter ($timeout = null) {$this->mastercosocket->streampoolwrite[(int) $this-&GT;SOC        KET] = $this->socket;        $pool = $this->mastercosocket->streampoolread;        $wSocks = [];        $rSocks = $eSocks = null;        foreach ($pool as $item) {$wSocks [] = $item; The yield ($num = Stream_select ($rSocks, $wSocks, $eSocks, $timeout));    return $num;        The Public Function onrequest () {/** @var the self $socket */$socket = yield from $this->accept ();        if (empty ($socket)) {return false;        } $data = yield from $socket->read (8192);        $response = Call_user_func ($this->handlecallback, $data);        Yield from $socket->write ($response);    Return yield from $socket->close ();        public static function Start ($port, callable $callback) {echo ' starting server at Port $port ... \ n ';        $socket = @stream_socket_server ("tcp://0.0.0.0: $port", $errNo, $ERRSTR);        if (! $socket) throw new Exception ($ERRSTR, $errNo);        Stream_set_blocking ($socket, 0);        $coSocket = new self ($socket);        $coSocket->handlecallback = $callback; Function Gen ($coSocket) {/** @var self $coSocket */while (true) yield from $coSocket->on        Request (); } foreach (Gen ($coSocket) as $itEM) {}; }}cosocket::start (8000, function ($data) {$response = <<<reshttp/1.1 okcontent-type:text/plaincontent-le Ngth:12connection:closehello world!    RES; return $response;});
Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.