2 Stimmen

Der Elementtyp von for comprehension in ScalaQuery

Ich habe etwas Interessantes gefunden, als ich das Queries-Tutorial von ScalaQuery verfolgte, von dem ich nicht genau weiß, warum es so ist.

Hier ist mein Datenbankschema definiert:

object Users extends Table[(Int, String, String)]("users") {
    def id = column[Int]("id", O NotNull)
    def first = column[String]("first", O NotNull)
    def last = column[String]("last", O NotNull)
    def * = id ~ first ~ last 
}

Und hier ist die Abfrage, die ich verwende:

object Main
{
    val database = Database.forURL("jdbc:sqlite:sample.db", driver = "org.sqlite.JDBC")
    def main(args: Array[String]) {
        database withSession {

            val query1 = for (user <- Query(Users)) yield user.id ~ user.last
            val query2 = for (user <- Users if user.id > 5) yield user.id ~ user ~ last
        }
    }
}

In diesem Fall konnten Sie sehen, dass in beiden query1 y query2 verwenden Sie etwas wie user.id scheint es, dass user ist der Typ des Singletons object Users die ich gerade oben definiert habe. Es hat also alle Methoden, die für dieses Objekt definiert sind.

Wenn ich aber versuche, die Abfrage direkt auszuführen, ohne yield Schlüsselwort, zum Beispiel:

for (user <- Users if user.id > 5) {
    println ("UserID:" + user.id)
}

In diesem Fall beschwert sich der Compiler:

[error] src/main/scala/Test.scala:23: value id is not a member of (Int, String, String)
[error]    println ("UserID:" + user.id)

Es scheint, als ob user in der println-Anweisung ist vom Typ Tuple3. Und wenn ich user wie ein gewöhnliches Tupel wie das folgende, wird es funktionieren.

for (user <- Users if user.id > 5) {
    println ("UserID:" + user._1)
}

Und Sie konnten sehen, in der Wache für den Ausdruck benutze ich noch user.id Was ist also die Art der user ? Warum könnte ich verwenden user.id im guard- und yield-Block, aber ich muss es als Tupel im Körper des for-Ausdrucks verwenden?

Danke.

7voto

Googol Shan Punkte 1245

Im ersten Codeschnipsel:

val query1 = for (user <- Query(Users)) yield user.id ~ user.last

user es object Users weil die Map-Methode der Query wie folgt definiert ist def map[F](f: E => F): Query[F] ist der erste Codeschnipsel gleichwertig:

Query(Users).map(user => user.id ~ user.last)

so dass die E es Users Typ und Users Instanz ist der Parameter, der an f(E):F .

Wenn Sie eine Zeile als Objekt besuchen möchten, müssen Sie die Benutzer wie unten beschrieben definieren:

import org.scalaquery.ql.basic.{BasicTable => Table}
object Users extends Table[User]("users") {
  def id = column[Int]("id", O NotNull)
  def first = column[String]("first", O NotNull)
  def last = column[String]("last", O NotNull)
  def * = id ~ first ~ last <> (User, User.unapply _)
}

case class User(id: Int, first: String, last: String)

und dann

for (user <- Users if user.id > 5) {
  println ("UserID:" + user.id)  // user is a User instance
}

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X