Ruby面試精選30題 - Day19 Ruby裡的yield

在[第11天]時,我們曾比較block, proc與lamdba方法,而yield的實用場景是在method裡讓路給block區塊執行程式的意思。


重點摘要:


Ruby經典面試題目 #19

  • 描述Ruby裡的yield用法?
    What is yield statement in Ruby?`

yield + block

現在來寫一個IronmanDairy類別,用以產生新物件day19,接著利用get_topic方法透過yield傳遞參數topicblock

class IronmanDairy
  def initialize(topic)
       @topic = topic
  end

  def get_topic
      yield( @topic )
  end
end

day19 = IronmanDairy.new("Yield")

#invoking the method passing a block
day19.get_topic do |topic|
    puts "We are going to talk about #{topic} today!"
end

從[第12天]文章比較實體變數類別實體變數的整理,我們可以了解這裡的@topic實體變數

Output:

tingdeMacBook-Air:Ironman tingtinghsu$ ruby yield.rb
We are going to talk about Yield today!

今天的Opening出現啦!

yield + block: 字串方法

Block裡面還可以玩許多有趣的String字串方法。例如,我們想要把大寫字母轉小寫、小寫字母轉大寫:

topic_swapcase = "" #set an empty string
day19.get_topic do |topic|
  topic_swapcase = topic.swapcase
end

puts "We are going to talk about #{topic_swapcase} today!"

Output:

tingdeMacBook-Air:Ironman tingtinghsu$ ruby yield_swapcase.rb
We are going to talk about yIELD today!

yield + block: 陣列方法

在寫鐵人賽的我目前所在城市是Sydney,南半球的現在正是花朵盛開、氣候美妙的春天~我想用array表達曼妙愉快的心情:

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

我想要將春天的三個月份條列印出在螢幕上,可以寫成print_list方法:

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

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

spring_month( spring ) { |mth| mth }

當我們呼叫spring_month方法時,可傳入試先設定好的spring陣列,再用block方式跑完每一個陣列裡的值。(記得{}do...end都是block的語法唷!)

Output:

1 September
2 October
3 November

現在,我想月份前面加上對應的阿拉伯數字,例如September是9,October是10…。該如何是好呢?

這時候yield就派上用場啦!

我們把yield放在計數器counter前,當作設定格式的一種方式

puts "#{yield counter} #{item}"

yield會去呼叫以下的block

spring_month( spring, 9 ) do |mth|
  "#{mth}. "
end

為了要讓第一個itemSeptember從9開始,我們呼叫spring_month方法時,也要代入參數9,讓spring_month方法幫助我們從9開始往上遞增。並且利用"#{mth}. "設定格式。

整體結構如下:

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

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

#list all the months in Spring
spring_month( spring, 9 ) do |mth|
  "#{mth}. "
end

output:

9.  September
10.  October
11.  November

以上的例子顯示,方法裡面可以結合陣列,在block裡面透過array#eachmethod對陣列裡的元素做出各種有趣的功能,再結合yield之後,是不是產生很大的威力呢?:)

Ref: