2012-05-10 15 views
40

Ad esempio, ho trovato il nome del metodo bundler? nel seguente snippet e non so se il carattere ? è una parola chiave specializzata o solo una parte del nome del metodo.Quali sono le restrizioni per i nomi dei metodi in Ruby?

# This is a predicate useful for the doc:guides task of applications. 
def bundler? 
    # Note that rake sets the cwd to the one that contains the Rakefile 
    # being executed. 
    File.exists?('Gemfile') 
end 

risposta

72

nomi di metodo in Ruby possono contenere maiuscole e minuscole, numeri, sottolinea _ e la punteggiatura segni !, ?, =.

Un nome di metodo non può iniziare con un numero e i caratteri !, ? e = possono essere visualizzati solo alla fine.

I caratteri non ASCII possono essere utilizzati in un nome di metodo, ma questo può portare a situazioni molto confuse e non dovrebbe essere una pratica comune.

È buona prassi, sebbene non sia obbligatorio, avviare il nome del metodo con un carattere minuscolo, poiché i nomi che iniziano con lettere maiuscole sono costanti in Ruby. E 'ancora possibile utilizzare un nome costante per un metodo, ma non sarà in grado di invocarlo senza parentesi, perché l'interpeter cercherà-up per il nome come una costante:

def Capital 
    nil 
end 

Capital # NameError: uninitialized constant Capital 
Capital() # => nil 

Alcuni molto ampiamente e costantemente utilizzato convenzioni quando definiscono i nomi dei metodi sono:

  1. nomi di metodo sono completamente in basso e minuscole, con sottolineature _ come separatori per le parole nel nome (ad esempio Math::sqrt, Array#each_index, ...).

  2. predicati hanno un punto interrogativo ? come ultimo carattere (ad esempio Array#empty?, Hash#has_key?, ...). Mentre i predicati di solito restituiscono valori booleani, questo non è sempre il caso: questi metodi devono solo restituire nil o false se il predicato restituisce false, qualsiasi altro valore in caso contrario (ad es. File::size? restituisce nil se il file non esiste, la dimensione del file come Integer in caso contrario).

  3. I metodi che modificano lo stato dell'oggetto su cui sono stati richiamati o che presentano un comportamento anomalo hanno un punto esclamativo ! come ultimo carattere; questi metodi vengono talvolta chiamati mutanti perché di solito sono versioni distruttive o sul posto di altri metodi (ad esempio Array#sort!, Array#slice!, ...).

  4. Setter hanno un segno di uguale = come ultimo carattere (ad esempio Array#[]=, ...); l'interpeter rubino offre zucchero sintattico per invocazione di metodi setter:

    a = [4, 5, 6] 
    a[0] = 3 # Shorthand for a.[]=(0, 3) 
    

rubino consente inoltre di definire operatori utilizzando il simbolo dell'operatore come il nome del metodo:

╔═══════════════════════════╦═════════════════════════════════════════════╦═══════╗ 
║ Operators (by precedence) ║     Operations     ║ Arity ║ 
╠═══════════════════════════╬═════════════════════════════════════════════╬═══════╣ 
║ ! ~ +      ║ Boolean NOT, bitwise complement, unary plus ║  1 ║ 
║       ║ (define with method name [email protected], Ruby 1.9+)  ║  ║ 
║       ║            ║  ║ 
║ **      ║ Exponentiation        ║  2 ║ 
║       ║            ║  ║ 
║ -       ║ Unary minus (define with method name [email protected]) ║  1 ║ 
║       ║            ║  ║ 
║ */%      ║ Multiplication, division, modulo   ║  2 ║ 
║       ║            ║  ║ 
║ + -      ║ Addition, subtraction      ║  2 ║ 
║       ║            ║  ║ 
║ << >>      ║ Bitwise shift        ║  2 ║ 
║       ║            ║  ║ 
║ &       ║ Bitwise AND         ║  2 ║ 
║       ║            ║  ║ 
║ |^      ║ Bitwise OR, Bitwise XOR      ║  2 ║ 
║       ║            ║  ║ 
║ < <= => >     ║ Ordering         ║  2 ║ 
║       ║            ║  ║ 
║ == === != =~ !~ <=>  ║ Equality, pattern matching, comparison  ║  2 ║ 
╚═══════════════════════════╩═════════════════════════════════════════════╩═══════╝ 

metodi operatore unario sono non ha passato argomenti; i metodi dell'operatore binario sono passati a un argomento e operano su di esso e su self.

È importante attenersi rigorosamente all'arità degli operatori; mentre è possibile definire metodi operatore con un'arità diversa (ad esempio un metodo + che richiede due argomenti), Ruby non consente di chiamare il metodo con la sintassi dell'operatore (funzionerebbe comunque con la sintassi del punto).

È buona prassi aderire il più possibile alla semantica originale degli operatori: dovrebbe essere intuitivo per qualcuno che conosce il significato originale dell'operatore come funziona con le classi definite dall'utente.

La lingua offre anche zucchero sintattico per lo speciale non-operatore, [] metodo che viene normalmente utilizzato per accedere ai valori di array e hash. Il metodo [] può essere definito con arbitrarietà.

Per ogni operatore binario nella tabella, tranne ordinazione, uguaglianza, confronto e pattern matching, rubino offre anche abbreviata per assegnazione abbreviato (ad esempio x += y espande a x = x + y); non puoi definirli come metodi, ma puoi modificare il loro comportamento definendo gli operatori su cui sono basati.

Nessuno di questi caratteri può essere utilizzato all'interno di nomi di metodi normali (ad esempio do&print o start-up non sono nomi di metodi validi).

+1

Ottima risposta! Come una piccola nota: è consuetudine per i metodi predicati (con un '?') Restituire valori falsi ('nil' o' false') o truethy (tutto il resto), non necessari 'true' e' false'. Il valore restituito è inteso per essere usato nelle istruzioni 'if' dove si comporta come se fosse' true'and 'false' ma il valore di ritorno effettivo spesso non fa parte dell'interfaccia del metodo previsto, ma è solo proprietà truethy o falsey. –

+0

Grazie per il consiglio, ho modificato di conseguenza. –

+0

Ci sono anche alcuni caratteri che possono essere usati solo come l'intero nome del metodo, ovvero puoi definire metodi chiamati - + * **/(se stai sovraccaricando questi operatori) ma non un metodo chiamato foo + bar –

0

I caratteri consentiti sono: a-Z,, 0-9 finché non all'inizio, _, e ? (per le funzioni booleane) e ! (per le funzioni distruttive) e = (per setter).

2

I nomi dei metodi possono terminare con !, ? o =. Anche i caratteri di sottolineatura sono ammessi. Oltre a ciò ci sono diversi metodi che sembrano operatori (ad esempio +, *, >>, []) che è possibile definire per le proprie classi.

4

Ciò che gli altri dicono che è vero per il built-in di sintassi, ma sembra che ci sia alcuna restrizione di back-end su ciò che può essere utilizzato se si utilizzano metodi come define_method + send:

define_method(:'$% ^&') { 0 } 
define_method(:'你好') { 1 } 

send(:'$% ^&') == 0 or raise 
send(:'你好') == 1 or raise 

Questo fatto può essere utile: metodo ActiveSupport::Testing::Declarative.test per esempio Rails utilizza in modo da non fare conversioni complesse su:

test 'Some Controller#Method' do 

a un nome più sano, che possano entrare in conflitto con un altro test denominato:

test 'Some Controller_Method' do 

Questo è indicato sullo Testing Guide.

Curiosità: una cosa simile accade in Java, in cui il nome del metodo bytecode lascia il posto più scelta rispetto al linguaggio Java: Why does the JVM allow us to name a function starting with a digit in bytecode?

2

aggiungere una cosa: si può anche dire un oggetto per eseguire un metodo con senza nome a tutti e si tenta di richiamare un metodo chiamato call:

#!/usr/bin/env ruby 

class Foo 

=begin 
    def call(*args) 
    puts "received call with #{args.join(' ')}" 
    end 
=end 

    def method_missing(m, *args, &block) 
    puts "received method_missing on `#{m}(#{args.join(', ')})`" 
    end 

end 

f = Foo.new 
f.('hi')    # Not a syntax error! method_missing with m of :call 
f.send :'', 'hmm' # method_missing with m set to :'' 
f.send nil, 'bye' # raises an error 

non c'è in realtà alcun metodo denominato call definito su Object, ma c'è uno sul Method e Proc classi.

In alcune lingue () è un operatore per l'invocazione di funzione, e ciò sembra molto simile a ciò che sta accadendo qui.

Viene utilizzato ad es. in JBuilder Rails:

https://github.com/rails/jbuilder

è documentato nella pagina 196 del libro O'Reilly rubino:

Ruby 1.9 offre un ulteriore modo per richiamare un oggetto Proc; come alternativa alla parentesi quadre, è possibile usare le parentesi con prefisso un periodo:

z = f.(x,y) 

.() si presenta come una chiamata di metodo manca il nome del metodo. Questo non è un operatore che può essere definito, ma piuttosto è sintattico-zucchero che richiama il metodo call. Può essere utilizzato con qualsiasi oggetto che definisce un metodo call e non è limitato agli oggetti Proc.

Problemi correlati