scalascalazshapelessscala-catszio

Is it possible to control the number of argument in a function when using varargs in compile time(Scala)?


Let us suppose, we have to create the OddList[+T] which contains only odd number of elements. Now can we do something like this

OddList(1,2) //Works fine
OddList(1,2,3) //Compilation error

if there is no condition of odd/even then we would simply do as below

object OddList{
 def apply[T](eles: T*) = ...
}

But can we control number of arguments that could be passed?


Solution

  • Thanks @Dylan and everyone who asked to explore to macros way. I don't know if there are better ways, I would love to know but macros way works for me, at least for now. I tried the below code and it worked.

    trait OddArgHolder[T]{
      val args: Seq[T]
    }
    case class OddArgs[T](args: Seq[T]) extends OddArgHolder[T]
    
    object OddArgHolder{
      import scala.language.experimental.macros
      import scala.reflect.macros.whitebox.Context
    
      def applyMacro[T](c: Context)(method: c.Expr[T]*): c.Expr[OddArgHolder[T]] = {
        import c.universe._
    
        if(method.size % 2 == 0){
          c.abort(c.enclosingPosition, "Only odd number of arguments allowed")
        } else {
          val met = method.map(m => c.typecheck(m.tree))
          c.Expr(c.parse(s"OddArgs( $met )"))
        }
    
      }
    
      def apply[T](method: T*): OddArgHolder[T] = macro applyMacro[T]
    
    }
    
    
      println(OddArgHolder(1,2))
     //Compiletime output: 
     //Only odd number of arguments allowed
     //  println(OddArgHolder(1,2))