2009-03-20 53 views
56

Ký hiệu ống trong Ruby là gì?Các ký hiệu ống trong Ruby là gì?

tôi đang học Ruby và RoR, đến từ một PHP và nền Java, nhưng tôi tiếp tục đi ngang qua mã như thế này:

def new 
    @post = Post.new 

    respond_to do |format| 
    format.html # new.html.erb 
    format.xml { render :xml => @post } 
    end 
end 

các |format| phần làm là gì? Cú pháp tương đương của các ký hiệu ống này trong PHP/Java là gì?

Trả lời

42

Chúng là các biến được mang lại cho khối.

def this_method_takes_a_block 
    yield(5) 
end 

this_method_takes_a_block do |num| 
    puts num 
end 

Đầu ra nào "5". Một ví dụ phức tạp hơn:

def this_silly_method_too(num) 
    yield(num + 5) 
end 

this_silly_method_too(3) do |wtf| 
    puts wtf + 1 
end 

Đầu ra là "9".

+0

nơi nào 'wtf' đi khi khối' | wtf | 'kết thúc? – ThorSummoner

+0

Nó được sắp xếp theo khối, vì vậy nó không có sẵn bên ngoài nó. Nói cách khác: nó biến mất. –

+0

Nếu nó có thể thay đổi? Nó phải được, nếu không tôi không có bất kỳ đầu mối như thế nào Vagrantfile của có thể sử dụng chúng như là một phương pháp cấu hình. – ThorSummoner

5

Mã từ do đến end xác định Ruby block. Từ format là một tham số cho khối. Khối được truyền cùng với lời gọi phương thức và phương thức được gọi có thể là giá trị yield cho khối.

Xem bất kỳ văn bản nào trên Ruby để biết chi tiết, đây là tính năng cốt lõi của Ruby mà bạn sẽ thấy mọi lúc.

+1

Không, mã giữa đầu và cuối là khối ruby. Các thuật ngữ giữa các thanh dọc là các tham số cho khối đó. – rampion

+0

IIRC, cú pháp ống được mượn từ Smalltalk. –

+0

Đúng, ngoại trừ Smalltalk chỉ sử dụng một đường ống. – Chuck

3

Tương đương trong Java sẽ là một cái gì đó giống như

// Prior definitions 

interface RespondToHandler 
{ 
    public void doFormatting(FormatThingummy format); 
} 

void respondTo(RespondToHandler) 
{ 
    // ... 
} 

// Equivalent of your quoted code 

respondTo(new RespondToHandler(){ 
    public void doFormatting(FormatThingummy format) 
    { 
     format.html(); 
     format.xml(); 
    } 
}); 
+0

Brent, nếu bạn muốn nói rằng, phiên bản Java là tiết và dài dòng, tôi đồng ý với bạn. Nhưng sau đó một lần nữa, đây là một cấu trúc ít thành ngữ trong Java. Ruby sử dụng nó mọi lúc, Java ít hơn. –

+0

format.html(); format.xml(); một phần có lẽ sẽ giống như một tuyên bố chuyển đổi, vì bạn muốn chuyển sang định dạng được yêu cầu. – jonnii

+0

Một ví dụ rõ ràng hơn là xây dựng tương đương trong JavaScript: respond_to (hàm mới (định dạng) {format.html(); format.xml();}); Tôi thấy Java thiếu sự hỗ trợ functor thực sự gây phiền nhiễu; chúng không khó sử dụng chút nào - trừ khi bạn đã học chúng với các lớp ẩn danh trong Java! –

2

Các tham số cho một ngồi block giữa | các biểu tượng.

5
@names.each do |name| 
    puts "Hello #{name}!" 
end 

tại http://www.ruby-lang.org/en/documentation/quickstart/4/ kèm theo lời giải thích này:

each là một phương pháp mà chấp nhận một khối mã sau đó chạy mà khối mã cho mỗi phần tử trong một danh sách, và các bit giữa doend chỉ là một khối. Một khối giống như một hàm ẩn danh hoặc lambda. Biến giữa các ký tự ống là tham số cho khối này.

Điều gì xảy ra ở đây là cho mỗi mục nhập trong danh sách, name được liên kết với phần tử danh sách đó, sau đó biểu thức puts "Hello #{name}!" được chạy với tên đó.

24

Điều này rất lạ với tôi lúc đầu, nhưng tôi hy vọng giải thích này/walkthru sẽ giúp bạn.

Tài liệu touches the subject, theo cách khá tốt - nếu câu trả lời của tôi không giúp tôi chắc chắn hướng dẫn của họ sẽ như thế nào.

Trước tiên, hãy kích hoạt trình thông dịch Tương tác Ruby bằng cách nhập irb vào vỏ và nhấn Nhập.

Loại gì đó như:

the_numbers = ['ett','tva','tre','fyra','fem'] # congratulations! You now know how to count to five in Swedish. 

chỉ để chúng tôi có một mảng để chơi với.Sau đó, chúng tôi tạo vòng lặp:

the_numbers.each do |linustorvalds| 
    puts linustorvalds 
end 

Nó sẽ xuất tất cả các số, được phân tách bằng dòng mới.

Trong các ngôn ngữ khác mà bạn muốn phải viết một cái gì đó như:

for (i = 0; i < the_numbers.length; i++) { 
    linustorvalds = the_numbers[i] 
    print linustorvalds; 
} 

Những điều quan trọng cần lưu ý là rằng |thing_inside_the_pipes| có thể bất cứ điều gì, miễn là bạn đang sử dụng nó một cách nhất quán. Và hiểu rằng đó là vòng mà chúng ta đang nói đến, đó là điều tôi đã không nhận được cho đến sau này.

+2

Trong một số "ngôn ngữ khác" (Python), bạn viết 'cho linustorvalds trong the_numbers làm print linustorvalds'. Một chút trực quan hơn, có lẽ. –

+1

Hoàn toàn chính xác. Tôi đã chọn cú pháp kiểu C vì tôi nghi ngờ nhiều người đến với ruby ​​đã quen thuộc với điều đó, nhưng tôi hy vọng họ cũng đọc nhận xét của bạn. –

+0

Cảm ơn bạn. Phần "ngôn ngữ khác" đã giúp tôi hiểu những gì đang diễn ra. +1. – rayryeng

1

Để làm cho nó thậm chí nhiều hơn rõ ràng hơn, nếu cần thiết:

các thanh ống chủ yếu tạo ra một biến mới để giữ giá trị tạo ra từ các cuộc gọi phương pháp trước. Một cái gì đó tương tự như:

định nghĩa gốc của phương pháp của bạn:

def example_method_a(argumentPassedIn) 
    yield(argumentPassedIn + 200) 
end 

Làm thế nào Nó được sử dụng:

example_method_a(100) do |newVariable| 
    puts newVariable; 
end 

Nó gần giống như cách viết này:

newVariable = example_method_a(100) 
puts newVariable 

wher e, newVariable = 200 + 100 = 300: D!

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