Toán tử (unary) * làm gì trong mã Ruby này?


174

Cho mã Ruby

line = "first_name=mickey;last_name=mouse;country=usa" 
record = Hash[*line.split(/=|;/)] 

Tôi hiểu mọi thứ trong dòng thứ hai ngoài *toán tử - nó đang làm gì và tài liệu cho việc này ở đâu? (như bạn có thể đoán, việc tìm kiếm trường hợp này thật khó khăn ...)

Câu trả lời:


271

Đây *là toán tử splat .

Nó mở rộng Arraymột danh sách các đối số, trong trường hợp này là một danh sách các đối số cho Hash.[]phương thức. (Nói chính xác hơn, nó mở rộng bất kỳ đối tượng nào phản hồi to_ary/ to_ahoặc to_atrong Ruby 1.9.)

Để minh họa, hai câu lệnh sau bằng nhau:

method arg1, arg2, arg3
method *[arg1, arg2, arg3]

Nó cũng có thể được sử dụng trong một ngữ cảnh khác, để bắt tất cả các đối số phương thức còn lại trong một định nghĩa phương thức. Trong trường hợp đó, nó không mở rộng, nhưng kết hợp:

def method2(*args)  # args will hold Array of all arguments
end

Một số thông tin chi tiết ở đây .


36
Nói chung, khi được sử dụng như trong tình huống giống như LHS (bất cứ khi nào bạn gọi nó trên một giá trị), splat sẽ chia một mảng thành các giá trị riêng biệt và khi được sử dụng trong tình huống giống như RHS (bất cứ khi nào bạn sử dụng nó trên một số biến không xác định trước đó), nó nhóm các giá trị riêng biệt thành một mảng. Vì vậy, a,b,*c = d,e,f,*gđặt a = d, b = e và c = [f, g0, g1, g2, ..., gn], trong đó g = [g0, g1, g2, ..., gn]
lan man

2
Để hoàn thiện, toán tử splat biến một mảng thành một danh sách trống theo thuật ngữ được sử dụng trong 'The Ruby Grounded Rubyist' của David A. Black
David Burrows

12
@rampion: Nhận xét tuyệt vời, bạn chỉ cần trộn LHS và RHS. Đó là cách khác.
ThomasH

46

Toán tử splat giải nén một mảng được truyền cho một hàm để mỗi phần tử được gửi đến hàm dưới dạng một tham số riêng lẻ.

Một ví dụ đơn giản:

>> def func(a, b, c)
>>   puts a, b, c
>> end
=> nil

>> func(1, 2, 3)  #we can call func with three parameters
1
2
3
=> nil

>> list = [1, 2, 3]
=> [1, 2, 3]

>> func(list) #We CAN'T call func with an array, even though it has three objects
ArgumentError: wrong number of arguments (1 for 3)
    from (irb):12:in 'func'
    from (irb):12

>> func(*list) #But we CAN call func with an unpacked array.
1
2
3
=> nil

Đó là nó!


6

Như mọi người đề cập, đó là một "splat". Tìm kiếm cú pháp Ruby là không thể, và tôi đã hỏi điều này trong các câu hỏi khác. Câu trả lời cho phần đó của câu hỏi là bạn tìm kiếm trên

asterisk in ruby syntax

trong Google. Google ở ​​đó cho bạn, chỉ cần đặt những gì bạn nhìn thấy thành từ.

Anyhoo, giống như rất nhiều mã Ruby, mã đó khá dày đặc. Các

line.split(/=|;/)

làm cho một mảng các phần tử SIX , first_name, mickey, last_name, mouse, country, usa. Sau đó, splat được sử dụng để biến nó thành Hash. Bây giờ người Ruby luôn gửi cho bạn xem phương thức Splat, vì mọi thứ đều được phơi bày trong Ruby. Tôi không biết nó ở đâu, nhưng một khi bạn đã có nó, bạn sẽ thấy rằng nó chạy forqua mảng và xây dựng hàm băm.

Bạn sẽ tìm mã trong tài liệu cốt lõi . Nếu bạn không thể tìm thấy nó (tôi không thể), bạn sẽ cố gắng viết một số mã như thế này (hoạt động, nhưng KHÔNG phải là mã giống như Ruby):

line = "first_name=mickey;last_name=mouse;country=usa"
presplat = line.split(/=|;/)
splat = Hash.new
for i in (0..presplat.length-1)
    splat[presplat[i]] = presplat[i+1] if i%2==0
end

puts splat["first_name"]

và sau đó, băng đảng Ruby sẽ có thể cho bạn biết lý do tại sao mã của bạn là ngớ ngẩn, xấu hoặc chỉ đơn giản là sai.

Nếu bạn đã đọc đến đây, hãy đọc tài liệu Hash để khởi tạo.

Về cơ bản, hàm băm được khởi tạo với một số đối số sẽ tạo chúng dưới dạng cặp giá trị khóa:

Hash["a", 100, "b", 200] #=> {"a"=>100, "b"=>200}

Vì vậy, trong ví dụ của bạn, điều này sẽ dẫn đến Hash sau:

{"first_name"=>"mickey", "last_name"=>"mouse", "county"=>"usa"}
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.