Refinements là một bổ sung thử nghiệm cho v2.0, sau đó được sửa đổi và được tạo vĩnh viễn trong phiên bản v2.1. Nó cung cấp một cách để tránh "khỉ vá" bằng cách cung cấp "một cách để mở rộng một lớp học tại địa phương".Sử dụng sàng lọc theo thứ bậc
Tôi đã cố gắng áp dụng Refinements
-this recent question mà tôi sẽ đơn giản hóa như sau:
a = [[1, "a"],
[2, "b"],
[3, "c"],
[4, "d"]]
b = [[1, "AA"],
[2, "B"],
[3, "C"],
[5, "D"]]
Yếu tố tại offset i
trong a
phù hợp với phần tử ở bù đắp i
trong b
nếu:
a[i].first == b[i].first
và
a[i].last.downcase == b[i].last.downcase
Nói cách khác, sự phù hợp của các chuỗi là độc lập với trường hợp.
Vấn đề là xác định số phần tử của a
khớp với phần tử tương ứng là b
. Chúng tôi thấy rằng câu trả lời là hai, các phần tử ở các số offset 1
và 2
.
Một cách để làm điều này là khỉ-vá String#==:
class String
alias :dbl_eql :==
def ==(other)
downcase.dbl_eql(other.downcase)
end
end
a.zip(b).count { |ae,be| ae.zip(be).all? { |aee,bee| aee==bee } }
#=> 2
hoặc thay vì sử dụng Refinements
:
module M
refine String do
alias :dbl_eql :==
def ==(other)
downcase.dbl_eql(other.downcase)
end
end
end
'a' == 'A'
#=> false (as expected)
a.zip(b).count { |ae,be| ae.zip(be).all? { |aee,bee| aee==bee } }
#=> 0 (as expected)
using M
'a' == 'A'
#=> true
a.zip(b).count { |ae,be| ae.zip(be).all? { |aee,bee| aee==bee } }
#=> 2
Tuy nhiên, tôi muốn sử dụng Refinements
như thế này:
using M
a.zip(b).count { |ae,be| ae == be }
#=> 0
nhưng, như bạn thấy, điều đó đưa ra câu trả lời sai. Đó là bởi vì tôi đang gọi Array#== và tinh chỉnh không áp dụng trong phạm vi Array
.
tôi có thể làm điều này:
module N
refine Array do
def ==(other)
zip(other).all? do |ae,be|
case ae
when String
ae.downcase==be.downcase
else
ae==be
end
end
end
end
end
using N
a.zip(b).count { |ae,be| ae == be }
#=> 2
nhưng đó không phải là những gì tôi muốn. Tôi muốn làm một cái gì đó như thế này:
module N
refine Array do
using M
end
end
using N
a.zip(b).count { |ae,be| ae == be }
#=> 0
nhưng rõ ràng là không hoạt động.
Câu hỏi của tôi: có cách nào để tinh chỉnh String
để sử dụng trong Array
, sau đó tinh chỉnh Array
để sử dụng trong phương pháp của tôi không?
Tuyệt vời! Một chi tiết: bạn có thể cân nhắc việc thay thế '! Self.zip (khác) .map {| x, y | x == y} .bao gồm? false' với 'zip (khác) .all? {| x, y | x == y} '. (Nhớ lại rằng 'self' là bộ thu mặc định.) –
Ah, vâng, cảm ơn — Tôi đã có thói quen xấu khi sử dụng' self' ở mọi nơi có thể áp dụng. Điều này sẽ giúp tôi nhớ xem có sử dụng hay không. Nó trông đẹp hơn/dễ đọc hơn ở đây mà không có 'self' và sử dụng' tất cả? '. –
Nhiều người Ruby sử dụng 'self' khi không cần thiết vì họ tin rằng sự thiếu sót của nó có thể gây nhầm lẫn cho người đọc. Tôi không ở trong trại đó, nhưng tôi không thể nói họ sai. –