8

Consider the following:

class A(foo: Int)(bar: Int)(baz: Int)
object A{
    def apply(foo: Int)(bar: Int)(baz: Int) = new A(foo)(bar)(baz)
}

With the apply method I can do the following:

scala> A(1)(2)(3)
res12: Script.A = Script$A@7a6229e9

scala> A(1)_
res13: Int => (Int => Script.A) = <function1>

Why is it that I can't do the following:

scala> new A(1)_
<console>:21: error: missing arguments for constructor A in class A
              new A(1)_
              ^

Am I missing something syntax wise? I thought constructors are meant to be just methods on the class, so they should be lifted to functions when needed (much like the apply method above)

Erik Kaplun
  • 37,128
  • 15
  • 99
  • 111
Henry Henrinson
  • 5,203
  • 7
  • 44
  • 76
  • Depending on how you're using it, it might be easier to define your constructor uncurried, and then use `.curried`. See [this answer](http://stackoverflow.com/a/3864950/3004881) – Dan Getz Jun 26 '14 at 10:36
  • Hopefully a future version of Scala will eliminate such caveats and become more consistent... – Erik Kaplun Jun 26 '14 at 10:42

1 Answers1

4

Calling new on the class supposed to create an instance of that class (A in you case), but what you are trying to do with new A(1) _ is to make an instance of A class without complete data for the contractor, which is essentially not logical at all. But writing A(1) _ is correct and logical cause in this case you are lifting a method into a function (apply method from A companion object) which already has all the data to make an instance of that class.

4lex1v
  • 21,367
  • 6
  • 52
  • 86
  • Isn't `new A()` under the hood call to `apply` method in companion object? – goral Jun 26 '14 at 10:08
  • I doubt it; the apply method is not always defined and, even if that were the case, it would cause an infinite loop in my case, since I defined apply in terms of new A()()() – Henry Henrinson Jun 26 '14 at 10:10
  • @goral no, the call to generated `apply` method would happen if you have a `case class`, then things like `val inst = CaseClass(params)` would call generated apply method, but you also can call `new CaseClass(params)`, which would simply call class contractor. – 4lex1v Jun 26 '14 at 10:11
  • I understand and know about notion of `case classes` and companion object. So how does compiler decide whether to call class contractor or `apply` method from companion object? Is there a performance difference between those two besides obvious call to `apply`? – goral Jun 26 '14 at 10:13
  • @HenryHenrinson Scala generates syntactic apply method only for case classes and you don't see it, your apply method is totally different case and it has nothing to do with call to `new` – 4lex1v Jun 26 '14 at 10:13
  • @goral Using new A() calls the constructor. Doing A() gets desugared into A.apply(). Thing is, there is nothing (apart from maybe convention) to stop someone from defining an apply method that does not return a new instance of A. One could easily define an apply method that just returns an Int or something. – Henry Henrinson Jun 26 '14 at 10:17
  • @Alexlv Agreed, but i don't see what you're trying to say. I am not using case classes here. – Henry Henrinson Jun 26 '14 at 10:18
  • @HenryHenrinson Yes, nothing stops you from returning unit from `apply` in companion object, what's the problem? – 4lex1v Jun 26 '14 at 10:20
  • 4
    Note that you can (almost) write `new A(1)(_)(_)`, because then you _are_ fully specifying the arguments to the constructor. Unfortunately as written the compiler can't handle it, you need to identify the types, for example `new A(1)(_: Int)(_: Int)`. – Dan Getz Jun 26 '14 at 10:40
  • 1
    @DanGetz Oh, neat. Although it seems to create an uncurried function in that case: `scala> new A(1)(_:Int)(_:Int) res41: (Int, Int) => Script.A = ` – Henry Henrinson Jun 26 '14 at 10:52
  • @HenryHenrinson If you want a curried version then call `curried` on the result: `(new A(10)(_: Int)(_: Int)).curried` – 4lex1v Jun 26 '14 at 10:57