2010-09-09 28 views
16

Tôi là một người mới bắt đầu trong Ruby, vì vậy tôi xin lỗi để hỏi một cái gì đó đơn giản như vậy, nhưng có điều gì sai trái với mã này -của Ruby multiline khối mà không làm chấm dứt

3.upto(9) { 
    print "Hello" 
    puts " World" 
} 

hoặc

3.upto(9) { |n| 
    print "Hello " 
    puts n 
} 

nó hoạt động khá tốt, nhưng hầu hết các mẫu mã tôi thấy sử dụng cú pháp của

3.upto(9) do |n| 
    print "Hello " 
    puts n 
end 

là nó chỉ là ước để chỉ sử dụng c niềng răng đay cho câu đơn? Xuất phát từ C/C# lần đầu tiên có vẻ tự nhiên hơn với tôi, nhưng khi ở Rome!

+0

Đây là bản sao của [Lỗi cú pháp khối Ruby] (http://StackOverflow.Com/q/6854283/), [Khối mã được chuyển đến 'mỗi' hoạt động với dấu ngoặc nhưng không có' do'-' end' (ruby)] (http://StackOverflow.Com/q/6718340/), [Block definition - sự khác biệt giữa niềng răng và 'do'-'end'?] (http://StackOverflow.Com/q/6179442 /), [Sử dụng 'do' block vs brackets' {} '] (http://StackOverflow.Com/q/2122380/), [Sự khác biệt hay giá trị của các kiểu mã hóa khối này trong Ruby là gì?] (Http: //StackOverflow.Com/q/533008/) và [Ruby block và unheshesized arguments] (http://StackOverflow.Com/q/420147/). –

Trả lời

37

Có sự khác biệt tinh tế giữa hai cú pháp. { } có mức độ ưu tiên cao hơn do ... end. Như vậy, sau đây sẽ vượt qua bar và một khối phương pháp foo:

foo bar do ... end 

trong khi sau đây sẽ vượt qua một khối để bar, và kết quả đó để foo:

foo bar { ... } 

Vì vậy, ví dụ bạn sẽ hành động tương tự. Tuy nhiên, nếu bạn rời khỏi ngoặc off:

> 3.upto 9 { 
    puts "Hi" 
} 
SyntaxError: compile error 
(irb):82: syntax error, unexpected '{', expecting $end 
3.upto 9 { 
     ^
    from (irb):82 
    from :0 

> 3.upto 9 do 
    puts "Hi" 
    end 
Hi 
Hi 
Hi 
Hi 
Hi 
Hi 
Hi 
=> 3 

Vì vậy, { } có nhiều khả năng để bắt bạn lên nếu bạn rời khỏi ngoặc trong Ruby, mà là khá phổ biến; vì lý do này và bởi vì Ruby có điều kiện và các cấu trúc điều khiển khác đều sử dụng end làm dấu phân cách, mọi người thường sử dụng do ... end cho các khối mã nhiều dòng ở cuối câu lệnh.

Tuy nhiên, { } thường được sử dụng ở những nơi mà do ... end sẽ là cồng kềnh, ví dụ: nếu bạn đang kết hợp một số phương thức với nhau. Điều này có thể cho phép bạn viết các khối nhỏ, một dòng có thể được sử dụng như một phần của chuỗi phương thức.

> [1,2,3].sort{|x,y| y<=>x}.map{|x| x+1} 
=> [4, 3, 2] 

Dưới đây là một ví dụ để minh họa cho sự khác biệt này:

def foo arg 
    if block_given? 
    puts "Block given to foo" 
    yield arg 
    else 
    puts "No block given to foo" 
    arg 
    end 
end 


def bar 
    if block_given? 
    puts "Block given to bar" 
    yield "Yielded from bar" 
    else 
    puts "No block given to bar" 
    end 
    "Returned from bar" 
end 

irb(main):077:0> foo bar { |arg| puts arg } 
Block given to bar 
Yielded from bar 
No block given to foo 
=> "Returned from bar" 
irb(main):078:0> foo bar do |arg| puts arg end 
No block given to bar 
Block given to foo 
Returned from bar 
=> nil 
+0

Cảm ơn bạn nhiều! –

+0

"Tuy nhiên, {} có thể được sử dụng trong trường hợp mà không thể, ví dụ, nếu bạn đang xích một số phương pháp với nhau mà có khối." Đo không phải sự thật. 'do' có thể được sử dụng hoàn toàn tốt với chuỗi. '[1,2,3] .map do | x | x + 1 end.each do | x | đặt x end' hoạt động tốt. – sepp2k

+0

@ sepp2k Bạn nói đúng về trường hợp đó; Tôi đã lầm. Tôi đã cập nhật câu trả lời của mình để cho biết rằng trường hợp đó chỉ đơn giản là vấn đề về phong cách. –

6

Đó chỉ là quy ước.

+0

nói riêng, quy ước là chúng ta thực hiện cú pháp cho nhiều dòng, curlies cho một dòng ... nhưng xem câu trả lời về quyền ưu tiên cho câu trả lời nhiều hơn. –

0

seamless. Từ số README:

Python cho phép bạn báo hiệu kết thúc của khối mã với thụt lề. Ruby bị một người kết thúc khối cực kỳ dài dòng và tẻ nhạt, "kết thúc". Giống như Lisps kết thúc với hàng chục parens gần gũi, các tập tin Ruby sử dụng các mô-đun và các lớp học kết thúc với rất nhiều "kết thúc" mà chỉ là không cần thiết.

Viết tệp Ruby nhưng bỏ qua tất cả "kết thúc". Xếp hàng các khối mã của bạn như trong Python. Sau đó, chỉ cần gọi nó là 'your_file.rbe', yêu cầu 'liền mạch' và yêu cầu 'your_file'. Dàn phần còn lại.

Điều này có bao giờ được sử dụng rộng rãi không? Tôi không biết. Nhưng nó khá thú vị!

Các vấn đề liên quan