Question

Imagine that I have the class Imaginary(x) and the class Real(y) in Scala. Is there a way to do ComplexNumber = 3 + 2i instead of doing ComplexNumber = Real(3) + Imaginary(2) ?

Thanks.

Était-ce utile?

La solution 4

No, this is not possible. The lexical analysis phase of the compiler "owns" suffixes on numeric strings such as f (Float), d (Double) and l (Long) and there is no extensibility for this notation.

You might want to think about using the new string interpolation mechanism to annotate constants. You'd have to accept parsing them and the "flag," if you will (your i), would have to be used in prefix position. That would give you something like this:

val imaginary = i"1.2+3.4i"

I'm not up-to-date with the capabilities of macros in the new compiler, but perhaps you could get the parsing done at compile time, which would preclude attempting to work with malformed values at run-time.

This approach (whether compile-time or run-time parsed) would be flexible (insofar as you can be as accommodating as you like in the accepted formats) but it clearly does not match the notation that people use in mathematical texts.

Autres conseils

Is 3 + 2.i enough?

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

Usage:

scala> 3 + 2.i
res3: Mixed = Mixed(3,2)

2i means 2*i. You can't replace 2*a with 2a in scala so you should use 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)

Usage:

scala> 3 + 2*I
res0: ComplexNumber = ComplexNumber(3,2)

scala> 4 - I
res1: ComplexNumber = ComplexNumber(4,-1)

Be careful. Remember that the real and imaginary parts of a complex number have to both be real. Could you do something like:

case class Complex(real: Real, imag: Real) {
  // in here define all your arithmetic ops
}

Then you could use senia's implicit trick to turn numbers automatically into reals and declare an i method in Real that would turn it into an imaginary number.

// inside Real
def i: Complex = Complex(Real(0), this)

I would just caution you not to complicate the code too much, just for the sake of cute syntax. Complex(a, b) is nice and clear. If you want to create a parser, feel free, but I'd reserve that for String values and let code be code.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top