Apa yield
?
Kata yield
kunci mengembalikan data dari fungsi generator:
Jantung dari fungsi generator adalah kata kunci hasil. Dalam bentuknya yang paling sederhana, pernyataan hasil lebih terlihat seperti pernyataan pengembalian, kecuali bahwa alih-alih menghentikan eksekusi fungsi dan kembali, hasil sebaliknya memberikan nilai pada perulangan kode di atas generator dan menghentikan sementara eksekusi fungsi generator.
Apa itu fungsi generator?
Fungsi generator secara efektif merupakan cara yang lebih ringkas dan efisien untuk menulis Iterator . Ini memungkinkan Anda untuk mendefinisikan fungsi (Anda xrange
) yang akan menghitung dan mengembalikan nilai saat Anda mengulanginya :
foreach (xrange(1, 10) as $key => $value) {
echo "$key => $value", PHP_EOL;
}
Ini akan menghasilkan output sebagai berikut:
0 => 1
1 => 2
…
9 => 10
Anda juga dapat mengontrol $key
dalam foreach
dengan menggunakan
yield $someKey => $someValue;
Dalam fungsi generator, $someKey
adalah apa pun yang Anda inginkan muncul $key
dan $someValue
menjadi nilai $val
. Dalam contoh pertanyaan itu$i
.
Apa bedanya dengan fungsi normal?
Sekarang Anda mungkin bertanya-tanya mengapa kami tidak hanya menggunakan range
fungsi asli PHP untuk mencapai hasil itu. Dan Anda benar. Outputnya akan sama. Perbedaannya adalah bagaimana kita sampai di sana.
Ketika kita menggunakan range
PHP, akan melaksanakannya, membuat seluruh array angka dalam memori dan return
bahwa seluruh array ke foreach
lingkaran yang kemudian akan pergi lebih dari itu dan output nilai-nilai. Dengan kata lain, foreach
akan beroperasi pada array itu sendiri. The range
Fungsi dan foreach
hanya "bicara" sekali. Anggap saja seperti mendapatkan paket melalui pos. Si kurir akan menyerahkan paket itu kepada Anda dan pergi. Dan kemudian Anda membuka bungkus seluruh paket, mengambil apa pun yang ada di sana.
Ketika kita menggunakan fungsi generator, PHP akan masuk ke fungsi dan menjalankannya sampai memenuhi akhir atau yield
kata kunci. Ketika bertemu a yield
, ia kemudian akan mengembalikan nilai apa pun pada saat itu ke loop luar. Kemudian ia kembali ke fungsi generator dan berlanjut dari tempat ia menghasilkan. Karena Anda xrange
memegang for
loop, itu akan mengeksekusi dan menghasilkan sampai $max
tercapai. Anggap saja seperti foreach
dan generator bermain ping pong.
Mengapa saya membutuhkannya?
Jelas, generator dapat digunakan untuk bekerja di sekitar batas memori. Tergantung pada lingkungan Anda, melakukan range(1, 1000000)
wasiat akan mematikan skrip Anda sedangkan yang sama dengan generator hanya akan berfungsi dengan baik. Atau seperti yang Wikipedia katakan:
Karena generator menghitung nilai yang dihasilkan hanya berdasarkan permintaan, mereka berguna untuk mewakili urutan yang akan mahal atau tidak mungkin untuk dihitung sekaligus. Ini termasuk misalnya urutan tak terbatas dan aliran data langsung.
Generator juga seharusnya cukup cepat. Tetapi perlu diingat bahwa ketika kita berbicara tentang puasa, kita biasanya berbicara dalam jumlah yang sangat kecil. Jadi sebelum Anda sekarang lari dan mengubah semua kode Anda untuk menggunakan generator, lakukan benchmark untuk melihat di mana itu masuk akal.
Case Penggunaan lain untuk Generator adalah coroutine asinkron. Kata yield
kunci tidak hanya mengembalikan nilai tetapi juga menerimanya. Untuk detailnya, lihat dua posting blog bagus yang ditautkan di bawah ini.
Sejak kapan saya bisa menggunakan yield
?
Generator telah diperkenalkan di PHP 5.5 . Mencoba menggunakan yield
sebelum versi itu akan menghasilkan berbagai kesalahan parse, tergantung pada kode yang mengikuti kata kunci. Jadi, jika Anda mendapatkan kesalahan parse dari kode itu, perbarui PHP Anda.
Sumber dan bacaan lebih lanjut:
yeild
, katakanlah, solusi seperti ini: ideone.com/xgqevMreturn range(1,100000000)
danfor ($i=0; $i<100000000; $i++) yield $i
Fungsi ini menggunakan hasil:
hampir sama dengan yang ini tanpa:
Satu-satunya perbedaan adalah yang
a()
mengembalikan generator danb()
array sederhana. Anda dapat mengulangi keduanya.Juga, yang pertama tidak mengalokasikan array penuh dan karenanya kurang menuntut memori.
sumber
contoh sederhana
keluaran
contoh lanjutan
keluaran
sumber
yield
kata kunci berfungsi untuk definisi "generator" di PHP 5.5. Ok, lalu apa itu generator ?Dari php.net:
Dari tempat ini: generator = generator, fungsi lain (hanya fungsi sederhana) = fungsi.
Jadi, mereka berguna ketika:
Anda perlu melakukan hal-hal sederhana (atau hal-hal sederhana);
Generator benar-benar jauh lebih sederhana daripada mengimplementasikan antarmuka Iterator. Sebaliknya, sumber daya, bahwa generator kurang berfungsi. bandingkan mereka .
Anda perlu menghasilkan sejumlah besar data - menghemat memori;
sebenarnya untuk menghemat memori kita hanya bisa menghasilkan data yang dibutuhkan melalui fungsi untuk setiap iterasi loop, dan setelah iterasi menggunakan sampah. jadi di sini poin utama adalah - kode yang jelas dan mungkin kinerja. lihat apa yang lebih baik untuk kebutuhan Anda.
Anda perlu membuat urutan, yang tergantung pada nilai perantara;
ini meluas dari pemikiran sebelumnya. generator dapat membuat segalanya lebih mudah dibandingkan dengan fungsi. periksa contoh Fibonacci , dan cobalah membuat urutan tanpa generator. Generator juga dapat bekerja lebih cepat dalam kasus ini, setidaknya karena menyimpan nilai perantara dalam variabel lokal;
Anda perlu meningkatkan kinerja.
mereka dapat bekerja lebih cepat daripada berfungsi dalam beberapa kasus (lihat manfaat sebelumnya);
sumber
Dengan
yield
Anda dapat dengan mudah menggambarkan breakpoints antara banyak tugas dalam satu fungsi. Itu saja, tidak ada yang istimewa tentang itu.Jika task1 dan task2 sangat terkait, tetapi Anda perlu breakpoint di antara mereka untuk melakukan sesuatu yang lain:
maka generator adalah solusi terbaik, karena Anda tidak perlu membagi kode Anda menjadi banyak penutupan atau mencampurnya dengan kode lain, atau menggunakan panggilan balik, dll ... Anda hanya
yield
perlu menambahkan breakpoint, dan Anda dapat melanjutkan dari itu breakpoint jika Anda siap.Tambahkan breakpoint tanpa generator:
Tambahkan breakpoint dengan generator
Catatan: Mudah membuat kesalahan dengan generator, jadi selalu tulis unit test sebelum Anda menerapkannya! note2: Menggunakan generator dalam loop tak terbatas seperti menulis penutupan yang memiliki panjang tak terbatas ...
sumber
Tidak ada jawaban di atas yang menunjukkan contoh nyata menggunakan array besar yang dihuni oleh anggota non-numerik. Berikut adalah contoh menggunakan array yang dihasilkan oleh
explode()
pada file .txt besar (262MB dalam kasus penggunaan saya):Outputnya adalah:
Sekarang bandingkan dengan skrip yang serupa, menggunakan
yield
kata kunci:Output untuk skrip ini adalah:
Jelas penghematan penggunaan memori sangat besar (emMemoryUsage -----> ~ 270,5 MB pada contoh pertama, ~ 450B pada contoh kedua).
sumber
Aspek yang menarik, yang layak untuk dibahas di sini, adalah menghasilkan dengan referensi . Setiap kali kita perlu mengubah parameter sedemikian rupa sehingga tercermin di luar fungsi, kita harus melewatkan parameter ini dengan referensi. Untuk menerapkan ini pada generator, kami cukup menambahkan ampersand
&
ke nama generator dan variabel yang digunakan dalam iterasi:Contoh di atas menunjukkan bagaimana mengubah nilai yang
foreach
diulang dalam loop mengubah$from
variabel dalam generator. Hal ini karena$from
ini dihasilkan dengan mengacu karena ampersand sebelum nama generator. Karena itu,$value
variabel dalamforeach
loop adalah referensi ke$from
variabel dalam fungsi generator.sumber
Kode di bawah ini mengilustrasikan bagaimana menggunakan generator mengembalikan hasil sebelum selesai, tidak seperti pendekatan non generator tradisional yang mengembalikan array lengkap setelah iterasi penuh. Dengan generator di bawah ini, nilai-nilai dikembalikan ketika siap, tidak perlu menunggu array diisi sepenuhnya:
sumber