17

http://woss.name/2012/04/02/retrieving-bigdecimals-from-a-database-with-anorm-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 *)
    }
  }
}
4

2 回答 2

29

在您的示例中, ~ 以两种不同的方式用于表示两种不同的事物。在第一部分你有

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

等等。正如已经指出的,这只是方法调用,它与

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

您可以在 anorm 源码中查看该方法的定义。它是 a RowParser[A]( 解析 an 的解析器上的方法A,它接受RowParser[B](解析 a 的解析器B) 并返回解析 a 的解析器A ~ B。这A ~ B是 . 的第二个含义~。现在不是指方法,而是指案例类在这里定义在同一个文件中。

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

这只是引用类的一种特殊方式~[A,B]。在类型级别,当您有两个参数的类型构造函数时,您可以使用中缀表示法的类名称。这没什么特别的~,它可以与任何两个参数类型的构造函数一起使用。如果你有trait Foo[A,B],你可以将其称为A Foo B. 类似地,在模式匹配中,变量ab可以使用语法进行绑定,在语言规范的第 8.1.10 节中a Foo b称为中缀操作模式

在示例的第二部分中,您有:

case id ~ name ~ latitude ~ longitude =>

~这是对这些案例类别的模式匹配,这是运行您在上面构建的解析的结果。所以这实际上只是一种更好的写作方式:

case ~(~(~(id, name), latitude), longitude) =>
于 2013-06-13T23:52:23.677 回答
6

在斯卡拉

a ~ b

方法

a.~(b)

所以它调用方法~并作为参数a给出。b另请注意,任何不以结尾的运算符:都是左结合的。

您重新访问的示例将是:

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)
}
于 2013-06-13T23:04:37.680 回答