2011-12-31 33 views
7

Khi có một khối hoặc biến địa phương không được sử dụng, đôi khi mọi người đánh dấu nó bằng * và đôi khi với _.Đánh dấu biến khối không sử dụng

{[1, 2] => 3, [4, 5] => 6}.each{|(x, *), *| p x} 

{[1, 2] => 3, [4, 5] => 6}.each{|(x, _), _| p x} 

{[1, 2, 3], [4, 5, 6]}.each{|*, x, *| p x} 

{[1, 2, 3], [4, 5, 6]}.each{|_, x, _| p x} 

def (x, *), *; p x; end 

def (x, _), _; p x; end 

def *, x, *; p x; end 

def _, x, _; p x; end 

Sự khác biệt giữa chúng là gì và khi nào tôi nên sử dụng? Khi có cần phải đánh dấu nhiều biến là không sử dụng như trong các ví dụ trên, hoặc là tốt hơn?

Trả lời

26

A * có nghĩa là "tất cả các tham số còn lại". An _ chỉ là một tên biến, mặc dù nó là một chút đặc biệt. Vì vậy, chúng khác nhau, ví dụ như sau không có ý nghĩa:

[[1, 2, 3], [4, 5, 6]].each{|*, x, *| p x} # Syntax error 

Thật vậy, làm sao Ruby biết sao đầu tiên có được 0, 1 hoặc 2 giá trị (và ngược lại)?

Có rất ít trường hợp bạn muốn sử dụng dấu sao để bỏ qua tham số. Một ví dụ sẽ được nếu bạn chỉ muốn sử dụng cuối cùng của một số biến của tham số:

của Ruby cho phép bạn không đặt tên cho "nghỉ ngơi" của các thông số, nhưng bạn có thể sử dụng _:

[[1], [2, 3], [4, 5, 6]].each{|*_, last| p last} # => prints 1, 3 and 6 

thông thường, số lượng các thông số được biết đến và lựa chọn tốt nhất của bạn là sử dụng một _:

[[1, 2, 3], [4, 5, 6]].each{|_, mid, _| p mid} # prints 2 and 5 

Lưu ý rằng bạn có thể rời khỏi unna paramater cuối cùng med quá (như bạn có thể khi sử dụng một *), mặc dù nó là ít rõ ràng:

[[1, 2, 3], [4, 5, 6]].each{|_, mid, | p mid} # prints 2 and 5 

Bây giờ _các định tên biến để sử dụng khi bạn không muốn sử dụng một giá trị. Nó là một tên biến đặc biệt vì hai lý do:

  1. Ruby sẽ không phàn nàn nếu bạn không sử dụng nó (nếu cảnh báo đang trên)
  2. Ruby sẽ cho phép bạn lặp lại nó trong danh sách đối số.

Ví dụ về điểm 1:

> ruby -w -e "def foo; x = 42; end; foo" 
-e:1: warning: assigned but unused variable - x 

> ruby -w -e "def foo; _ = 42; end; foo" 
no warning 

Ví dụ về điểm 2:

[[1, 2, 3], [4, 5, 6]].each{|unused, mid, unused| p mid} 
# => SyntaxError: (irb):23: duplicated argument name 

[[1, 2, 3], [4, 5, 6]].each{|_, mid, _| p mid} 
# => prints 2 and 5 

Cuối cùng, như ghi chú @DigitalRoss, _ giữ kết quả cuối cùng trong irb

Cập nhật: Trong Ruby 2.0, bạn có thể sử dụng bất kỳ biến nào bắt đầu bằng _ để biểu thị nó không được sử dụng. Bằng cách này, tên biến có thể rõ ràng hơn về những gì bị bỏ qua:

_scheme, _domain, port, _url = parse_some_url 
# ... do something with port 
+0

Cảm ơn câu trả lời chi tiết.Câu trả lời này có tất cả các thông tin mà tôi muốn. – sawa

1

Tôi nghĩ rằng đó là chủ yếu là phong cách và sự lựa chọn của nhà lập trình. Sử dụng * có ý nghĩa hơn với tôi trong Ruby vì mục đích của nó là tích lũy tất cả các tham số truyền từ vị trí đó trở đi. _ là một biến số hiếm hoi mà hiếm khi được sử dụng trong Ruby, và tôi đã nghe ý kiến ​​rằng nó cần phải biến mất. Vì vậy, nếu tôi sử dụng một trong hai, tôi sẽ sử dụng *.

MỘT SỐ công ty có thể xác định nó trong tài liệu phong cách lập trình của họ, nếu họ có, nhưng tôi nghi ngờ nó có giá trị phần lớn thời gian của họ vì nó là một biến ném. Tôi đã phát triển chuyên nghiệp trong hơn 20 năm, và chưa bao giờ thấy bất cứ điều gì xác định việc đặt tên của một ném đi.

Cá nhân, tôi không lo lắng về điều này và tôi sẽ quan tâm hơn đến việc sử dụng các biến số một chữ cái. Thay vào đó, tôi sẽ sử dụng unused hoặc void hoặc blackhole cho mục đích này.

+3

'_' là * không * biến mất và có cách điều trị cụ thể, xem câu trả lời của tôi. Hơn nữa, chạy Ruby trong cảnh báo có thể cung cấp cho bạn cảnh báo khi sử dụng 'không sử dụng' hoặc mô phỏng, nhưng không phải với' _'; xem câu trả lời của tôi quá ;-) –

1

Sự khác nhau giữa chúng là gì?

Trong trường hợp _ một biến cục bộ _ đang được tạo. Nó giống như sử dụng x nhưng được đặt tên khác.

Trong trường hợp * trường hợp việc gán biểu thức cho * sẽ tạo [expression]. Tôi không hoàn toàn chắc chắn những gì nó hữu ích vì nó dường như không làm bất cứ điều gì mà chỉ xung quanh biểu thức với dấu ngoặc ôm.

Khi nào tôi nên sử dụng?

Trong trường hợp thứ hai, bạn không kết thúc bằng một biểu tượng thừa được tạo nhưng có vẻ như hoạt động hơi nhiều cho trình thông dịch. Ngoài ra, rõ ràng là bạn sẽ không bao giờ sử dụng kết quả đó, trong khi với _ người ta phải đọc vòng lặp để biết nếu nó được sử dụng.

Nhưng tôi dự đoán rằng chất lượng mã của bạn sẽ phụ thuộc vào những thứ khác mà bạn sử dụng để loại bỏ các thông số khối không được sử dụng. Các * không có một yếu tố mát mẻ tối nghĩa nhất định mà tôi loại như thế nào.

Lưu ý: khi thử nghiệm với điều này, lưu ý rằng trong irb, _ giữ giá trị của biểu thức cuối cùng được đánh giá.

+0

Bạn có nghĩa là '**' trường hợp, hoặc '*'? Tôi có nghĩa là '*', nhưng chúng khác nhau? Tôi biết việc sử dụng '*' như tạo một mảng khi được đặt trước tên biến, nhưng là sử dụng riêng biệt '*' giống nhau không? Và trong môi trường chính, nếu tôi gõ '* = ['a']', nó trả về '['a']'. Điều đó nghĩa là gì? – sawa

1

IMO thực tiễn làm cho mã ít đọc được hơn và ít rõ ràng hơn.

Đặc biệt trong các phương pháp API lấy các khối, có thể không rõ khối thực sự mong đợi. Điều này cố ý loại bỏ thông tin từ nguồn, làm cho bảo trì và sửa đổi khó khăn hơn.

Tôi muốn các biến được đặt tên phù hợp; trong một khối ngắn nó sẽ được rõ ràng nó không được sử dụng. Trong các khối dài hơn, nếu không sử dụng là đáng chú ý, một bình luận có thể giải thích về lý do.

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