|| = là thành ngữ Ruby phổ biến: nó chỉ gán giá trị nếu nó chưa được đặt. Hiệu quả là giống như mã như
if some_variable == nil
some_variable = some_value
end
hoặc
some_variable= some_value unless some_variable
===, khi không ghi đè, so sánh hai đối tượng cho sắc. Trong trường hợp của Hash === args.last
, Hash (là đối tượng của loại Class) đang kiểm tra xem nó có khớp với lớp của mục cuối cùng trong mảng args hay không. Mã đang sử dụng thực tế rõ ràng là việc triển khai Class # === buộc kiểm tra trên lớp của đối tượng được so sánh.
Nó không làm việc theo cách khác xung quanh, ví dụ:
a = [{}]
Hash === a.last #=> true
a.last === Hash #=> false
Những lập luận trailing đến một phương pháp có thể được cung cấp như nội dung của một băm mà không cần phải cung cấp {}
Vì vậy, bạn có thể thực hiện điều này:
def hello(arg1, arg2, arg3)
puts [arg1.class, arg2.class, arg3.class].join(',')
end
hello 1,2,3 #=> Fixnum,Fixnum,Fixnum
hello :a, "b", :c => 1, :d => 99 #=> Symbol,String,Hash
Nó thường được sử dụng để cung cấp danh sách các thông số tùy chọn có độ dài thay đổi cho hàm.
Bạn có chắc là bạn đã phiên mã chính xác mã btw không? Để có được một mảng các đối số, bạn thường sẽ thêm một * vào đối số như được khai báo, nếu không args sẽ phải là đầu vào như là một mảng, thay vì sẽ đánh bại đối tượng.
def add_spec_path_to(*args) # now args is an array
args << {} unless Hash === args.last # if trailing arguments cannot be
# interpreted as a Hash, add an empty
# Hash here so that following code will
# not fail
args.last[:spec_path] ||= caller(0)[2] # Set the spec_path option if it's not
# already set
end
EDIT: Mở rộng hơn nữa về điều * args, hãy thử này:
def x(*args)
puts args.join(',')
puts args.map{|a| a.class }.join(',')
end
x 1,2,:a=>5,:b=>6
1,2,a5b6
Fixnum,Fixnum,Hash
... sử dụng * args gây args sẽ được trình lên các phương pháp như một mảng. Nếu tôi không sử dụng *, như thế này, ví dụ:
def y(args)
puts args.join(',')
puts args.map{|a| a.class }.join(',')
end
... sau đó args phải là một mảng trước khi tôi gọi phương thức, hoặc tôi sẽ nhận được một "ArgumentError: sai số đối số "cho bất cứ điều gì nhưng một điều đã trôi qua. Vì vậy, nó phải giống như thế này:
y [1,2,{:c=>3,:d=>4}]
... với Hash được tạo một cách rõ ràng với {}. Và nó xấu xí.
Tất cả các thử nghiệm trên đã được thử với MRI 1.8.6, btw.
Không, đi qua trong một mảng có ý nghĩa, vì args không được trả lại, vì vậy nếu không một Hash nối sẽ bị mất. – rampion
Tôi không chắc chắn tôi hiểu: bạn sẽ gọi phương thức như thế này: some_method ([arg1, arg2, arg3], options_hash)? Thật kinh khủng: hãy xem câu trả lời đã chỉnh sửa ở trên ... –
Giải thích tuyệt vời, Mike. –