Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Seemingly spurious "does not take arguments" error with case class constructor

I have a case class that has a few parameters for its constructor, and I define an accompanying class object that defines an alternative constructor that takes a different set of arguments, like so:

case class MyClass (c: Char, mc: List[MyClass]) 

object MyClass {
  def apply(c: Char, mc: MyClass): MyClass = {
    MyClass(c, List(mc))
  }
}

I want to use the original case class constructor in a foldRight:

object SomeStuff {
  def problem (s: String) {
    assert(!s.isEmpty)

    val zero = MyClass('a', Nil)

    val mc2 = "Pillsy Pillsy Pillsy" foldRight(zero) {
      MyClass(_, List(_))
    }
  }
}

When I do this, I get an error message from the compiler: "MyClass does not take parameters." If I comment out the section val mc2 = ... this problem goes away, but MyClass is clearly taking parameters in the definition of zero. I feel like I must be missing something really basic, but I have no idea what it is. I've tried a couple workarounds, like defining a helper method or a function value to use as the second argument of foldRight, but none of it helps, which is not too surprising since I'm basically fumbling around randomly.

like image 481
Pillsy Avatar asked May 12 '12 18:05

Pillsy


1 Answers

First, foldRight takes two arguments, so you can't use operator notation (in its current form), but you can:

("foo" foldRight zero) { ... }

or alternatively,

("foo" :\ zero) { ... }

Second, { MyClass(_, List(_)) } will desugar into

{ x => MyClass(x, y => List(y)) }

so, you should name arguments and use new keyword to ensure that constructor is called instead of apply method:

"Pillsy Pillsy Pillsy".foldRight(zero) { (c, mc) =>
  new MyClass(c, List(mc))
}

or use supplemental apply method if you want to go with underscores:

"Pillsy Pillsy Pillsy".foldRight(zero) { MyClass(_, _) }
like image 165
4e6 Avatar answered Oct 04 '22 17:10

4e6