Pillsy
Pillsy

Reputation: 9901

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.

Upvotes: 6

Views: 4058

Answers (1)

4e6
4e6

Reputation: 10776

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(_, _) }

Upvotes: 5

Related Questions