Yield 在 Ruby 跟 Rails 中

紅寶鐵軌客
來關注...
關注/停止關注:紅寶鐵軌客
關注有什麼好處?:當作者有新文章發佈時,「思書」就會自動通知您,讓您更容易與作者互動。
現在就加入《思書》,你就可以關注本作者了!
《思書》是一個每個人的寫作與論壇平台,特有的隱私管理,讓你寫作不再受限,討論更深入真實,而且免費。 趕快來試試!
還未加入《思書》? 現在就登錄! 已經加入《思書》── 登入
寫程式中、折磨中、享受中 ......
954   0  
·
2020/09/23
·
4分鐘


我是個寫 C 出身的工程師,現在開始學寫 Ruby & Rails,雖然 C 寫的很普普,但是還是有影響, ruby 中總是有些東西,對我來說,很難懂,ruby 的 yield 就是一個例子。

Ruby 的 Yield

Yield 在 Ruby 中是個 keyword,我花了至少一個小時,才總算搞清楚 yield 的來源以及其含義,我個人是這樣,如果不能理解,就是不懂,就算能用,也不過就是隻猴子學樣吧了,自己都難過,所以,特別把它記錄下來,不然很快就又忘了。

在英文中,Yield 這字是:「收成」、「獲得」⋯⋯ ,作為動詞,大家最熟悉的應該就是「讓路」,在美國,就是這個路標:

在台灣也有個相似的:

是的,在 Ruby 中,yield 就是「讓路」,但是要讓給誰能?讓我們來看這個 code:

# 參考來源:https://ithelp.ithome.com.tw/articles/10203982

autumn = ["September", "October", "November"]

def autumn_month (array, start = 1)
  counter = start
  array.each do |item|
    ## yield 來了 ##
    puts "#{yield counter} #{item}"
    counter=counter.next
  end
end

# 列出秋天的月份
autumn_month( autumn, 9 ) {|mth| "#{mth}. " }

9.  September
10.  October
11.  November

這個例子很有趣的清楚說明了 yield,我們先來看看這碼的流程:

  1. 先宣告一個 autumn array
  2. 再宣告 autumn_month() 的方法
  3. 執行 autumn_month() 方法

就這麼簡單,但是,請注意,在 #3 中,執行 autumn_month 方法的時候,後面跟了一個 ruby block {|mth| "#{mth}. " },這個是重點,這個 ruby block 也就是當碰到 yield 讓路時,會先執行(先行)的 ruby block! 還是不懂,沒關係,我也搞好久才懂,模擬一下就懂了:

  1. 執行 autumn_month() 方法,帶入參數 ( autumn, 9 ),後面跟著 {|mth| "#{mth}. " } 這個 ruby block。
  2. autumn_month() 方法中,counter 被設定為 9,然後準備印出(puts) autumn array 的內容
  3. 印出(puts)時,裡面有個 yield,因為碰到「讓路」,所以這段碼要先暫停,讓路給 {|mth| "#{mth}. " } ,這個已經在等的 ruby block。
  4. ruby 的 yield 不只會讓路,還可以傳值,所以:yield counter => yield(counter) => 傳出 counter 的值到等待中的 ruby block => 所以 mth = counter => ruby block 的內容變成{|counter| "#{counter}. " } => "#{counter}. "
  5. 禮讓先行完成後,就輪回到 puts "#{yield counter} #{item}",這時 yield counter 已經變成 "#{counter}. "了,所以 puts "#{yield counter} #{item}" => puts "#{counter}. #{item}",就這樣,魔術完成了!

從上面這個很有趣的例子中,我們可以看到,yield 是個很有趣的指令,它可以在呼叫方法時,將一段「程式碼」置入,所以,yield 一定要有相對應的  ruby block,如果我們在寫 yield 時,不確定有沒有相對應的  ruby block,就可以用 yield(value) if block_given?

在 ruby 中,類似 block 的還有 lambdas 跟 proc,三者之間有很大的相似,但是細節卻大不同,這也是 ruby 對我來說,另一個很難搞懂的地方,有時,從一個老 C programmer 來看,還會覺得超怪,說真的,我是有些排斥用 lambdas 跟 proc,心想,就不用它們,只用block 就可以打天下了,好像是有可能呢,不過,排斥總不是好事,大該寫了一些:

  • lambdas 跟 proc:都是 block 的 wrapper,讓我們把一個 block 變成一個變數:a object - an instance of the Proc class.
  • lambdas 跟 proc:都是 Proc class,但是內部的 return 大不同⋯⋯
  • lambda 會檢查 arguments 數目,proc 不會,
  • 我覺得下面這篇文章介紹 lambdas 跟 proc 很棒,清楚地說出重點:

Procs and Lambdas — Today I was refreshing my knowledge and learning something new about proc and lambda in Ruby and want...
DEV Community

Rails 的 Yield

在 Rails 的 layout 中,也有 yield,主要是在 app/views/layouts/application.html.erb 中,在這個 layout 中,就有一個<%= yield %>

那,Ruby 跟 Rails 中的這兩個  yield 是相同的嗎?是的,Rails 就是 Ruby 寫的,而 yield 是 Ruby 的 keyword,所以當然就是同一個, 只是在 Rails 中,是由 Controller 來在處理 View 時,它會先取用 Layout(預設是 app/views/layouts/application.html.erb),當碰到<%= yield %> 時、會將 Controller 相對應的 view 塞到其中,例如:index.html.erb,就這樣。

希望有幫助。


喜歡作者的文章嗎?馬上按「關注」,當作者發佈新文章時,思書™就會 email 通知您。

思書是公開的寫作平台,創新的多筆名寫作方式,能用不同的筆名探索不同的寫作內容,無限寫作創意,如果您喜歡寫作分享,一定要來試試! 《 加入思書》

思書™是自由寫作平台,本文為作者之個人意見。


文章資訊

本文摘自:
Categories:
Tags:
Total: 1012 words


分享這篇文章:
關於作者

很久以前就是個「寫程式的」,其實,什麼程式都不熟⋯⋯
就,這會一點點,那會一點點⋯⋯




參與討論!
現在就加入《思書》,馬上參與討論!
《思書》是一個每個人的寫作與論壇平台,特有的隱私管理,用筆名來區隔你討論內容,讓你的討論更深入,而且免費。 趕快來試試!
還未加入《思書》? 現在就登錄! 已經加入《思書》── 登入


×
登入
申請帳號

需要幫助
關於思書

暗黑模式?
字體大小
成人內容未過濾
更改語言版本?