Ruby: nếu biến vs nếu biến.nil?


11

Tôi mới biết về Ruby và tôi đã rất ngạc nhiên khi phát hiện ra rằng tất cả các đối tượng là đúng và không. Ngay cả 0 là đúng.

Một điều tốt đẹp về tài sản của ngôn ngữ là bạn có thể viết:

if !variable
  # do stuff when variable is nil
end

Các đồng nghiệp của tôi, những người phát triển Ruby dày dạn hơn, khẳng định tôi nên chọn điều đó thay vì sử dụng .nil? như vậy

if variable.nil?
  # do stuff when variable is nil
end

Tuy nhiên tôi tin rằng cái sau là một lựa chọn tốt hơn vì hai lý do: 1. Tôi nghĩ rằng nó hướng đối tượng hơn, đặc biệt là trong một ngôn ngữ như Ruby, nơi mọi thứ đều là một đối tượng và trao đổi thông điệp. 2. Nó dễ đọc hơn, theo ý kiến ​​chủ đề của tôi, ngay cả khi nó nhỏ gọn hơn.

Tôi có đang phạm sai lầm "người mới" ở đây không?


4
Bạn đang thử nghiệm cho con số không? hoặc một giá trị sai?

Tôi đang thử nghiệm cho con số không. Về cơ bản nếu biến là con số không, tôi sẽ làm một cái gì đó (hoặc không)
Javier Holguera

3
Nếu bạn đang kiểm tra cho con số không, tại sao bạn muốn kiểm tra sai cũng nhập vào khối đó?

Đồng ý, tôi chỉ ra rằng đó là một lý do khác để thích .nil? Nhưng họ nhấn mạnh rằng "if biến do x" là thành ngữ hơn "if
biến.nil

Câu trả lời:


17

Viết những gì bạn có ý nghĩa. Có nghĩa là những gì bạn viết.

Hãy làm một bài kiểm tra khác. .vowel?

if char == 'a'
   # do stuff
end

đấu với

if char.vowel?
   # do stuff
end

Bây giờ, rõ ràng là những điều này không làm điều tương tự. Nhưng nếu bạn chỉ mong charđược ahoặc bnó sẽ làm việc. Nhưng nó sẽ gây nhầm lẫn cho nhà phát triển tiếp theo - khối thứ hai sẽ được nhập vào cho các điều kiện cũng có char [eiou]. Nhưng cho a, nó sẽ hoạt động chính xác.

Vâng, đó là trường hợp nilfalselà giá trị giả mạo duy nhất trong Ruby. Tuy nhiên, nếu bạn đang kiểm tra nilbằng cách kiểm tra nil || false, đây không phải là ý bạn.

Điều đó có nghĩa là nhà phát triển tiếp theo (người tình cờ là một kẻ giết rìu điên rồ biết địa chỉ nhà của bạn) sẽ đọc mã và tự hỏi tại sao falsecũng nên vào đó.

Viết mã truyền tải chính xác những gì bạn muốn nói.


3

Hãy xem xét những điều sau đây:

response = responses.to_a.first

Điều này sẽ trả về phần tử đầu tiên của responses, hoặc nil. Sau đó, vì các câu điều kiện xử lý nilnhư falsechúng ta có thể viết:

response = responses.to_a.first
if response
  # do something ('happy path')
else
  # do something else
end

Cái nào dễ đọc hơn:

if response.nil?
  # do something else
else
  # do something ('happy path')
end

Các if (object)mô hình là rất phổ biến trong mã Ruby. Nó cũng dẫn độc đáo đến tái cấu trúc, ví dụ:

if response = responses.to_a.first
  do_something_with(response)
else
  # response is equal to nil
end

Cũng nhớ rằng một phương thức Ruby trả về niltheo mặc định. Vì thế:

def initial_response
  if @condition
    @responses.to_a.first
  else
    nil
  end
end

có thể được đơn giản hóa để:

def initial_response
  if @condition
    @responses.to_a.first
  end
end

Vì vậy, chúng tôi có thể tái cấu trúc thêm:

if response = initial_response
  do_something_with(response)
else
  # response is equal to nil
end

Bây giờ bạn có thể lập luận rằng trở về nilkhông phải lúc nào cũng là ý tưởng tốt nhất, vì nó có nghĩa là kiểm tra nilmọi nơi. Nhưng đó là một ấm cá khác. Cho rằng việc kiểm tra đối tượng "hiện diện hay vắng mặt" là một yêu cầu thường xuyên như vậy, tính trung thực của các đối tượng là một khía cạnh hữu ích của Ruby, mặc dù gây ngạc nhiên cho những người mới sử dụng ngôn ngữ này.


2

Không chỉ được if variable.nil?đọc giống như ngôn ngữ tự nhiên, nó còn bảo vệ chống lại một lập trình viên vô tình gán cho nó một falsegiá trị và rơi vào iftuyên bố của bạn , vì Ruby là một ngôn ngữ được đánh máy lỏng lẻo.


1
Vậy nhận xét ban đầu trong câu hỏi ban đầu có sai không? Có nên "làm công cụ khi biến là không hoặc sai"? Và vì mã không phù hợp với nhận xét là một lỗi, ngay lập tức có một lỗi?
gnasher729

Chính xác. Một bài kiểm tra tính trung thực đơn giản có thể giới thiệu các lỗi logic.
Greg Burghardt

0

Thành ngữ, unless variablelà thích hợp hơn if !variable. Các iftuyên bố phủ định thường được coi là một mùi mã vì dễ bỏ qua các phủ định khi lướt qua.

Bức tranh lớn hơn ở đây là việc nilkiểm tra như thế này cũng có một chút mùi mã. Đối với OO thích hợp, hãy nhắm đến việc sử dụng mẫu đối tượng null để loại kiểm tra này không bao giờ cần thiết. http://devblog.avdi.org/2011/05/30/null-objects-and-falsiness/

Nói cho đối tượng biết phải làm gì, đừng hỏi họ là gì. Điều này đôi khi được gọi là nói đừng hỏi

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.