2013-06-13 29 views
9

http://woss.name/2012/04/02/retrieving-bigdecimals-from-a-database-with-anorm-scala/Cosa significa la tilde (~) in questo esempio di Scala?

object Site { 
    val allFieldsParser = { 
    get[Pk[Long]]("sites.id") ~  // Help me parse this syntax 
    get[String]("sites.name") ~ 
    get[BigDecimal]("sites.latitude") ~ 
    get[BigDecimal]("sites.longitude") map { 
     case id ~ name ~ latitude ~ longitude => 
     Site(id, name, latitude, longitude) 
    } 
    } 

    def findAll(): Seq[Site] = { 
    DB.withConnection { implicit connection => 
     SQL("SELECT * FROM sites").as(Site.allFieldsParser *) 
    } 
    } 
} 
+2

Questa notazione era derivata dai combinatori di parser. Per favore, vedi http://stackoverflow.com/questions/6818390/understanding-the-tilde-in-scalas-parser-combinators In breve, potresti sostituire mentalmente '~' con '&', quindi tale struttura sembrerà un pattern (lo sai, come un pattern in regex). Stai definendo una rappresentazione di alto livello usando parti particolari (combinate in una struttura solida con ~ 's) e poi il parser succederà, e avrai una struttura secondo il tuo schema, o fallirà. Ad esempio, per abbinare l'espressione algebrica si potrebbe scrivere qualcosa come 'Numero ~ Operazione ~ Numero ...' –

+0

@ om-nom-nom Quindi, perché hai risposto nel commento? –

+1

@ DanielC.Sobral perché non sono sicuro che la domanda riguardi l'implementazione tecnica (che è stata già spiegata da gzm0) o di materiale semantico. –

risposta

21

Nel tuo esempio, ~ è utilizzato in due modi diversi per significare due cose diverse. Nella prima parte si dispone di

get[Pk[Long]]("sites.id") ~  // Help me parse this syntax 
get[String]("sites.name") ~ 
get[BigDecimal]("sites.latitude") ~ 

ecc Come è già stato sottolineato, questo è solo chiamata di metodo, è lo stesso che

get[Pk[Long]]("sites.id").~(get[String]("sites.name").~(... 

Potete guardare the definition of this method in the anorm source. Si tratta di un metodo su un RowParser[A] (un parser che analizza un A, che prende un RowParser[B] (un parser che analizza un B) e restituisce un parser che analizza un A ~ B. Questo A ~ B è un secondo significato per ~. Questo è ora non riferisce a un metodo, ma ad un case class defined in the same file here.

case class ~[+A, +B](_1: A, _2: B) 

Questo è solo un modo idiosincratico di riferirsi ad una classe ~[A,B]. a livello tipo, quando si dispone di un tipo di costruttore a due argomenti, è possibile utilizzare il nome di la classe in notazione infisso. Questo non è niente di speciale su ~, funzionerebbe con due costruttore di argomenti. Se avessi trait Foo[A,B] potresti riferirti a questo come A Foo B. Analogamente, in pattern matching, variabili a e b può essere vincolato utilizzando la sintassi a Foo b, che viene indicato come un pattern infissa Funzionamento in sezione 8.1.10 della language specification.

Nella seconda parte del tuo esempio si ha:

case id ~ name ~ latitude ~ longitude => 

Questo è il pattern matching nelle ~ caso clases che sono il risultato di eseguire il parsing hai costruito sopra. Quindi questo è davvero solo un modo più bello di scrivere:

case ~(~(~(id, name), latitude), longitude) => 
+0

Grazie per la risposta completa. – ripper234

5

In Scala

a ~ b 

significa

a.~(b) 

Così chiama il metodo ~ su a e dà b come argomento. Si noti inoltre che qualsiasi operatore che non termina con : è associato a sinistra.

Il tuo esempio potrebbe essere rivisitato:

get[Pk[Long]]("sites.id").~( // Help me parse this syntax 
get[String]("sites.name").~(
get[BigDecimal]("sites.latitude").~(
get[BigDecimal]("sites.longitude")))) map { 
    case id ~ name ~ latitude ~ longitude => 
    Site(id, name, latitude, longitude) 
} 
+1

Più in generale, "a qualunque b" significa "a.whatever (b)" (ad eccezione di alcune parole chiave, operatori primitivi e l'indicatore associativo a sinistra che hai già menzionato). –

Problemi correlati