2014-03-13 35 views
1
3.times {puts "Hello"} 

輸出:作爲紅寶石方法的參數塊是一個謎?

Hello
Hello
Hello

我們把它理解爲timesInteger類中的函數,接受block作爲參數。

我試圖挖掘並發現它並不那麼簡單。

如果它是times是在一個方法調用的函數,並且括號中的情況下是可選的我試圖用它來驗證:

3.times({puts "Hello"}) 

扔明顯的錯誤:

SyntaxError: (irb):3: syntax error, unexpected tSTRING_BEG, expecting keyword_do or '{' or '(' 3.times({puts "Hello"}) ^ (irb):3: syntax error, unexpected '}', expecting end-of-input 3.times({puts "Hello"}) ^ from /home/ashish/.rvm/rubies/ruby-2.0.0-p353/bin/irb:12:in `'

進一步調查:

a = 3.times 
puts a.class 

輸出Enumerator th意味着3X是一個Enumerator類對象。

有人可以用這背後的確切概念來解釋整個事情嗎?

+3

塊「參數」是句法糖;如果你在parens裏面做,它會試圖解析爲一個散列。 –

+0

如果我們在這種情況下嘗試「3.times(do puts」hello「end)」,那麼爲什麼它會試圖將其解析爲散列值? –

+2

'3.times(&proc {puts「Hello」})' –

回答

3

正如Sawa所說,塊不是對象,因此不會作爲參數傳遞。在Ruby中塊是一件特別的事情。它們有特殊的語法(它只允許我們傳遞一個方法到一個方法)和一個專門調用它們的特殊關鍵字。下面是times在Ruby中的範例:

def times 
    if block_given? 
    i = 0 
    while i < self 
     yield i 
     i += 1 
    end 
    # times returns the number that was executing times, 
    # so we need to return self here 
    self 
    else 
    enum_for :times 
    # ^^ This is where the Enumerator comes from if 
    # you don't pass a block. 
    end 
end 

block_given?方法測試是否存在與當前方法相關的塊,和yield關鍵字調用塊。

2

塊不是一個參數,它甚至不是一個對象。把它放在括號裏是沒有意義的,因爲它不是一個對象。

def times(&block) 
    block.call(...) 
end 

調用它,你需要一個可以轉換爲一個對象:

+0

它是一個參數,只是一個位置和語法糖,它允許你省略'&'和'proc'。 –

+0

你的言論是矛盾的。 '一個塊不是一個參數'並且'取一個塊的時間' 考慮一個方法只會把某些事情當作參數。 –

+0

@VictorMoroz根據你的邏輯,女人是一個男人,可以成爲一個沒有MtoF性別再分配操作的女人。 – sawa

0

是座位置(通常,如果定義的最後一個)與傳遞值的特殊規則的說法,times可以作爲被定義Proc類的一個實例,你應該用&加前綴:

3.times(&Proc.new { puts "Hello" }) 

調用times

3.times { puts "Hello" } 

只是上述形式的語法糖。

更新:我不得不承認,它不是一個語法糖,塊是速度更快,只是增加&block參數times確實慢下來的東西,即使它永遠不會被調用。

+3

這不完全是句法糖。 「3.times {puts」Hello「}實際上比」3.times(&Proc.new {puts「Hello」})簡單得多。兩者都具有相同的最終效果,但是像這樣做的包裝和解開包裝和展開過程涉及更多的工作。此外,說「塊是一個位置的爭論」有點欺騙性。從語言的角度來看,如果您選擇將其包裝在Proc中,那纔是真實的。 – Chuck

+1

參數必須是一個對象。塊不是一個對象。 **證明:**如果一個塊是一個對象,它應該是一個'Object'實例,並且應該響應'object_id'方法。但是,「{puts」foo「}。object_id'會引發語法錯誤。因此,一個塊是一個對象的假設是錯誤的。 QED。 – sawa

+0

@sawa我一直認爲它叫做語法糖。我的'times'版本中的'block'同時具有class和'object_id'。簡單的例子:'some_method(:a => 1)'。 ':a => 1.object_id'?那些大括號在哪裏? –