2012-02-06 27 views
10

Tôi đang cố gắng để đánh giá biểu thức (a=10) || (rr=20) khi biến rr không được định nghĩaLiệu || toán tử đánh giá đối số thứ hai ngay cả khi đối số đầu tiên là đúng?

vì vậy việc đánh rr trong ruby ​​console trước khi đánh giá sự biểu hiện trước trả

rr 
NameError: undefined local variable or method `rr' for main:Object 
from (irb):1 
from :0 

Khi tôi viết biểu thức (a=10) || (rr=20) nó trả về 10, và khi tôi viết rr sau đó nó nói nil

(a=10) || (rr=20) 
rr # => nil 

vậy, tại sao điều này lại xảy ra? Không nên định nghĩa rr nếu đối số thứ hai của || toán tử được đánh giá, không bao giờ nên dựa trên tài liệu này?

+1

Có sự khác biệt giữa các hoạt động có điều kiện ngắn mạch (không đánh giá điều kiện thứ hai nếu điều kiện đầu tiên là sai) và không khai báo biến. Vấn đề của bạn liên quan đến vấn đề thứ hai. – DOK

+1

Biết khi nào một biến cục bộ nằm trong phạm vi của bạn thì khó khăn trong Ruby. Thử chạy 'a + 1 nếu a = 5'. Bạn có thể mong đợi rằng nó sẽ thiết lập một đến 5 và sau đó trở về 6, nhưng thực sự nó sẽ đặt 'a' và THEN phàn nàn về' a' là không xác định. –

Trả lời

10

Điều này xảy ra vì thông dịch viên ruby ​​xác định một biến khi nó thấy một bài tập cho nó (nhưng trước khi nó thực thi dòng mã thực). Bạn có thể đọc thêm về nó in this answer.

OR (||) biểu thức Boolean sẽ đánh giá giá trị của biểu thức tay trái nếu nó không phải là nil và không false, khác || sẽ đánh giá giá trị của biểu thức bên phải.

Trong ví dụ của bạn thông dịch viên ruby ​​thấy một bài tập để arr (nhưng nó không thực hiện dòng này chưa), và khởi (định nghĩa, tạo ra) arr với nil. Sau đó, nó thực thi biểu thức ||. Trong biểu thức || này, a được gán cho 1010 được trả lại. r=20 không được đánh giá và rr không bị thay đổi (vẫn là nil). Đây là lý do tại sao trong dòng tiếp theo rrnil.

+0

Biến là * không * được khởi tạo, nó chỉ được xác định. Đó là lý do tại sao nó đánh giá thành 'nil': bởi vì các biến uninitialized được đánh giá là' nil' trong Ruby. Nếu nó * được * khởi tạo, nó sẽ đánh giá thành '20', không phải' nil'. –

+0

@ JörgWMittag, tnx cho từ ngữ chính xác. * được khởi tạo * trong câu trả lời của tôi thực sự nên * định nghĩa * –

3

Tôi nghĩ rằng biến xác định xảy ra ở giai đoạn phân tích cú pháp, không phải thời điểm thực thi. Vì vậy, khi nó đánh giá dòng, nó phân tích toàn bộ điều và biến được xác định, nhưng chưa được gán.

+0

* Chính xác *. Đây là câu trả lời đúng. Biến được định nghĩa *, vì các biến được định nghĩa khi có một phép gán trong mã. Nhưng nó không * được khởi tạo hoặc gán, bởi vì nhiệm vụ không bao giờ được thực hiện. Do đó, nó đánh giá thành 'nil' vì đó là những biến chưa được khởi tạo được đánh giá trong Ruby. –

2

Khi trình phân tích cú pháp phát hiện ra một biến, nó sẽ tự động hợp lệ trong ngữ cảnh được xác định. Tự đánh giá rr không hợp lệ. Đánh giá rr=20 là đủ để tạo ra một định nghĩa ngay cả khi việc gán giá trị không bao giờ xảy ra.

Đây là điều không thể tránh khỏi về cách Ruby cố gắng phân biệt giữa các biến và các cuộc gọi phương thức. Nó không hoàn hảo nhưng thường hoạt động tốt nhất.

4

Như @DOC cho biết, &&|| được gọi là short circuited toán tử có điều kiện.

In case of ||, if the left part of || expression returns true, the right part won't be executed. Điều đó có nghĩa là phần bên phải sẽ chỉ được thực thi nếu phần bên trái của biểu tượng || trả về sai.

In case of &&, right part of the & & expression will be executed only if left part of && returns true.

Trong kịch bản cho (a=10) || (rr=20), rr = 20 sẽ không được thực hiện kể từ khi biểu ruby ​​a=10 lợi nhuận true. Lưu ý rằng trong biểu thức gán ruby ​​trả về true trừ nil and false.

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