2012-05-20 9 views
6

Posso richiedere il metodo nella classe Predef di Scala con una stringa come secondo argomento, ad es.Perchè Scala richiede che il metodo in Predef consenta una stringa come argomento?

In primo luogo un pensiero il metodo require è sovraccaricato per parametri diversi come secondo argomento. Ma non è. La firma del metodo require (Scala 2.9.1) è:

require(requirement: Boolean, message: ⇒ Any): Unit 

Perché la chiamata al metodo di cui sopra è possibile?

+2

Cosa c'è che non va nella definizione? '" foo "==" bar "' è un valore 'Boolean' e un' String' è conforme a 'Any' (come fa _any_ type). – Tharabas

+0

La domanda è, perché una stringa è un tipo valido per il secondo argomento mentre le firme dicono che deve essere una funzione 'message: => Any' –

risposta

21

Non capisco completamente la domanda, ma qui c'è un po 'di spiegazione. require ha una versione sovraccarico in Predef:

def require(requirement: Boolean) //... 
def require(requirement: Boolean, message: => Any) //... 

Il secondo è un po 'di confusione a causa message: => Any tipo. Probabilmente sarebbe più facile se si trattava semplicemente:

def require(requirement: Boolean, message: Any) //... 

Il secondo parametro è, naturalmente, un messaggio che è supponiamo di essere allegata al messaggio di errore se le affermazioni non sono soddisfatti. Si potrebbe immaginare message dovrebbe essere di tipo String ma con Any si può semplicemente scrivere:

require(x == 4, x) 

che aggiungerà valore reale della x (di tipo Int) in un messaggio di errore se non è uguale a 4. Ecco perché è stato scelto Any - per consentire un valore arbitrario.

Ma per quanto riguarda la parte : =>? Si chiama chiama per nome e in pratica significa: valuta questo parametro quando si accede a. Immaginate il seguente frammento:

require(list.isEmpty, list.size) 

In questo caso si vuole essere sicuri che il list è vuoto - e se non lo è, aggiungere il list dimensioni reali al messaggio di errore. Tuttavia, con la normale convenzione di chiamata, la parte list.size deve essere valutata prima del, il metodo viene chiamato, il che potrebbe essere uno spreco.Con chiama per nome la convenzione list.size viene valutata solo la prima volta che viene utilizzata, quando il messaggio di errore è costruttore (se necessario).

+0

Questo ha aiutato molto, grazie. –

+0

@Tomasz - Ho intenzione di modificare la risposta per rimuovere la parola "lazily" dalla descrizione di call-by-name. Penso che questo sia fuorviante. Esiste una netta differenza tra lazy (valutare una volta) e call-by-name (valutare ogni accesso). –

+0

@oxbow_lakes: nessun problema, capisco che possa essere confuso con la parola chiave 'pigro'. Grazie! –

3

Il metodo require esisteva in Predef prima che scala avesse i parametri predefiniti (introdotto in 2.8), quindi l'overloading era l'unica opzione se si desiderava il comportamento predefinito per un determinato parametro. Come indicato dal messaggio, il secondo argomento può essere qualsiasi cosa, che viene poi utilizzato come message (chiamando il suo metodo toString) del gettato IllegalArgumentException, (se si getta - vale a dire se il requisito non riesce).

Si noti che l'argomento è, in effetti, una chiamata per nome; vale a dire, è dichiarato come => Any, il che significa che sarà solo essere valutato se il requisito non riesce.

Questo comporta una penalizzazione delle prestazioni sotto forma di creazione di un oggetto, ma può essere utile nel caso in cui la costruzione del messaggio sia costosa (forse richiede un O (n) accesso a una struttura dati).

-1

La risposta è abbastanza semplice: Si prevede che il secondo argomento di

require(boolean: Boolean, message: => Any): Unit 

essere un funzione a Qualsiasi e chiedere perché un String opere, anche se non è un funzione.

scomposizione a questo: un fisso String non è altro che una funzione che

  1. non prende alcun argomento
  2. non richiede il () parentesi di essere chiamato
  3. produce lo stesso risultato in ogni chiamata

In effetti le seguenti due istruzioni sono equivalenti in Scala:

def x: String = "ABC" // const value, even though 'def' implies a function 
val x: String = "ABC" 

così si potrebbe dire che il => Any è soddisfatta da un String.

+0

Questo ha aiutato molto, grazie. –

2

La domanda è, perché una stringa è di tipo valido per il secondo argomento mentre le firme dice che deve essere una funzione message: => Any.

La firma non lo dice. La firma dice che il secondo argomento è di tipo Any e che questo parametro è passato al nome.

Il "dal nome" viene indicato dal prefisso => simbolo che fa non funzione medio - una funzione viene sempre indicato come parametri di input =>risultato tipo, con Function0 essendo () => type.

Cercare i parametri "in base al valore" e "in base al nome".

Problemi correlati