2011-10-09 30 views
5

Tôi đang học những điều cơ bản của Ruby (chỉ mới bắt đầu), và tôi đã xem qua số Hash.[] method. Nó đã được giới thiệu vớiCó "quy tắc" cho đường cú pháp của Ruby không?

a = ["foo", 1, "bar", 2] 
=> ["foo", 1, "bar", 2] 
Hash[*a] 
=> {"foo"=>1, "bar"=>2} 

Với một chút suy nghĩ, tôi đã tìm ra rằng Hash[*a] tương đương với Hash.[](*a) hoặc Hash.[] *a. Câu hỏi của tôi là tại sao lại như thế. Nó cho phép bạn đặt *a bên trong dấu ngoặc vuông là gì và có loại quy tắc nào ở đâu và khi nào khác "nó" có thể được sử dụng?

Chỉnh sửa: Từ ngữ của tôi có vẻ gây nhầm lẫn. Tôi không hỏi về việc mở rộng mảng. Tôi hiểu rồi. Câu hỏi của tôi về cơ bản là: nếu [] là tên phương thức, tại sao việc đặt các đối số bên trong dấu ngoặc đơn là không quan trọng? Nó có vẻ gần như - nhưng không hoàn toàn - như nói rằng nếu bạn có một phương pháp Foo.dood, và bạn muốn vượt qua chuỗi "hey" với nó, sau đó bạn có thể viết Foo.do"hey"od.

+0

Tôi thấy rất nhiều câu trả lời tập trung vào '* a' trong lời gọi phương thức. Tuy nhiên, sẽ tốt hơn nếu thấy các sản phẩm khác được giải quyết, chẳng hạn như tại sao '[1, * a]' hoạt động như mong đợi "(cho kết quả khác với' [1, a] ') và tại sao' [* a, 1] 'không hợp lệ. Nó cũng sẽ được tốt đẹp để xem làm thế nào "splat" liên quan đến nhiệm vụ và làm thế nào nó có thể/không tương tác với phân công-phân hủy của Ruby ... có lẽ được cho là một câu hỏi SO hoàn toàn ;-) Nó sẽ được * thực sự tốt đẹp * nếu có một ruby bán chính thức. Liên kết đến bán hàng kỹ thuật sẽ làm cho câu trả lời tốt hơn. –

+0

@pst: câu hỏi hay. Nếu bạn hỏi một câu hỏi SO mới về nó, hãy đăng liên kết ở đây để tôi có thể theo dõi nó. –

+0

lưu ý rằng cách thông thường sử dụng nó là gửi một mảng các cặp: Hash [[[key1, value1], [key2, value2]]] – tokland

Trả lời

3

Có một vài phương pháp mà ruby ​​cho phép bạn gọi trong một đặc biệt đường. Đây là số [] như bạn đã đề cập, +, -, == và các nội dung tương tự như người khác được đề cập.Một ví dụ quan trọng khác là các phương thức của mẫu something=(value) có thể được gọi với object.something = value và cho phép bạn tạo người truy cập.

Edit:

thực tế Fun 1: nếu bạn xác định một phương pháp + bạn nhận được += miễn phí.

thực tế Fun 2: nếu bạn định nghĩa một <=> bạn nhận được tất cả các phương pháp so sánh, biếu không của Comparable

+0

Vì vậy, có một danh sách ở đâu đó của công cụ "đặc biệt" này? –

+1

Có một danh sách các toán tử có thể được ghi đè [ở đây] (http://www.zenspider.com/Languages/Ruby/QuickRef.html#28) –

4

Hash["a", "b", "c", "d"] tương đương với Hash.[]("a", "b", "c", "d"). Hầu hết mọi thứ trong Ruby là một cuộc gọi phương thức. 5 + 5 tương đương với 5.+(5).

Cho a = ["a", "b", "c", "d"]Hash[*a] tương đương với Hash["a", "b", "c", "d"], lần lượt tương đương với Hash.[]("a", "b", "c", "d"). Tương tự, foo(*a) tương đương với foo("a", "b", "c", "d") Điều này được gọi là toán tử phát nổ, và cho phép gửi một mảng tới một phương thức và có mỗi mục trong mảng được tính là một đối số cho phương thức, thay vì gửi mảng tới phương thức làm đối số đầu tiên.


Để trả lời cụ thể cập nhật của bạn, không có gì đặc biệt cho phép bạn đặt *a bên trong dấu ngoặc vuông. Các dấu ngoặc đơn chỉ là đường cho một cuộc gọi phương thức thông thường. Điều "đặc biệt" duy nhất ở đây là bạn có thể gửi *a cho bất kỳ phương pháp nào.

+0

Vì vậy, [tất cả] những nơi mà mở rộng splat được cho phép là gì? (Có ít nhất một liên kết khác không liên quan đến lời gọi phương thức AFAIK.) –

+0

Cập nhật? Tôi chưa cập nhật gì cả. Vì vậy, bạn có nói rằng bất cứ nơi nào mà dấu ngoặc vuông xảy ra trong Ruby như một tên phương pháp, bạn có thể sử dụng dấu ngoặc vuông thay vì dấu ngoặc đơn để chứa danh sách đối số? I.e bất kỳ phương pháp cũ 'Foo. []' Lấy các đối số a, b, và c có thể được viết là 'Foo [a, b, c]'? Đó có phải là một tính năng ngôn ngữ kỳ diệu không? –

+0

Đúng vậy. Một phương thức có tên [] có thể được gọi với đường 'my_obj [foo]'. Phương thức có tên [] = có thể được gọi với 'my_obj [foo] = bar'. Điều này biến thành 'my_obj. [] = (Foo, bar)'. Đây là những gì sức mạnh cú pháp của 'Hash' trường hợp. Cũng có 'Dir [" glob pattern "]', biến đổi thành 'Dir. [] (" Glob pattern ")'. –

0

Phương thức *<Array> yêu cầu ruby ​​không lấy mảng làm mảng, nhưng để sử dụng mảng 'được mở rộng'.

Ví dụ:

def test(*argv) 
    p argv 
end 

a = [1,2,3] 
test(a) #-> [[1, 2, 3]] 
test(*a) #-> [1, 2, 3]  

Với test(a) mảng a là một và chỉ tham số.

Với test(*a) a được sử dụng làm danh sách tham số.


Trong trường hợp của bạn

a = ["foo", 1, "bar", 2] 
Hash[*a] 

cũng tương tự như

Hash[*a] sẽ

Hash[["foo", 1, "bar", 2]] 
+0

Phải, nhưng điều này được cho phép ở đâu hoặc không được phép? (ví dụ: các quy tắc sản xuất là gì?) –

+0

Phụ thuộc vào phương pháp mà bạn sử dụng nó. 'a' là một mảng,' * a' là danh sách các tham số. Vì vậy, câu hỏi là không, là '* a' được cho phép, nhưng: Tôi có cần một mảng như tham số, hoặc tôi cần một danh sách tham số. – knut

+0

Câu hỏi của tôi không phải là về việc mở rộng mảng. Đó là về phương pháp '[]' và đặc biệt là tại sao nó được đặt đối số bên trong các dấu ngoặc đó. –

2

Tôi nghĩ rằng cú pháp Ruby được định nghĩa trong parse.y cho YARV Ruby.

+0

+1 để truy cập vào phần ghi đè không cần thiết của IMHO. –

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