Yes the method RowParser.~
combines two separate RowParsers for separate columns, giving result RowParser[anorm.~[Col1Type, Col2Type]]. Here's the processing details:
Singleton
object
anorm.SqlParser
has all members imported.It has a method
get[T]
:def get[T](columnName: String)(implicit extractor: Column[T]): RowParser[T]
- when called, generic param
T
is instantiated asString
- input param
columnName
is populated as"user.email"
, etc - input param
extractor
isimplicit
. It's not provided in calls. So, the compiler picks up an implicit value using the type signature matching within theColumn
singleton object. It finds methodrowToString: Column[String]
. - output params
RowParser[T]
is instantiatedRowParser[String]
- when called, generic param
anorm.RowParser[String]
has method "~
" called. It's signature is:def ~[B](p: RowParser[B]): RowParser[~[String, B]]
But what is the input (parameter p) for "
~
"? It's on the next line:get[String]("user.name") ~
.Because of this "chaining" of method calls, the method call order is actually bottom-up:
first
get[String]("user.password") map { case email~name~password => User(email, name, password)
which returns type
RowParser[String]
which is passed into
get[String]("user.name") ~
which returns type
RowParser[~[String, String]]
. Here, this uses a different "~" - the typeanorm.~[A,B]
which is defined as a case class:case class ~[+A, +B](_1: A, _2: B) extends Product with Serializable
representing the result of conjoining two parsed columns in the row.
This RowParser is passed into:
get[String]("user.email") ~
which returns type
RowParser[~[String, RowParser[~[String, String]]]]