Refinements è un'aggiunta sperimentale alla v2.0, quindi modificata e resa permanente nella v2.1. Fornisce un modo per evitare la "patch di scimmia" fornendo "un modo per estendere una classe localmente".Utilizzo gerarchico dei perfezionamenti
ho tentato di applicare Refinements
-this recent question cui vi semplificare così:
a = [[1, "a"],
[2, "b"],
[3, "c"],
[4, "d"]]
b = [[1, "AA"],
[2, "B"],
[3, "C"],
[5, "D"]]
L'elemento all'offset i
nel a
corrisponde l'elemento all'offset i
in b
se:
a[i].first == b[i].first
e
a[i].last.downcase == b[i].last.downcase
In altre parole, la corrispondenza delle stringhe è indipendente dal caso.
Il problema è determinare il numero di elementi di a
corrispondenti all'elemento corrispondente di b
. Vediamo che la risposta è due, gli elementi a offset 1
e 2
.
Un modo per farlo è quello di scimmia-patch 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
o utilizzare invece 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
Tuttavia, vorrei utilizzare Refinements
come questo:
using M
a.zip(b).count { |ae,be| ae == be }
#=> 0
ma, come vedi, dà la risposta sbagliata. Questo perché sto invocando Array#== e il perfezionamento non si applica all'interno di Array
.
avrei potuto fare questo:
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
ma non è questo quello che voglio. Voglio fare qualcosa di simile:
module N
refine Array do
using M
end
end
using N
a.zip(b).count { |ae,be| ae == be }
#=> 0
ma chiaramente quello non funziona.
La mia domanda: c'è un modo per perfezionare String
per l'uso in Array
, quindi perfezionare Array
per l'utilizzo nel mio metodo?
È grandioso! Un dettaglio: potresti prendere in considerazione la sostituzione di '! Self.zip (altro) .map {| x, y | x == y} .includere? false' con 'zip (altro) .tutto? {| x, y | x == y} '. (Ricorda che 'self' è il ricevitore predefinito.) –
Ah, sì, grazie-ho acquisito una brutta abitudine di usare' self' ovunque possa applicarsi. Questo mi aiuterà a ricordare di considerare se ha senso usare. Sembra molto più bello/più leggibile qui senza "sé" e usando "tutto?". –
Molti Rubyists usano 'self' quando non è necessario perché ritengono che la sua omissione possa confondere il lettore. Non sono in quel campo, ma non posso dire che si sbagliano. –