回答
這本書「Programming Ruby」有一個很好的explanation of blocks and using them。
在1.9+,傳遞到塊的參數列表變得更加複雜,從而允許定義局部變量:
do |a,b;c,d|
some_stuff
end
;c,d
聲明塊內的兩個新的局部變量,不從接收值稱爲例程的yield
聲明。 Ruby 1.9+保證,如果變量存在於塊之外,那麼它們將不會被塊內的同名變量踩踏。這是新的行爲; 1.8會踩踏他們。
def blah
yield 1,2,3,4
end
c = 'foo'
d = 'bar'
blah { |a, *b; c,d|
c = 'hello'
d = 'world'
puts "a: #{a}", "b: #{b.join(',')}", "c: #{c}", "d: #{d}"
}
puts c, d
# >> a: 1
# >> b: 2,3,4
# >> c: hello
# >> d: world
# >> foo
# >> bar
另外還有「圖示」運營商*
,它在參數列表的工作原理:
do |a,*b|
some_stuff
end
將會分配第一多值的,以「一」,和所有其餘的將被捕獲在「b」中將被視爲一個數組。該*
可能是在a
變量:
do |*a,b|
some_stuff
end
將捕獲的變量全部通過除了最後一個,這將被傳遞給b
。而且,與前兩次:
do |a,*b,c|
some_stuff
end
將指定第一個值a
,最後的價值c
和所有/任何中間值b
。
我認爲這是非常強大和光滑。
例如:
def blah
yield 1,2,3,4
end
blah { |a, *b| puts "a: #{a}", "b: #{b.join(',')}" }
# >> a: 1
# >> b: 2,3,4
blah { |*a, b| puts "a: #{a.join(',')}", "b: #{b}" }
# >> a: 1,2,3
# >> b: 4
blah { |a, *b, c| puts "a: #{a}", "b: #{b.join(',')}", "c: #{c}" }
# >> a: 1
# >> b: 2,3
# >> c: 4
從Why's (poignant) guide to ruby:
由大括號包圍的任何代碼是 塊。
2.times { print "Yes, I've used chunky bacon in my examples, but never again!" }
就是一個例子。使用塊,您可以將一組 指令組合在一起,以便它們可以在您的程序中傳遞。 大括號給出了 螃蟹夾的外觀,它們已經抓取了 代碼並將它們放在一起。當 你看到這兩個鉗子,記得 ,其中的代碼已被按下 成一個單位。這就像 一個那些小的Hello Kitty盒他們 在一個與 微小的鉛筆和微觀紙, 全部塞進可以在你的手掌被隱藏 隱蔽固定 操作閃閃發光的 透明的情況下塞滿商場出售。除了塊不要 需要這麼多眯眼。 花括號也可以交易爲 單詞做和結束,這是很好的,如果 您的塊是長於一行。
loop do
print "Much better."
print "Ah. More space!"
print "My back was killin' me in those crab pincers."
end
塊參數是一個 組由管包圍 字符和由逗號分隔的變量。
|x|, |x,y|, and |up, down, all_around| are examples.
塊參數被在塊的開始時使用 。
{ |x,y| x + y }
在上述示例中,| X,Y |是爭論。在參數後面,我們 有一些代碼。表達式x + y將兩個參數一起添加。我想 喜歡想象管道字符 代表隧道。他們給出 滑槽的外觀,即 變量滑落。 (一個x去 下來撒鷹,而y整齊 越過她的腿。)該滑道作爲 與塊之間的通道周圍的 世界。變量 通過這個料槽(或隧道) 到塊通過。
「任何由花括號包圍的代碼都是塊」除非它是一個**哈希**。 – Meltemi 2011-05-09 19:53:04
塊是一種在Ruby中對代碼進行分組的方法。有兩種寫塊的方法。一個使用do..end語句,另一個使用大括號括住代碼:{}。塊被認爲是Ruby編程語言中的對象,默認情況下所有函數都接受一個隱式塊參數。
下面是做同樣的事情塊的兩個例子:
2.times { puts 'hi' } 2.times do puts 'hi' end
塊可以接收豎條內的逗號分隔的參數列表||。例如:
[1,2].map{ |n| n+2 } # [3, 4]
塊(在紅寶石1.9.2)可以明確地有局部變量:
x = 'hello' 2.times do |;x| x = 'world' puts x end => world => world
局部變量可以用參數組合:
[1,2].map{ |n;x| n+2 }
所有功能都可以接受默認塊參數:
def twice yield yield end twice { puts 'hello' } => hello => hello
do..end和{}塊之間有什麼區別?按照慣例{}塊在一條線上並且做..結束塊跨越多行,因爲它們每個都更容易閱讀。主要的區別有雖與優先做的事情:
array = [1,2] puts array.map{ |n| n*10 } # puts (array.map{ |n| n*10 }) => 10 => 20 puts array.map do |n| n*10 end # (puts array.map) do |n| n*10 end => <Enumerator:0x00000100862670>
塊是與一些煩人的限制匿名一流的程序輕量級文字。他們的工作方式相同在Ruby中,因爲他們在幾乎所有其他的編程語言工作,模提到前面所限制,它們分別是:
- 塊只能出現在參數列表
- 最多一個塊可以出現在參數列表(它必須是最後一個參數)
我提供了從this answer我自己的解釋,略作修改:
「塊」在Ruby中是不一樣的,一般編程術語「代碼塊「o r「代碼塊」。
假裝下列(無效)Ruby代碼實際工作了一會兒:
def add10(n)
puts "#{n} + 10 = #{n+10}"
end
def do_something_with_digits(method)
1.upto(9) do |i|
method(i)
end
end
do_something_with_digits(add10)
#=> "1 + 10 = 11"
#=> "2 + 10 = 12"
...
#=> "9 + 10 = 19"
雖然該代碼是無效的,其意圖傳遞一些代碼的方法和具有方法運行的代碼,是Ruby可以通過各種方式實現。其中一種方式是「塊」。
Ruby中的塊非常非常像一個方法:它可以接受一些參數併爲這些參數運行代碼。無論何時您看到foo{ |x,y,z| ... }
或foo do |x,y,z| ... end
,這些塊都需要三個參數並在其上運行...
。 (你甚至可能看到upto
上述方法被傳遞塊。)
因爲塊是的Ruby語法的一個特殊部分,每一個方法允許傳遞一個塊。方法使用該塊取決於方法。例如:
def say_hi(name)
puts "Hi, #{name}!"
end
say_hi("Mom") do
puts "YOU SUCK!"
end
#=> Hi, Mom!
的方法,上述傳遞塊是準備發出損傷,但由於該方法從未調用塊,當打印僅好的消息。下面是我們如何調用該塊從一個方法:
def say_hi(name)
puts "Hi, #{name}!"
if block_given?
yield(name)
end
end
say_hi("Mridang") do |str|
puts "Your name has #{str.length} letters."
end
#=> Hi, Mridang!
#=> Your name has 7 letters.
我們使用block_given?
看到一塊是否沿着或者不通過。在這種情況下,我們將一個參數傳回給塊;這取決於你的方法來決定要傳遞給塊的內容。例如:
def say_hi(name)
puts "Hi, #{name}!"
yield(name, name.reverse) if block_given?
end
say_hi("Mridang"){ |str1, str2| puts "Is your name #{str1} or #{str2}?" }
#=> Hi, Mridang!
#=> Is your name Mridang or gnadirM?
這只是(你想支持和良好的一個,和一個)對於某些類通過剛剛創建的塊實例的約定。
這不是一個詳盡的答案,因爲它不包括捕獲塊作爲參數,它們如何處理arity,在塊參數中不噴濺等,而是打算用作Blocks-Are-Lambdas的介紹。
Ruby塊是一種創建Proc
objects的方法,它代表其他代碼可以使用的代碼。Proc對象是大括號{}
(或do...end
多行塊的短語,其優先級低於大括號)之間的指令,可以選擇帶參數和返回值(例如{|x,y| x+y}
)。特效是first-class objects,並且可以明確地被構造或隱式地獲得作爲方法的僞參數:
施工作爲Proc對象(或使用
lambda
關鍵字):add1 = Proc.new {|x| x+1} # Returns its argument plus one. add1.call(1) # => 2
傳遞爲方法僞參數,明確地使用
&
最後一個參數語法糖操作符或隱式使用block_given?
/yield
對:def twice_do(&proc) # "proc" is the block given to a call of this method. 2.times { proc.call() } if proc end twice_do { puts "OK" } # Prints "OK" twice on separate lines. def thrice_do() # if a block is given it can be called with "yield". 3.times { yield } if block_given? end thrice_do { puts "OK" } # Prints "OK" thrice on separate lines.
第二種形式通常用於Visitor patterns;數據可以作爲參數傳遞給特殊塊參數,即call
或yield
方法。
任何人來對這個問題從C#的背景(或其他LANGS真的),這可能幫助:
紅寶石塊是像lambda表達式和C#匿名方法。它們是C#調用代理(和Ruby調用Proc)的東西,也就是說它們本質上是可以作爲值傳遞的函數。在Ruby和C#中,它們也可以表現爲關閉。
紅寶石:{ |x| x + 1 }
C#:x => x + 1
紅寶石:{ |name| puts "Hello there #{name}" }
C#:name => { Console.WriteLine("Hello there {0}", name); }
C#和紅寶石提供替代的方式來寫上面的例子。
紅寶石:
do |name|
puts "Hello there #{name}"
end
C#:
delegate(string name)
{
Console.WriteLine("Hello there {0}", name);
}
在Ruby和C#,多個語句是允許的,在Ruby中,所述第二語法以上是必需的這一點。
這些概念在許多受函數編程背後思想影響的其他語言中都可用。
- 1. 解釋「2.11351E + 16」的最佳方式
- 2. .each_with_object ruby解釋?
- 3. 最佳Python模塊的HTML解析
- 4. Django的{%塊%}解釋
- 5. iPhone塊解釋
- 6. 在ruby中釋放對象的最佳做法
- 7. Ruby解釋器的名字
- 8. ipython像ruby的解釋器
- 9. 的Ruby語法解釋
- 10. Ruby的最佳YouTube寶石?
- 11. 請解釋此javascript函數定義及其最佳用法(模塊模式)
- 12. Cidr塊AWS解釋
- 13. 擴展Ruby與C模塊返回奇怪的值,請解釋...
- 14. 瞭解ruby模塊
- 15. yii中的模塊 - 解釋
- 16. Ruby如何解釋$(foo)
- 17. Python和Ruby解釋器
- 18. params [key] .instance_eval Ruby解釋?
- 19. Ruby解釋變量is_a?
- 20. 在Ruby中解釋哈希
- 21. 使用Ruby解釋XML(Sinatra)
- 22. 瞭解Ruby/Rails中的塊
- 23. Ruby連接最佳實踐
- 24. 「通用」一詞的最佳解釋是什麼?
- 25. C#解釋器執行的最佳途徑
- 26. 什麼是解釋「位串」的最佳方式
- 27. forgiving命令解釋器的最佳Java庫(012)
- 28. 在Ruby中解析網頁的最佳方式是什麼?
- 29. Ruby:什麼是解析XML的最佳方式?
- 30. 什麼是Ruby中大緩存的最佳解決方案?
您是否在尋找關於塊的概念的介紹,或者對其進行詳盡的參考? – Phrogz 2011-02-06 19:21:55
或者你是否只是通過問你不需要答案,不打算接受,甚至不打算參加討論的問題來回答問題?我們會看看你是否回覆。 – Phrogz 2011-02-06 19:22:17
這是一個有用的線程:http://www.reactive.io/tips/2008/12/21/understanding-ruby-blocks-procs-and-lambdas/ – Lucio 2015-09-21 23:18:11