2015-10-06 15 views
5

Dưới đây là một máy phát điện đơn giản Javascript (thông qua: http://blog.carbonfive.com/2013/12/01/hanging-up-on-callbacks-generators-in-ecmascript-6/)Làm thế nào để sử dụng máy phát điện PHP mà không cần cho phép?

function* powGenerator() { 
    var result = Math.pow(yield "a", yield "b"); 
    return result; 
} 

var g = powGenerator(); 
console.log(g.next().value); // "a", from the first yield 
console.log(g.next(10).value); // "b", from the second 
console.log(g.next(2).value); // 100, the result 

Tôi đang cố gắng để mô hình một cái gì đó tương tự với PHP nhưng đó là một chút đau đầu.

<?php 
function powGenerator() { 
    return pow((yield 'a'), (yield 'b')); 
} 

Trước khi tôi đi xa hơn, tôi nhận được lỗi này trong PHP

Fatal error: Generators cannot return values using "return"

Ok, vì vậy có lẽ tôi sẽ chỉ sử dụng năng suất khác để có được giá trị cuối cùng ra? ...

<?php 
function powGenerator() { 
    yield pow((yield 'a'), (yield 'b')); 
} 

$g = powGenerator(); //=> Generator {#180} 
echo $g->send(10); //=> "b" 
echo $g->send(2); //=> 100 

OK, vì vậy tôi có giá trị của tôi trở lại, nhưng có hai vấn đề lớn ở đây

  1. đâu tôi "a" đi đâu? — Lưu ý trong ví dụ JS, tôi có thể truy cập vào cả các số "a""b" mang lại giá trị cũng như kết quả cuối cùng 100.

  2. Máy phát điện vẫn chưa hoàn tất! — tôi phải gọi send một thời gian thêm để hoàn thành máy phát điện

    $g->valid(); //=> true 
    $g->send('?'); //=> null 
    $g->valid(); //=> false 
    

Từ PHP Generator::send

public mixed Generator::send (mixed $value)

Sends the given value to the generator as the result of the current yield expression and resumes execution of the generator.

If the generator is not at a yield expression when this method is called, it will first be let to advance to the first yield expression before sending the value. As such it is not necessary to "prime" PHP generators with a Generator::next() call (like it is done in Python).

Nhấn mạnh vào "Như vậy nó không phải là cần thiết để "thủ" Máy phát PHP với Generator::next() ". OK, nhưng điều đó thực sự có ý nghĩa gì? Tôi không phải "đánh lừa" nó như ví dụ JavaScript, nhưng giá trị mang lại đầu tiên cũng bị nuốt chửng.

Bất cứ ai có thể giải thích cách bạn muốn bước qua máy phát điện mà không cần sử dụng foreach?

Trả lời

8

Giá trị mang lại đầu tiên không được nuốt, bạn chỉ không bao giờ nhìn vào nó.

$g = powGenerator(); 
echo $g->current(); //a 

Bạn đang sau đó hai lần gửi trong các giá trị và khôi phục thực hiện, $g->valid()true sau này vì bạn đã không tiếp tục sau khi ba yield - máy phát điện là không đầy đủ và có thể có nhiều hơn cho nó để làm . Xem xét:

function powGenerator() { 
    yield pow((yield 'a'), (yield 'b')); 
    echo "Okay, finishing here now!\n"; 
} 

$g = powGenerator(); 
echo $g->current(), "\n"; //a 
echo $g->send(10), "\n"; //b 
echo $g->send(2), "\n"; //100 
$g->next();    // Resumes execution of the generator, 
          // which prints its own message and completes. 
var_dump($g->valid()); //false 

điều này sẽ đầu ra:

a 
b 
100 
Okay, finishing here now! 
bool(false) 

Bây giờ trong PHP 7 bạn thểreturn from a generator.

function powGenerator() { 
    return pow((yield 'a'), (yield 'b')); 
    echo "This will never print."; 
} 

$g = powGenerator(); 
echo $g->current(), "\n"; //a 
echo $g->send(10), "\n"; //b 
echo $g->send(2), "\n"; // Prints just the newline, you're moving on 
          // to a return which you must get explicitly. 
var_dump($g->valid()); // Generator complete, you're free to get the return. 
echo $g->getReturn(), "\n"; 

Những kết quả đầu ra:

a 
b 

bool(false) 
100 

Đối với bước qua chúng mà không có một foreach - Generator thực hiện Iterator, vì vậy nó có phương pháp thích hợp để đối xử với nó như vậy: current, key, next, rewindvalid. Với báo trước rằng rewind sẽ ném một ngoại lệ nếu bạn gọi nó trên máy phát điện đã bắt đầu.

Một ví dụ mà thực hiện điều này và cũng chứng tỏ PHP 7 mới generator delegation:

function letterGenerator() { 
    yield from range('a', 'z'); 
} 

$g = letterGenerator(); 

while ($g->valid()) { 
    echo $g->current(); 
    $g->next(); 
} 

Output:

abcdefghijklmnopqrstuvwxyz 
+0

Ok, việc sử dụng của 'current' và 'next' ít nhất là phù hợp với hiện tại triển khai mảng, nhưng không thể xác định phần cuối của trình tạo là thực sự câm, imo. Lệnh 'next()' bổ sung để chấm dứt trình tạo ra làm cho việc xây dựng chương trình riêng của bạn xung quanh vấn đề này thực sự khó khăn. Các tài liệu làm cho nó âm thanh như máy phát điện PHP là tuyệt vời không phải "thủ" chúng như Python nào. Họ chỉ kết thúc với một API clunky anyway. PHP cổ điển. – naomik

+0

'return' trong PHP 7 không giải quyết được mối quan tâm của tôi nhưng nó không thực sự giúp ích gì cho tôi. PHP 7 có lẽ sẽ không ổn định trong một thời gian dài. Tôi không thấy các máy phát điện hiện tại có thể quá ngắn ngủi như thế nào. Có vẻ như chỉ thực tế là sử dụng chúng với 'foreach'. – naomik

+0

Dù sao, cảm ơn sự giúp đỡ của bạn. Tôi sẽ chỉ gắn bó với một phong cách lập trình hoàn toàn bắt buộc. Đó là khá nhiều tất cả PHP đáng tin cậy dành cho tôi, anyway. Không có gì mới trong PHP dev và. – naomik

Các vấn đề liên quan