0
\$\begingroup\$

I started learning Scala, and like most functional languages, things get messy pretty quickly for a beginner.

Here I have built a wrapper class for Ints so that I can declare additional functions for the Int class. For example, I want to be able to do something like 1.isPrime, and it should call a function that tells me if the given number is prime or not.

Here is my code:

package object Arithmetic {
    trait S99Int { me =>
        var value: Int = 0
        implicit def int2S99Int(value: Int):me.type = {
            me.value = value; me
        }
    }
}

The above creates the implicit conversions that enable any class that conforms to the trait, to be able to declare additional functions for Ints. For example, I can now do this:

import Arithmetic._

object S99IntPrime extends S99Int {
    import scala.math.{sqrt, abs}

    def isPrime: Boolean = value match {
        case -1|0|1 => false
        case p      => Stream.cons(2,
        Stream.range(3, sqrt(abs(p)).toInt + 1, 2)) forall (p % _ != 0)
    }

    def main(args: Array[String]): Unit = { 
        println(args.head.toInt.isPrime)
    }
}

I am mostly asking this question about the first snippet I posted. What are the advantages/disadvantages with declaring the base object like I have? Recommendations? Warnings? I just started learning Scala, so any advice will save me hours of Googling.

\$\endgroup\$

1 Answer 1

1
\$\begingroup\$

First of all, what Scala version are you using? If you're using 2.10 or newer versions, the language has introduced implicit classes which help you avoid the definition of implicit conversions - as a side note implicit classes are translated to implicit conversions by the compiler so let's say they are some type of syntactic sugar.

As you might now, the implicit modifier cannot be used on top-level definitions - that includes implicit classes as well, so we must wrap them in a class / trait / object. As a best practice it's best to put them in an object (or package object like you did). The other constraints of implicit classes are already explained in the first link, so I won't go through them here.

A final note before we get to the code is that you will often see that implicit classes are used as value classes. Please consult this post if you're curious to see how when you should mix them with value classes.

Enough talk, let's see the code now:

package object arithmetic {
  implicit class RichInt(val value: Int) extends AnyVal {
    def isPrime: Boolean = ???
  }
}

object ArithmeticTest extends App {
  import arithmetic._
  1.isPrime
}

That's it! Hope it helps.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.