`new Foo` vs `new Foo()`

154 views
Skip to first unread message

Seth Tisue

unread,
Jul 13, 2015, 3:06:44 PM7/13/15
to scala-l...@googlegroups.com
Is there consensus on this? Not sure whether to merge.


Seth

Rex Kerr

unread,
Jul 13, 2015, 3:20:04 PM7/13/15
to scala-l...@googlegroups.com
That's the convention I use.  I've seen both with and without parens in e.g. the Scala library code base.

  --Rex

--
You received this message because you are subscribed to the Google Groups "scala-language" group.
To unsubscribe from this group and stop receiving emails from it, send an email to scala-languag...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Jon Pretty

unread,
Jul 13, 2015, 4:28:08 PM7/13/15
to scala-l...@googlegroups.com
I tend to include the parentheses for a couple of reasons: firstly because case classes require the parens, and by association I justify that classes should too, and secondly because instantiating a new instance of a class is side-effecting, so the "method" which does that (i.e. the constructor) should look like a side-effecting method.

Additionally, for some reason, I prefer to write `new Foo().bar` rather than `(new Foo).bar`. I think the reason is that I have a slight discomfort at starting an expression with an opening parenthesis, and I've taught myself to give the `new` in `new Foo().bar` higher precedence than the `.`, even though this is counterintuitive to other parsing rules.

Jon​
--
Jon Pretty | @propensive

Adriaan Moors

unread,
Jul 13, 2015, 5:13:34 PM7/13/15
to scala-l...@googlegroups.com
If we apply the same rule as for methods, you should not add parens unless your constructor is side-effecting (which is probably not a great idea in itself).
That's the reasoning for case classes, I guess, since a side-effect-free case class should be a case object.

I tend to leave off the empty parens. Their presence should imply potential side-effects.

Haoyi Li

unread,
Jul 13, 2015, 7:05:50 PM7/13/15
to scala-l...@googlegroups.com
That's the reasoning for case classes, I guess, since a side-effect-free case class should be a case object.

This doesn't make sense to me. Since when was object allocation considered side effecting? When people say "avoid side effects", they usually mean you should allocate *more* objects, not less! Is CaseClass#copy just as side-effecting as mutating vars?

Rex Kerr

unread,
Jul 13, 2015, 7:50:44 PM7/13/15
to scala-l...@googlegroups.com
Well, the question is why you would ever

  case class Foo {
    def foo = ???
  }

instead of

  case object Foo {
    def foo = ???
  }

If you're doing the former, maybe it is because you are actually performing side effects.  Right?  So you should use parens?

Except

  trait Bar[A] {
    def bar: A
  }

  case class Foo[A] extends Bar[A] {
    def foo: A = ???
    def bar = foo
  }

And, um, yeah.  Case object?  Not really gonna work here.  Not sure why this should be a case class at _all_, though--maybe just because we don't like the default toString?

Anyway, there is at least some argument that case classes should have parens, even if it's not terribly strong.

  --Rex

Adriaan Moors

unread,
Jul 13, 2015, 8:02:58 PM7/13/15
to scala-l...@googlegroups.com
I didn't mean to imply allocation is side-effecting. I meant the side effect of the initializer in your case class would be invoked every time you instantiate it, whereas the effect in an object's body occur at most once.

On Mon, Jul 13, 2015 at 4:05 PM, Haoyi Li <haoy...@gmail.com> wrote:

Haoyi Li

unread,
Jul 13, 2015, 8:05:36 PM7/13/15
to scala-l...@googlegroups.com
I didn't mean to imply allocation is side-effecting. I meant the side effect of the initializer in your case class would be invoked every time you instantiate it, whereas the effect in an object's body occur at most once.

Oh ok. I thought you were agreeing with jon, who said instantiating a new instance of a class was a side effect (???)

Adriaan Moors

unread,
Jul 13, 2015, 8:21:43 PM7/13/15
to scala-l...@googlegroups.com
Some (exotic) systems consider allocation a side-effect (e.g., for embedded, where GC needs to be bounded etc).

Normally, you only care about "changes"/effects to stuff that's reachable, and a freshly allocated object is known not to be aliased, so there is no side-effect -- move along people!
Btw, on a related note: Facebook's Infer is fascinating stuff -- applying separation logic to production systems.

Haoyi Li

unread,
Jul 13, 2015, 8:27:17 PM7/13/15
to scala-l...@googlegroups.com
Yeah, I can imagine cases where allocation is specially tracked. Rust does that now too. Sometimes I wish things like iterators and builders had their uniqueness tracked via the compiler. 

Anyway this is off topic. My contribution to the original post is that I just try to match parens() with whether or not the class was defined with parens(). Often I wish the compiler would enforce this for me but it doesn't

Som Snytt

unread,
Jul 14, 2015, 1:37:40 AM7/14/15
to scala-l...@googlegroups.com
It's probably worth adding that there's no such thing as a constructor with no params. Even so casual a document as a style guide shouldn't use that language.

http://www.scala-lang.org/files/archive/spec/2.11/05-classes-and-objects.html#class-definitions

"If no formal parameter sections are given, an empty parameter section () is assumed."

The empty parens are made visible when there is an implicit param list and args are supplied explicitly.

This isn't news. Maybe there's a phrase to be newly minted to capture what this purely stylistic difference is. "Pure virtual style."

scala> class C(implicit val c: String)
defined class C

scala> new C
<console>:12: error: could not find implicit value for parameter c: String
       new C
       ^

scala> new C("hi")
<console>:12: error: too many arguments for constructor C: ()(implicit c: String)C
       new C("hi")
       ^

scala> new C()("hi")
res2: C = C@60f82f98

scala> implicit val s = "bye"
s: String = bye

scala> new C
res3: C = C@5f375618


I also switch between where to put the parens when selecting; mostly depending on whether I remembered the left paren when I started typing.

scala> (new C).c
res6: String = bye

scala> new C().c
res7: String = bye


Maybe this is the strongest case for postfixOps.

scala> new C c
warning: there was one feature warning; re-run with -feature for details
res8: String = bye


Yes, whenever I begin, It's probably worth adding..., it never is.

Jon Pretty

unread,
Jul 14, 2015, 6:34:37 AM7/14/15
to scala-l...@googlegroups.com
Yes, in hindsight, it's not particularly *useful* to consider instantiation as a side-effect in Scala... ;)

Cheers,
Jon

Roland Kuhn

unread,
Jul 14, 2015, 7:01:02 AM7/14/15
to scala-l...@googlegroups.com
[caution, some nit-picking ahead]

Well, that depends: object allocation can cause widely visible effects like GC pauses and simple constructor execution in many cases entails memory barriers (i.e. visible concurrency and latency effects). I agree that such effects usually are ubiquitous and therefore not much can be gained from explicitly tracking them in normal code bases, but Scala can also be used in a fashion that avoids allocation in substantial parts of the program.

Regards,

Roland


Dr. Roland Kuhn
Akka Tech Lead
Typesafe – Reactive apps on the JVM.
twitter: @rolandkuhn


Reply all
Reply to author
Forward
0 new messages