想象一下,我在 Scala 中有 Imaginary(x) 类和 Real(y) 类。有没有办法做 ComplexNumber = 3 + 2i 而不是做 ComplexNumber = Real(3) + Imaginary(2) ?
谢谢。
够3 + 2.i
了吗?
sealed trait ComplexNumber {
val re: Int
val im: Int
}
case class Real(re: Int) extends ComplexNumber { val im: Int = 0 }
implicit class ToReal(val re: Int) extends AnyVal {
def +(that: Imaginary) = Mixed(re, that.im)
}
case class Imaginary(im: Int) extends ComplexNumber { val re: Int = 0 }
implicit class ToImaginary(val im: Int) extends AnyVal {
def i: Imaginary = Imaginary(im)
}
case class Mixed(re: Int, im: Int) extends ComplexNumber
用法:
scala> 3 + 2.i
res3: Mixed = Mixed(3,2)
2i
意味着2*i
。您不能在 scala 中替换2*a
为2a
,因此您应该使用 operator *
。
case class ComplexNumber(re: Int, im: Int){
def +(that: ComplexNumber) = ComplexNumber(re + that.re, im + that.im)
def -(that: ComplexNumber) = ComplexNumber(re - that.re, im - that.im)
def *(that: ComplexNumber) = ComplexNumber(re*that.re - im*that.im, re*that.im + im*that.re)
}
implicit def intToComplec(i: Int): ComplexNumber = ComplexNumber(i, 0)
object I extends ComplexNumber(0, 1)
用法:
scala> 3 + 2*I
res0: ComplexNumber = ComplexNumber(3,2)
scala> 4 - I
res1: ComplexNumber = ComplexNumber(4,-1)
当心。请记住,复数的实部和虚部都必须是实数。你能做类似的事情:
case class Complex(real: Real, imag: Real) {
// in here define all your arithmetic ops
}
然后,您可以使用 senia 的隐式技巧将数字自动转换为实数,并声明一个将其转换为虚数的i
方法。Real
// inside Real
def i: Complex = Complex(Real(0), this)
我只是提醒你不要让代码过于复杂,只是为了可爱的语法。Complex(a, b)
很好很清楚。如果您想创建解析器,请随意,但我会将其保留为String
值并让代码成为代码。
不,这是不可能的。编译器的词法分析阶段“拥有”数字字符串的后缀,例如f
( Float
)、d
( Double
) 和l
( Long
),并且这种表示法没有可扩展性。
您可能想考虑使用新的字符串插值机制来注释常量。您必须接受解析它们,并且如果您愿意,“标志”(您的i
)必须用于前缀位置。这会给你这样的东西:
val imaginary = i"1.2+3.4i"
我不了解新编译器中宏的功能,但也许您可以在编译时完成解析,这将排除在运行时尝试使用格式错误的值。
这种方法(无论是编译时解析还是运行时解析)将是灵活的(只要您可以在接受的格式中随心所欲地适应),但它显然与人们在数学文本中使用的符号不匹配。