9

Having two simple classes taking Int as an argument:

case class Foo(i: Int)
     class Bar(j: Int)

I can say:

List(1,2,3) map Foo

Which works fine and is equivalent to a bit more verbose:

List(1,2,3) map {Foo(_)}

However Bar (because it is not a case class?) cannot be used in the same construct:

List(1,2,3) map Bar

  error: not found: value Bar
          List(1,2,3) map Bar
                          ^

Is there some special syntax to reference any constructor and take advantage of eta expansion? List(1,2,3) map {new Bar(_)} seems a bit more verbose compared to Foo.

7
  • 1
    Eta expansion is something that happen to methods. Note that a constructor is not a method. Commented Oct 8, 2011 at 13:56
  • @DanielC.Sobral What exactly is a constructor ? Commented Oct 30, 2019 at 8:36
  • @AshkanKh.Nazary A constructor is a sequence of instructions that initializes a newly allocated object. Commented Dec 2, 2019 at 18:44
  • @DanielC.Sobral And that is not a method or a function ? You can't call it explicitly or pass it around or apply eta expansion on it to turn it into a function ? Commented Dec 4, 2019 at 9:41
  • @AshkanKh.Nazary No, you can't. Try new String _, for example. It is also different at the bytecode level, and there's all sort of differences in JVM expectations between methods and constructors. Commented Dec 19, 2019 at 17:50

2 Answers 2

12

It works in the former case, because companion object of a case class extends appropriate FunctionN trait. (object Foo extends (Int => Foo) in your example.) For non-case classes, you could do this manually:

scala> class Bar(i: Int)
defined class Bar

scala> class Bar(i: Int); object Bar extends (Int => Bar) { def apply(i: Int) = new Bar(i) }
defined class Bar
defined module Bar

scala> List(2, 3) map Bar
res17: List[Bar] = List(Bar@1f99e90, Bar@1191056)

IMO it's better to go with new Bar(_) as this extra boilerplate might not be worth the little concision achieved.

Sign up to request clarification or add additional context in comments.

2 Comments

Interesting, wasn't aware that a case class extends FunctionN. I remember a SO answer where all automatic features of case classes are listed but don't remember that issue mentioned.
case classes don't. Their companion objects do.
2

Since Foo is a case class there is also a companion object called Foo, which implements the Function1 interface (had the constructor taken three arguments it would have been the Function3 interface).

Comments

Your Answer

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

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.