2012-06-05 37 views
7

Để đưa ra một bối cảnh nhỏ xung quanh cách tôi hiểu vấn đề.Tại sao toán tử splat/unary thay đổi giá trị được gán khi p được gọi trước * a = ""?

Sử dụng splat thu thập trên một chuỗi gửi: to_a hay: to_ary để String

class String 
    def method_missing method, *args, &block 
    p method #=> :to_ary 
    p args #=> [] 
    p block #=> nil 
    end 
end 

*b = "b" 

Vì vậy, tôi đã suy nghĩ rằng xác định lại: Phương pháp to_ary sẽ là những gì tôi sau đó.

class String 
    def to_ary 
    ["to_a"] 
    end 
end 

p *a = "a" #=> "a" 
p a  #=> "a" 

*b = "b" 
p b  #=> ["to_a"] 

Hiện tại điều này khiến tôi không thể kết thúc.

In kết quả từ * a = "a" thay đổi giá trị được gán cho?

Để chứng minh thêm

class String 
    def to_ary 
    [self.upcase!] 
    end 
end 

p *a = "a" #=> "a" 
p a  #=> "a" 

*b = "b" 
p b  #=> ["B"] 

Trả lời

9

Câu hỏi rất thú vị! Ruby có biểu hiện này:

p *a = "a" 

và chuyển nó thành một cái gì đó như thế này:

temp = (a = "a") 
p *temp 

Vì vậy, điều đầu tiên mà xảy ra là a được giao cho "a", và sau đó là kết quả của nhiệm vụ biểu thức là "a" được chia nhỏ và gửi đến p. Vì hành vi mặc định của p khi gửi nhiều đối số chỉ để lặp lại và in từng đối số, bạn chỉ thấy "a" xuất hiện.

Tóm lại, nó tuân theo thứ tự đánh giá "gán sau đó". Vì vậy, a được gán cho "a" trước khi chuỗi được chia nhỏ.

Khi bạn không có một cuộc gọi chức năng tuy nhiên, nó được xem như là một cái gì đó như thế này:

# *a = "a" gets interpreted as: 
temp = "a" 
a = *temp 

này sau một "splat sau đó gán" tự đánh giá. Vì vậy, a được chỉ định sau chuỗi được chia nhỏ.

Bạn có thể nhìn thấy những gì đang được nhận bởi một hàm bằng cách như thế này:

def foo *args 
    puts args.inspect 
end 

foo *a = "a" # outputs ["a"] 
a    # outputs "a" 

Hy vọng điều này đã xóa bỏ những gì đang xảy ra!

Nói tóm lại (nhờ Mark Reed):

p *a = "a" # interpreted as: p(*(a = "a")) 
*a = "a"  # interpreted as: a = *("a") 
+1

Đúng vậy. Đó là tất cả về sự ưu tiên. 'p * a =" a "' có nghĩa là 'p (* (a =" a "))', không phải 'p (* a =" a ")'. –

+0

Yup chính xác, tôi đã chỉnh sửa để thêm một chút ghi chú làm rõ. – robbrit

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