溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

Ruby的block怎么使用

發(fā)布時間:2022-01-14 14:46:17 來源:億速云 閱讀:147 作者:iii 欄目:大數(shù)據(jù)

這篇文章主要介紹“Ruby的block怎么使用”的相關(guān)知識,小編通過實際案例向大家展示操作過程,操作方法簡單快捷,實用性強(qiáng),希望這篇“Ruby的block怎么使用”文章能幫助大家解決問題。

1. 塊(block)是一段「半自由」的代碼,其形在方法外,而魂歸方法里。

塊(block)代碼由{...}或do...end界定而成。

   [1, 2, 3].each{|i| i + 1}

塊(block)代碼不能被單獨調(diào)用,只能依附于方法,所以稱其為魂歸方法里。

2. 塊(block)魂歸自身,獲得完全自由的唯一方法就是,讓其對象化。

魂歸自身,意味著,它完全自由了,可被單獨調(diào)用了

 
  Proc.new{ puts "hello"}
  proc{ puts  "hello"}
  proc{|msg| puts "hello #{msg}"}
  
  lambda{puts "hello"}
  lambda{|msg = "world!"| puts "hello #{msg}"}
  
  ->{puts "hello"}
  ->(msg="world!"){puts "hello #{msg}"}

以上就是Ruby提供的所有塊(block)對象, 都是Proc類的對象。

3. 用不用塊(block),是你的自由,但是方法天生就是塊的魂歸之地。

Ruby中任何一個方法你都可以傳遞一個塊。

 
   def test;end
   test{ puts i}

上面的代碼,甚至都不會報錯,因為在test方法內(nèi)部沒有去使用這個塊(block)。
顯然,你已經(jīng)不能把塊(block)當(dāng)成那個常規(guī)的方法參數(shù)了,雖然它的行為像參數(shù)。

4. 如何使用塊(block), 直接決定了它的命運!

A. 在方法內(nèi)部使用yield關(guān)鍵字去引block的“魂”。

 
  def test
    yield
  end
  test{puts "hello test!"}
  
  def test(x)
    yield(x)
  end
  test('world!'){|x| puts "hello #{x}"}

yield關(guān)鍵字不僅可以掛載塊(block)代碼,而且可以給塊傳遞參數(shù)。

B. 魂歸自身式:使用「&」讓一個傳遞給方法的塊(block)魂歸自身。

 
  def test(&block)
    block.call("world")
  end
  
  test{|msg| puts "hello #{msg}"}

但是在方法內(nèi)部,也可以使用「&」給塊對象(Proc對象)抽魂:

 
  def test(&block)
    inner_test(&block)
  end
  
  def inner_test
    yield("haha!")
  end
  
  test{|msg| puts "hello #{msg}"}

方法真陰險!有木有?

5. 爭風(fēng)吃醋的block兄弟。

{...}和do ... end,雖然是塊(block)孿生兄弟,但是也有個誰先誰后的,使用的時候注意,否則它們會讓你知道誰才是老大!

  def test(block)
    block.call
  end
  
  test lambda do 
     puts "hello"
  end

你給test方法傳遞了一個自由的Proc對象,但是稍有不同,這個Proc對象是用do...end,但是,你執(zhí)行代碼后會發(fā)現(xiàn),這段代碼會拋出異常:ArgumentError: tried to create Proc object without a block

 
  test( lambda do
          puts "hello"
        end
      )

必須要這么修改才可以正常執(zhí)行?;蛘呤褂茫?/p>

 
  test lambda{puts "hello"}

這樣也可以正常工作。

可以看得出來, do...end 不如 {...}優(yōu)先級高,{...}親近離它最近的那個lambda, 而do...end卻親近最遠(yuǎn)的那個test。
感覺do...end有點混,所以類似于這種把Proc對象傳遞給方法的時候,一定要注意用括號,或者用{...}

不過由于這個拋出的異常,ArgumentError: tried to create Proc object without a block,我們倒是可以得到一個隱式傳遞block給方法的寫法:

 
  def test
    proc_obj = Proc.new
    proc.call
  end
  
  test{puts "hello"}

6. 塊(block)也有自尊。

 
  def test
    x = 1
    yield(x)
  end
  
  x = 2
  test{ puts x }

塊(block)有個超能力,穿透作用域。 上面例子里,塊(block)并沒有使用test方法里的變量x=1, 而是把塊(block)作用域外的變量x=2抓在了手里。

7. 對于塊(block)的自尊, 方法向你(Rubyist)求助!

 
  def test
    x = 1
    yield(x)
  end
  
  x = 2
  test{ |x| puts x }

你(Rubyist)往塊(block)里插入了個參數(shù),頓時霸氣側(cè)漏。方法對你感激不盡,你驕傲的昂起了頭 。。。

8. 塊(block)還是不服!向你(Rubyist)求助,恢復(fù)其自由身!

你(Rubyist)幫塊(block)實現(xiàn)了自由身,使用lambda對象化了塊

 
  def test
    x = 1
    lambda{ puts x}
  end
  
  lambda_proc_obj = test
  lambda_proc_obj.call

這下塊對象(lambda_proc_obj)出氣了, lambda_proc_obj想啥時候調(diào)用就啥時候調(diào)用(lambda_proc_obj.call)。
lambda_proc_obj心想:「哥把你這方法打包了,掌握著你的數(shù)據(jù)(x=1),再也不看你臉色了?!?br/>噢, 原來如此, 讓塊(block)完全自由以后變成Proc對象, 它就有閉包的超能力了,好可怕!

9. 兩種塊對象(Proc對象), 兩種命運,可悲可嘆!。

A. 被方法所奴役 : 必須要執(zhí)行的代碼段

 
  proc_obj = Proc.new{ return "from proc return"}
  # proc_obj = proc {return  "from proc return"}
  
  def test(block)
    msg = block.call
    puts "hello! #{msg}!"
  end
  
  test(proc_obj)

這段代碼會拋出LocalJumpError異常, 用Proc.new和proc{}定義的Proc對象,是不能使用return的。
這就意味著,這個Proc對象,一旦被call,就必須要執(zhí)行完。

注意這里test方法傳遞一個本身就是Porc的對象,并沒有使用&。

再看看這段代碼,看看這倆Proc對象對arity的關(guān)心程度(是否檢查塊對象的參數(shù)個數(shù))

 
def call_with_too_many_args(closure)
  begin
      puts "closure arity: #{closure.arity}"
      closure.call(1,2,3,4,5,6)
      puts "Too many args worked"
  rescue Exception => e
      puts "Too many args threw exception #{e.class}: #{e}"
  endend
 def two_arg_method(x,y)endputs "Proc.new:"; call_with_too_many_args(Proc.new {|x,y|})puts "proc:"    ; call_with_too_many_args(proc {|x,y|})

這段代碼可以看出來, Proc.new或proc{}定義的proc對象,完全是方法的奴隸??!
工作必須執(zhí)行完不說(無法return),參數(shù)個數(shù)給傳多少都不能發(fā)出半點怨言??!僵尸? 奴隸?

B. 一段匿名的方法體

 
  lambda_proc_obj = lambda{return "return from lambda proc"}
  # lambda_proc_obj = ->{return "return from lambda proc"}

  def test(block)
    msg = block.call
    puts "hello! #{msg}!"
  end
  
  test(lambda_proc_obj)

可以看得出來,lambda proc對象是可以正常返回的.

 
  puts "lambda:"  ; call_with_too_many_args(lambda {|x,y|})

這段代碼,就明白了,lambda{}方式創(chuàng)建的Proc對象,才是真正的自由塊對象??!
工作想休息的時候就休息(可以return), 給傳的參數(shù)多了,也可以發(fā)出怨言。
自由的空氣,真好。

看來lambda proc和Method對象,有點類似:

 
  puts "Method:"  ; call_with_too_many_args(method(:two_arg_method))

10. 你(Rubyist)有四種方式對可憐的塊對象呼來喝去。

 
  lm_proc_obj = lambda{puts  "hello world!"}
  
  lm_proc_obj.call
  lm_proc_obj.() #無參數(shù)必須給一個空的括號
  lm_proc_obj[] #無參數(shù)必須給一個空的中括號
  
  lm_proc_obj = lambda{|msg| puts  "hello #{msg}!"}
  
  lm_proc_obj.call("world")
  lm_proc_obj.("world") 
  lm_proc_obj["world"]
  lm_proc_obj === "world"

看到第四種方式,你應(yīng)該想到,你可以在case語句里使用proc對象了吧?

 
  def response_code?(code)
    ->(response) { response.code == code }
  end

  case response
  when response_code?(200) then 'OK'
  when response_code?(404) then 'Not found'
  else 'Unknown code'
  end

關(guān)于“Ruby的block怎么使用”的內(nèi)容就介紹到這里了,感謝大家的閱讀。如果想了解更多行業(yè)相關(guān)的知識,可以關(guān)注億速云行業(yè)資訊頻道,小編每天都會為大家更新不同的知識點。

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI