2011-08-07 35 views
6

Tôi đang chạy ruby ​​1.9.2p180 (2011-02-18 phiên bản 30909) [x86_64-linux].trong ruby, tại sao không được xác định? hoạt động như mong đợi khi được sử dụng với đảm bảo

#!/usr/bin/env ruby 

    def ouch() 
      raise ArgumentError, "woof" 
      fred = 3 
      return(nil) 

    ensure 
      if (defined?(fred)) then 
        printf("fred is defined (%s)\n", fred.inspect()) 
      else 
        printf("fred is not defined\n") 
      end 

    end # ouch() 


    ouch() 

Khi chạy, đầu ra từ tập lệnh ruby ​​ở trên là khá bất ngờ.

$ ./ouch.rb 
    fred is defined (nil) 
    ./ouch.rb:4:in `ouch': woof (ArgumentError) 
      from ./ouch.rb:22:in `<main>' 

Vì vậy, tăng/ngoại lệ đang xảy ra, fred là không nhận được thiết lập để 3, nhưng nó là nhận được xác định và thiết lập để nil, qua đó đánh bại thử nghiệm cho định nghĩa?(). Điều này rất khó hiểu. Đây có phải là một lỗi? Rõ ràng là các thử nghiệm cho các nhu cầu được xác định để được theo sau bằng cách thử nghiệm cho không nil.

Nếu đây không phải là lỗi, ai đó có thể giải thích lý do không?

Trả lời

7

Biến cục bộ trong Ruby được xác định giữa dòng đầu tiên chúng được sử dụng tại và cuối phạm vi từ vựng hiện tại. Chúng cũng được khởi tạo thành nil hoàn toàn.

cũng ví dụ này xem xét:

if false 
    var = 123 
end 
p var # => nil 

Hành vi này được dự định. Ruby được thiết kế theo cách nó có thể phân biệt giữa các cuộc gọi phương thức và truy cập biến cục bộ tại các bước phân tích cú pháp, không thực thi. Vì vậy, sau thời điểm mà một biến đã được xác định, tất cả các tham chiếu thêm vào tên đó sẽ truy cập biến, cho dù nó được đặt rõ ràng thành một giá trị nào đó hay không.

(Nếu ai đó trỏ tôi đến loại cuộc gọi phương thức CALL_VCALL trong Ruby, tôi sẽ trả lời rằng theo như tôi biết, nó chỉ được sử dụng trong eval: khi bạn là eval -ing, bạn không thể biết ngay từ đầu nếu một số biến được định nghĩa trên dòng trước của IRB, do đó truy cập như vậy nên được đánh bắt và cử cho phù hợp.)

+0

biến của Ruby được định nghĩa từ dòng trong mã nguồn của họ được giao nhiệm vụ đầu tiên. Bạn không thể sử dụng chúng trước khi được chỉ định. Vì vậy, chúng được _not_ "định nghĩa ở đầu khối mà chúng được sử dụng trong". –

+0

@RobertKlemme Điểm tuyệt vời, cố định. – whitequark

4
  • Không phải là một lỗi
  • biến địa phương được tạo ra bằng cách chuyển nhượng, nhưng nó chỉ ra rằng việc chuyển nhượng chỉ cần được phân tích cú pháp, không thực sự được thực thi ...

Dưới đây là một ví dụ đơn giản:

if false 
    alocal = 123 
end 
p defined? alocal 
=> "local-variable" 
Các vấn đề liên quan