我希望javascripts能够在scala中解构。考虑js中的对象和scala中的case类。如果我只想要来自object / case类的第一个和最后一个属性,那么在scala中我需要列出所有属性或者我得到编译错误。
在scala案例类解构(据我所知)是使用unapply
方法的位置
case class ABC(a: Int, b: Int, c: Int)
val obj = ABC(1,2,3)
// deconstruction
val (a, _, c) = obj
在javascript中按属性名称
const obj = { a: 1, b: 2, c: 3 }
const { a, c } = obj
// or
const { a: attrA, c: attrC } = obj
// scala deconstruction is essentially javascript array deconstruction
const arr = [1,2,3]
const [ first, _, last ] = arr
是否可以在scala中使用'javascript like'对象解构?在这个例子中,差异是微不足道的,但是在未来的修订中可能会改变顺序的更多属性,scala代码变得更难管理。
答案 0 :(得分:4)
如果我错了,请纠正我,但据我了解,
obj.a
只需将名称obj.c
和a
下的值c
和import
纳入范围。如果模式匹配过于冗长,您可以使用case class Abc(a: Int, b: Int, c: Int)
val obj = Abc(1, 2, 3)
val somethingUsingOnlyAandC = {
import obj.{a, c}
a + c
}
println(somethingUsingOnlyAandC) // Output: 4
轻松实现类似的效果,例如:
case class Abc(a: Int, b: Int, c: Int)
val x = Abc(1, 2, 3)
val y = Abc(4, 5, 6)
val bar = {
import x.{a => a1, c => c1}
import y.{a => a2, c => c2}
a1 * a2 + c1 * c2
}
println(bar) // prints "22", 1 * 4 + 3 * 6
如果您有多个具有重命名导入的同一类对象,也可以使用它:
CONNECT
答案 1 :(得分:1)
如果您坚持使用提取器,则可以使用构思from this answer
object && {
def unapply[A](a: A): Option[(A, A)] = Some((a, a))
}
并为每个成员变量另外定义一个单独的提取器:
case class Abc(a: Int, b: Int, c: Int)
object Abc {
object A { def unapply(x: Abc): Option[Int] = Some(x.a) }
object B { def unapply(x: Abc): Option[Int] = Some(x.b) }
object C { def unapply(x: Abc): Option[Int] = Some(x.c) }
}
现在你可以在像这样的模式匹配中使用它:
val z = Abc(42, 100, 58)
import Abc._
val A(a) && B(b) = z
println(s"a = $a , b = $b")
此示例的输出为:
a = 42 , b = 100
请注意,它适用于与&&
链接在一起的任意数量的提取器,例如:
case class Abc(a1: Int, a2: Int, a3: Int, a4: Int, a5: Int, a6: Int, a7: Int, a8: Int)
object Abc {
object A1 { def unapply(x: Abc): Option[Int] = Some(x.a1) }
object A2 { def unapply(x: Abc): Option[Int] = Some(x.a2) }
object A3 { def unapply(x: Abc): Option[Int] = Some(x.a3) }
object A4 { def unapply(x: Abc): Option[Int] = Some(x.a4) }
object A5 { def unapply(x: Abc): Option[Int] = Some(x.a5) }
object A6 { def unapply(x: Abc): Option[Int] = Some(x.a6) }
object A7 { def unapply(x: Abc): Option[Int] = Some(x.a7) }
object A8 { def unapply(x: Abc): Option[Int] = Some(x.a8) }
}
object && {
def unapply[A](a: A): Option[(A, A)] = Some((a, a))
}
val z = Abc(1, 2, 3, 4, 5, 6, 7, 8)
import Abc._
val A3(a3) && A5(a5) && A7(a7) = z
println(s"$a3 $a5 $a7")
输出
3 5 7
正如所料。如果你真的想经常使用这些笨重的对象,你应该考虑为样板代码生成代码。
答案 2 :(得分:0)
您可以解构提供unapply method (extractor)的所有内容:
class Test(val a: String, val b: Int)
object Test {
def unapply(test: Test): Option[(String, Int)] = Some((test.a, test.b))
}
val test = new Test("test", 0)
val (a, b) = test
它是为案例类自动生成的,因此您的示例也允许它:
case class ABC(a: Int, b: Int, c: Int)
val obj = ABC(1,2,3)
// deconstruction
val ABC(a, _, c) = obj
请注意,有一个包含提取器的对象名称 - 它告诉编译器在哪里搜索它(如果你想要的话可能有几个提取器!)。
相同的机制用于模式匹配,因此当您使用:
时option match {
case Some(value) => // uses Some.unapply(option)
case None => // uses None.unapply(option)
}
either match {
case Left(left) => // uses Left.unapply(either)
case Right(right) => // uses Right.unapply(either)
}
提取器获取带有内容的元组的Option
- 有些意味着匹配成功,而无意味着失败。
对于集合,您可能需要查找确切示例,具体取决于您的数学运算:
list match {
case v1 :: v2 :: Nil => // 2-element list
case head :: tail => // non-empty list
case Nil => // empty list
}
seq match {
case Seq() => // empty Seq
case Seq(a, b) => // 2-element Seq
case Seq(a, tail @ _*) => destructures into a and iterable tail
}