摘要:這個關鍵字到底返回的是什么我們簡單看一下返回的是一個叫做中文名就是生成器的對象,而這個生成器是實現了接口至于接口,你們去手冊上搜索吧。
其實,我并不是因為迭代或者生成器或者研究PHP手冊才認識的yield,要不是協程,我到現在也不知道PHP中還有yield這么個鬼東西。人家這個東西是從PHP 5.5就開始引入了,官方名稱叫做生成器。你要說為什么5.5年代的東西,現在才拿出來。我還想問你喲,PHP 5.3就有了的namespace為毛到最近這幾年才開始正式投產。
那么,問題來了,這東西到底是有何用?
先來感受一個問題,給你100Kb的內存(是的,你沒有看錯,就是100Kb),然后讓你迭代輸出一個從1開始一直到10000的數組,步進為1。
愈先迭代數組,必先創造數組。
所以,腦門一拍,代碼一坨如下:
一頓操作猛如虎,運行一下成績1-5,你們感受一下:
528440bytes,約莫就是528Kb,幾乎是100Kb的五倍了,媽的這日子沒法過了。
畢竟你們也知道,最近內存價格確實貴,國家也在號召低碳節能減排,你多耗費5倍內存,就意味著多排放5倍的二氧化碳,就意味著要為多用的內存多花錢貢獻給棒子... ...你想想,那可是棒子。
人都是被逼出來的,于是yield可以來救場了,大概代碼如下,注意看操作:
運行一下,你們感受一下:
首先,我們觀察一下yield_range這個函數跟普通函數不一樣的地方,就是普通函數往往都是使用return來返回結果,而這個中則是yield。其次是普通函數中return只能返回一次,這個yield能返回好多次。
那么,我們來分析一波兒這個神奇的yield_range函數。這個yield關鍵字到底返回的是什么?我們簡單看一下:
yield返回的是一個叫做Generator(中文名就是生成器)的object對象,而這個生成器是實現了Iterator接口(至于Iterator接口,你們去PHP手冊上搜索吧)。所以,既然實現了Iterator接口(也正是因為如此,這個東西可以使用foreach進行迭代,明白了吧?),所以可以有如下代碼:
valid() ){ echo $generator->current().PHP_EOL; $generator->next(); }運行結果如下所示:
重點來了:這個yield_range函數似乎能夠記住它上一次運行到哪兒了,上一次運行的結果是什么,然后緊接著在下一次運行的時候繼續從上次終止的地方繼續開始。這不是普通的PHP函數可以做得到的!
我們知道,操作系統在調度進程的時候,會觸發一個叫做“進程上下文切換”的概念。比如CPU從進程A調度給進程B了,那么當再次從進程B調度給進程A的時候,當初進程A運行到哪兒了、臨時的數據結果是什么都是需要被還原的,不然,一切都要從頭,那就要出大問題了。而,這個yield關鍵字,似乎在用戶態(非系統內核級)就可以實現這個概念。所以說,用yield搞迭代,怕是真的很沒出息的一件事,它能做的太多。
緊接著,我們需要認識一個生成器對象的一個方法,叫做send,簡單看下下面這坨代碼:
send( $generator->current() * 10 );運行結果如圖所示:
send方法可以修改yield的返回值,但是,你也不能想當然,比如下面這坨代碼,你們以為運行結果是什么樣呢?
send( $generator->current() * 10 ); }本來以為運行結果是類似于這樣的:
然而,唯物主義告訴我們:
結果是打臉的,你們感受一下:
原因是什么呢?原因是當你在外部向yield發送send的時候,會自動觸發一次next,自己動手試下吧。
最近開了一個微信公眾號,所有文章都在這里(手賤弄成服務號了)
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/30996.html
摘要:粗暴地說上面的過程就算是協程的基本概念。多線程和多進程都是操作系統參與的調度,而協程是用戶自主實現的調度,協程的關鍵點實際上是用戶層實現自主調度,大概有翻身農奴把歌唱的意思。 首先是,這是我第一次把公眾號文章復制粘貼到sf.gg來。 其次是,很久很久之前,我挖了一個yield的一個坑,自己挖的坑自己填,不然遲早會把自己埋掉。 最后是,如果想看之前那個坑,請發送yield給文章末尾的公眾...
摘要:當運行到時,不會暫停,而是直接跳進函數執行函數內的代碼。由于函數中沒有,因此會一直執行完函數中的代碼,并返回至函數中執行后面的代碼。 本系列旨在通過對co,koa等庫源碼的研究,進而理解generator在異步編程中的重大作用(ps:所有代碼請在node --harmony或者iojs環境中運行) koa中間件的形式 相信用過koa的小伙伴一定很熟悉下面這段代碼 var app ...
摘要:把中的初始化方法改下,因為我們在運行一個的時候,我們要分析出他包含了哪些子協程,然后將子協程用一個堆棧保存。總結這下應該明白怎么實現協程了吧建議不要使用的來實現協程,推薦使用,已經支持了協程,并附帶了部分案例。 前言 相信大家都聽說過『協程』這個概念吧。 但是有些同學對這個概念似懂非懂,不知道怎么實現,怎么用,用在哪,甚至有些人認為yield就是協程! 我始終相信,如果你無法準確地表達...
閱讀 3380·2021-11-22 09:34
閱讀 650·2021-11-19 11:29
閱讀 1350·2019-08-30 15:43
閱讀 2232·2019-08-30 14:24
閱讀 1867·2019-08-29 17:31
閱讀 1223·2019-08-29 17:17
閱讀 2617·2019-08-29 15:38
閱讀 2729·2019-08-26 12:10