2010-12-30 20 views
5

probabilmente chiesto già, ma non sono riuscito a trovarlo .. Qui ci sono 2 situazione comune (per me mentre le rotaie di programmazione ..) che sono frustranti di scrivere in Ruby:rubino zucchero sintattico: si tratta di Nils

"a string".match(/abc(.+)abc/)[1] 

in questo caso viene visualizzato un errore perché la stringa non corrisponde, pertanto l'operatore [] viene chiamato su zero. Quello che mi piacerebbe trovare un posto più bello è un'alternativa al seguente:

temp="a string".match(/abc(.+)abc/); temp.nil? ? nil : temp[1] 

in breve, se non corrisponde semplicemente restituire nil senza l'errore

La seconda situazione è questa:

var = something.very.long.and.tedious.to.write 
var = something.other if var.nil? 

in questo caso voglio assegnare qualcosa da VAR solo se non è pari a zero, nel caso in cui si tratta di nulla io assegnare something.other ..

Qualsiasi suggerimento? Grazie!

+0

Ok Sono molto stanco Mi scuso per la seconda domanda che era stupido (sì, è un semplice O ..), il primo rimane interessante anche se .. – luca

+0

realtà anche la seconda era interessante. In breve ho sbagliato, perché ho dimenticato la precedenza dell'operatore 'o'. L'uso improprio di 'or' è un passo falso piuttosto comune e vale la pena evidenziare. –

+0

Questo è molto simile a questa domanda: http://stackoverflow.com/questions/4371716/looking-for-a-good-way-to-avoid-hash-conditionals-in-ruby/ – mpd

risposta

0

Per la prima mi consiglia ick s' maybe (equivalente a andand)

"a string".match(/abc(.+)abc/).maybe[1] 

io non sono sicuro di aver capito la seconda, si vuole questo?

var = something.very.long.and.tedious.to.write || something.other 
3

in Ruby on Rails è necessario il metodo try disponibile su qualsiasi oggetto. In base all'API:

Invoca il metodo identificato dal metodo del simbolo, passandogli eventuali argomenti e/o il blocco specificato, proprio come fa il normale oggetto Ruby # send.

A differenza di questo metodo, tuttavia, un'eccezione NoMethodError non verrà sollevata e verrà restituito nil se l'oggetto di ricezione è un oggetto nil o NilClass.

Così, per la prima domanda si può fare questo:

"a string".match(/abc(.+)abc/).try(:[], 1) 

E sarà o dare [1] o nullo senza errori.

+0

Questo codice è difficile da leggere e funziona solo se è presente ActiveSupport. –

+0

La domanda era originariamente contrassegnata con ruby-on-rails prima di essere modificata, quindi ho presentato la soluzione più pulita incorporata in Ruby on Rails. E difficile da leggere? La maggior parte dei programmatori di Ruby sono abituati a come funziona il metodo "invia", e questo è appena meno leggibile della risposta accettata, usando la libreria Ick esterna. Potresti anche avere un downvote, perché "funziona solo se Ick è presente". Nel complesso, un downvote ingiustificato. – icecream

+0

Considerando che la seconda metà della risposta di tokland è corretta al 100%, questo * sarebbe * un ingiustificato downvote. Mentre la domanda originale è stata contrassegnata da ruby-on-rails, nulla sulla domanda ha nulla a che fare con le guide. Le dipendenze non necessarie sono tra gli errori più odiosi che i programmatori di Ruby fanno. Ma nel tuo caso, non hai semplicemente aggiunto una dipendenza non necessaria. La tua implementazione introduce anche un'invio-invio non necessario e lento e, come affermato in precedenza, è difficile da leggere. Non lascerei mai vivere il codice come questo attraverso la revisione del codice. Quindi sì, giù voto. –

0
"a string".match(/foo(bar)/).to_a[1] 

NilClass#to_a restituisce un array vuoto, e l'indicizzazione di fuori di esso dà nil valori.

alternativa (cosa faccio) è possibile splat le partite:

_, some, more = "a string".match(/foo(bar)(jim)/).to_a 
+1

Ewww. Per favore, non farlo. –

+0

@BobAman Ti piacerebbe elaborare? A quale parte obietti? L'uso della variabile di sottolineatura per ignorare silenziosamente l'intera corrispondenza nei casi in cui tutto ciò che ti interessa sono le sottotitoli? Non aiuta nessuno a parlare di down, dice "Ewww", e va via. – Phrogz

+1

Mi riferisco all'utilizzo del metodo 'NilClass # to_a' oltre all'indicizzazione out-of-range. È divertente come scrivere con le anatre, sei troppo intelligente qui. Intelligente è cattivo E lo splatting delle partite è comunque più leggibile. Lo farei sempre e comunque solo se assegnassi più gruppi di cattura contemporaneamente. Altrimenti dovresti usare il metodo 'String # []' dato che è ciò per cui è destinato. –

3
"a string"[/abc(.+)abc/, 1] 
# => nil 
"abc123abc"[/abc(.+)abc/, 1] 
# => "123" 

E:

var = something.very.long.and.tedious.to.write || something.other 

prega di notare che or ha un diverso precedenza degli operatori rispetto || e || dovrebbe essere preferito per questo tipo di utilizzo. L'operatore or è per l'utilizzo del controllo di flusso, ad esempio ARGV[0] or abort('Missing parameter').

3

Dimentica questo atavismo Python!

"a string"[/abc(.+)abc/,1] # => nil 
+2

+1 per usare la parola "atavismo" in un contesto correlato alla programmazione. – zetetic

+0

L'unico scopo di 'match' che conosco è http://stackoverflow.com/questions/4472848/is-there-a-shorthand-for-assigning-from-1-n-after-matching-in-ruby/4472857 # 4472857 – Nakilon

+0

In realtà, un po 'di tempo fa ho scritto un meccanismo di routing che digitava "duck" su una coppia di metodi 'match' /' captures'. Ciò mi ha permesso di introdurre banalmente la corrispondenza dei template URI con il sistema di routing. In realtà ho trovato molti vantaggi nell'avere un modo meno idiomatico di eseguire un'espressione regolare. Tendono solo ad essere cose che scrivi nel contesto della meta-programmazione o durante la creazione di DSL. –

0

Per la prima domanda, penso che la risposta di Bob sia buona.

Per la seconda domanda,

var = something.very.long.and.tedious.to.write.instance_eval{nil? ? something.other : self} 
Problemi correlati