كيف نفهم "معرف الحالة ~ اسم المستخدم => _" في anorm؟
-
29-10-2019 - |
سؤال
يحتوي anorm Play2 على DSL لطيف لمحلل النتائج:
case class User(id:Pk[String], name:String)
object User {
val parser = get[String]("id") ~ get[String]("name") map {
case id ~ name => User(id,name)
}
}
أنا لا أفهم هذا الجزء case id ~ name
, ، لماذا يمكن أن يكون هناك ~
بين متغيرين؟
أرى case
عادة مثل:
case id => _
case (a,b) => _
case Array(a, _*) => _
لكنني لا أرى case id ~ name
.
مصدر ~
هنا: https://github.com/playframework/Play20/blob/master/framework/src/anorm/src/main/scala/SqlParser.scala#L49
وهو يحدد فئة الحالة ~
:
case class ~[+A, +B](_1:A, _2:B)
وأكتب اختبارًا بسيطًا:
case class ~[+A, +B](_1:A, _2:B)
new ~("a","b") match {
case x ~ y => println(x , y)
}
يطبع a,b
, ولكن لماذا بناء الجملة case x ~ y
?
المحلول
أنت بالفعل في منتصف الطريق هناك.هذا ممكن لأن Scala يتيح لك القيام بذلك لجميع الأنواع التي تم الإعلان عنها اثنين معلمات النوع.
على سبيل المثال:
scala> case class Foo[X,Y]()
defined class Foo
scala> val x: Int Foo Double = Foo[Int,Double]()
x: Foo[Int,Double] = Foo()
على الرغم من أن الأمر قد يبدو غريبًا في البداية، إلا أنه في الواقع خاصية رائعة لأن بناء الجملة هذا يمكن أن يجعل الأشياء أكثر قابلية للقراءة.خذ بعين الاعتبار المثال التالي حيث يتم تعريف نوع مخصص لمجموعة:
class |::|[A, B](val left: A, val right: B)
object |::| {
def unapply[A, B](o: A |::| B) = Some((o.left, o.right))
}
هنا، A |::| B
يستخدم كتدوين infix لـ |::|[A, B]
.من ناحية أخرى، سكالا أيضًا يسمح بتدوين infix لمطابقة النمط (بفضل incrop للتذكير)، كما في حالة المُنشئ في المثال التالي:
new |::|("Hello","World") match {
case l |::| r => Console println (l + "," + r)
case _ =>
}