|| = è un idioma di Ruby comune: assegna il valore solo se non è già impostato. L'effetto è lo stesso codice come
if some_variable == nil
some_variable = some_value
end
o
some_variable= some_value unless some_variable
===, quando non ignorata, confronta due oggetti per l'identità. Nel caso di Hash === args.last
, Hash (che è un oggetto di tipo Classe) verifica se corrisponde alla classe dell'ultimo elemento nella matrice di args. Il codice sta facendo uso del fatto evidente che l'implementazione di Class # === impone un controllo sulla classe dell'oggetto confrontato.
Non funziona viceversa, ad esempio:
a = [{}]
Hash === a.last #=> true
a.last === Hash #=> false
Gli argomenti trascinamento ad un metodo possono essere forniti come il contenuto di un hash senza la necessità di fornire il {}
Così puoi fare questo:
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
Viene spesso utilizzato per fornire alla funzione un elenco di parametri opzionali di lunghezza variabile.
Sei sicuro di aver trascritto il codice originale con precisione, btw? Per ottenere un array di argomenti, normalmente si aggiunge un * all'argomento come dichiarato, altrimenti gli argomenti dovrebbero essere inseriti come una matrice, piuttosto che sconfiggere l'oggetto.
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: Espandendo ulteriormente sulla cosa * args, provate questo:
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
... usando args * provoca args da presentare al metodo come un array. Se io non uso il *, in questo modo, per esempio:
def y(args)
puts args.join(',')
puts args.map{|a| a.class }.join(',')
end
... poi args deve essere un array prima che io chiamo il metodo, o vado a prendere un "ArgumentError: numero sbagliato di argomenti "per tutto tranne una cosa passata. Quindi deve apparire così:
y [1,2,{:c=>3,:d=>4}]
... con l'hash creato in modo esplicito con {}. Ed è brutto.
Tutto quanto sopra testato con risonanza magnetica 1.8.6, btw.
n, passando in un array senso, poiché args non viene restituito, così altrimenti un Hash allegata sarebbe perso. – rampion
Non sono sicuro di aver capito: chiameresti il metodo in questo modo: some_method ([arg1, arg2, arg3], options_hash)? È orribile: vedi la risposta sopra ... –
Grande spiegazione, Mike. –