implciit class + case class don't mix

145 views
Skip to first unread message

Josh Suereth

unread,
Aug 17, 2012, 2:57:18 PM8/17/12
to scala-i...@googlegroups.com
I think this maybe needs to be more critical: https://issues.scala-lang.org/browse/SI-6227?focusedCommentId=59645#comment-59645

I'd hate to launch a new feature that doesn't work with another feature at all.  Perhaps we should just warn if you define an implicit case class ?

Paul Phillips

unread,
Aug 17, 2012, 5:30:41 PM8/17/12
to scala-i...@googlegroups.com


On Fri, Aug 17, 2012 at 11:57 AM, Josh Suereth <joshua....@gmail.com> wrote:
I'd hate to launch a new feature that doesn't work with another feature at all.  Perhaps we should just warn if you define an implicit case class ?

I think everything would work if we inhibit the implicit method creation and mark the object's apply as implicit instead.

  implicit case class Foo(x: Int) 

becomes

  class Foo(val x: Int)
  object Foo { implicit def apply(x: Int) = new Foo(x) }

This avoids there being an irregularity in the non-implicit way of calling the method.

Josh Suereth

unread,
Aug 17, 2012, 5:39:45 PM8/17/12
to scala-i...@googlegroups.com

Does that actually work now?  If I import Foo, is it picked up?

martin odersky

unread,
Aug 17, 2012, 6:53:15 PM8/17/12
to scala-i...@googlegroups.com
On Fri, Aug 17, 2012 at 11:39 PM, Josh Suereth <joshua....@gmail.com> wrote:

Does that actually work now?  If I import Foo, is it picked up?

No. It's not in scope. I think for now it's best to disallow implicit case classes. 

Cheers

 - Martin



--
Martin Odersky
Prof., EPFL and Chairman, Typesafe
PSED, 1015 Lausanne, Switzerland
Tel. EPFL: +41 21 693 6863
Tel. Typesafe: +41 21 691 4967

Paul Phillips

unread,
Aug 17, 2012, 6:58:29 PM8/17/12
to scala-i...@googlegroups.com
On Fri, Aug 17, 2012 at 3:53 PM, martin odersky <martin....@epfl.ch> wrote:
No. It's not in scope.

Sure it is.  If object Foo is in scope, then an implicit Int => Foo is in scope.

scala> object bip { class Foo(val x: Int) ; object Foo { implicit def apply(x: Int) = new Foo(x) } }
warning: there were 1 feature warnings; re-run with -feature for details
defined module bip

scala> import bip.Foo
import bip.Foo

scala> 5: Foo
res0: bip.Foo = bip$Foo@158654b4
 

Jason Zaugg

unread,
Aug 17, 2012, 7:04:47 PM8/17/12
to scala-i...@googlegroups.com
That only works because the implicits in the companion are in the
implicit scope:

scala> object bip { class Foo(val xxx: Int) ; object Foo { implicit
def apply(x: Int) = new Foo(x) } }
warning: there were 1 feature warnings; re-run with -feature for details
defined module bip

scala> 5: bip.Foo
res6: bip.Foo = bip$Foo@4edb89c2

scala> 5.xxx
<console>:8: error: value xxx is not a member of Int
5.xxx
^

scala> import bip.Foo
import bip.Foo

scala> 5.xxx
<console>:10: error: value xxx is not a member of Int
5.xxx
^

scala> import bip.Foo.apply
import bip.Foo.apply

scala> 5.xxx
res9: Int = 5

-jason

Paul Phillips

unread,
Aug 17, 2012, 7:08:17 PM8/17/12
to scala-i...@googlegroups.com


On Fri, Aug 17, 2012 at 4:04 PM, Jason Zaugg <jza...@gmail.com> wrote:
That only works because the implicits in the companion are in the
implicit scope:

I was just noticing that.  How inconvenient.  Implicit scope might be my kryptonite.

Josh Suereth

unread,
Aug 17, 2012, 7:11:39 PM8/17/12
to scala-i...@googlegroups.com

The use case Jason shows was the big motivator for implicit classes.  I think if we had case-class-feature-a-la-cart not having companion object would be OK.

Worse though is the inconsistencies of object and def/val/var in the term namespace.

Jason Zaugg

unread,
Aug 17, 2012, 7:14:53 PM8/17/12
to scala-i...@googlegroups.com
There is also this:

scala> object bip { class Foo(val xxx: Int) ; implicit object Foo
extends (Int => Foo) { implicit def apply(x: Int) = new Foo(x) } }
warning: there were 1 feature warnings; re-run with -feature for details
defined module bip

scala> 5.xxx
res11: Int = 5

I should note that, as before, this can't allow you to create these at
the top level; you need to manually place them in a package object.

-jason

Paul Phillips

unread,
Aug 17, 2012, 7:17:09 PM8/17/12
to scala-i...@googlegroups.com


On Fri, Aug 17, 2012 at 4:14 PM, Jason Zaugg <jza...@gmail.com> wrote:
scala> object bip { class Foo(val xxx: Int) ; implicit object Foo
extends (Int => Foo) { implicit def apply(x: Int) = new Foo(x) } }

Okay, THIS is what I was thinking of.

But the apply doesn't have to be implicit, just the object.

Jason Zaugg

unread,
Aug 17, 2012, 7:18:05 PM8/17/12
to scala-i...@googlegroups.com
Exactly. (Copy-paste might just be my kryptonite.)

-jason

Josh Suereth

unread,
Aug 17, 2012, 7:19:49 PM8/17/12
to scala-i...@googlegroups.com

I'd be for that encoding but I remember some kind of issue with the tech. details.  Anyone recall what?

Jason Zaugg

unread,
Aug 17, 2012, 7:22:16 PM8/17/12
to scala-i...@googlegroups.com
On Sat, Aug 18, 2012 at 1:11 AM, Josh Suereth <joshua....@gmail.com> wrote:
> The use case Jason shows was the big motivator for implicit classes. I
> think if we had case-class-feature-a-la-cart not having companion object
> would be OK.
>
> Worse though is the inconsistencies of object and def/val/var in the term
> namespace.

I don't think it's so bad. You can't define a nullary method and a
same-named object:

scala> object A { val x = 0; object x }
<console>:12: error: x is already defined as value x
object A { val x = 0; object x }
^

Overload resolution sort of does it's own thing that I can't find
specced (and which isn't replicated in implicit search [1]), and uses
`followApply` to consider both `method x` and `method x.apply` as
equal candidates:

scala> object A { def x(a: Int) = 0; object x { def apply(a: Int) = 1 } }
defined module A
warning: previously defined class A is not a companion to object A.
Companions must be defined together; you may wish to use :paste mode for this.

scala> A.x(0)
<console>:14: error: ambiguous reference to overloaded definition,
both object x in object A of type A.x.type
and method x in object A of type (a: Int)Int
match argument types (Int)
A.x(0)
^

-jason

[1] https://groups.google.com/d/msg/scala-language/fed6fSKEfS8/Xe_-w773ZpYJ
Reply all
Reply to author
Forward
0 new messages