- About Scala
- Documentation
- Code Examples
- Software
- Scala Developers
fallbackStringCanBuildFrom used in (Set(1, 2, 3).map(_ * 2)(collection.breakOut)): Seq[Int]
Sun, 2011-05-22, 19:51
Hey all,
To answer a question on IRC, I executed the following command via scalabot:
scala> (Set(1, 2, 3).map(_ * 2)(collection.breakOut)): Seq[Int]
res0: Seq[Int] = Vector(2, 4, 6)
Kevin Wright pointed out that this was unexpected given the default
builder for Seq. Stefan Zeiger also got involved and with the help of
-Xprint:type it seems that
LowPriorityImplicits.fallbackStringCanBuildFrom is being used in this
scenario:
(scala.this.Predef.Set.apply[Int](1, 2, 3).map[Int, Seq[Int]](((x$1:
Int) => x$1.+(1)))(scala.collection.`package`.breakOut[scala.collection.immutable.Set[Int],
Int, Seq[Int]](scala.this.Predef.fallbackStringCanBuildFrom[Int])):
Seq[Int])
That seems a bit odd, but it's not clear whether it's a bug, so
sending it here for further feedback.
Best,
Ismael
Sun, 2011-05-22, 21:27
#2
Re: fallbackStringCanBuildFrom used in (Set(1, 2, 3).map(_ * 2)
On Sun, May 22, 2011 at 9:10 PM, Paul Phillips wrote:
> Not only that, it switched from multiplying by two to adding one! Nice
> falsified transcript there ijuma, real believable.
haha, nicely spotted. ;) Seems like I switched the function inside map
when I compiled it with -Xprint:typer (with no consequences to the
issue at hand, of course).
> I would say this is definitely a bug in terms of "is this desirable
> behavior"
Shall I file one?
> * first, check every implicit accessible via simple identifier.
> * and if that fails, check the companion of type T.
>
> So it doesn't matter how low priority we go, if something is in predef
> it is higher priority than anything in a companion.
I see.
Best,
Ismael
Sun, 2011-05-22, 21:57
#3
Re: fallbackStringCanBuildFrom used in (Set(1, 2, 3).map(_ * 2)
On 5/22/11 1:19 PM, Ismael Juma wrote:
> Shall I file one?
I can't give you any special authorization, but paulp thinks it's a bug.
Sun, 2011-05-22, 22:07
#4
Re: fallbackStringCanBuildFrom used in (Set(1, 2, 3).map(_ * 2)
This makes it even worse:
scala> import scala.collection.immutable.Seq._
import scala.collection.immutable.Seq._
scala> (Set(1, 2, 3).map(_ * 2)(collection.breakOut)): Seq[Int]
:11: error: ambiguous implicit values:
both method stringCanBuildFrom in object Predef of type => scala.collection.generic.CanBuildFrom[String,Char,String]
and method canBuildFrom in object Seq of type [A]=> scala.collection.generic.CanBuildFrom[collection.immutable.Seq.Coll,A,scala.collection.immutable.Seq[A]]
match expected type scala.collection.generic.CanBuildFrom[Nothing,T,To]
(Set(1, 2, 3).map(_ * 2)(collection.breakOut)): Seq[Int]
^
The CanBuildFrom[String,Char,String] is creating an ambiguity as I attempt to go from Set[Int] to Seq[Int] !? Something is very wrong with that picture.
Sun, 2011-05-22, 22:17
#5
Re: fallbackStringCanBuildFrom used in (Set(1, 2, 3).map(_ * 2)
On Sun, May 22, 2011 at 10:10 PM, Paul Phillips wrote:
> So it doesn't matter how low priority we go, if something is in predef
> it is higher priority than anything in a companion.
Perhaps in this case these
LowPriorityImpicits#fallbackStringCanBuildFrom and
Predef.stringCanBuildFrom could be moved into a (fictional) companion
object for String. Although perhaps that trades one set of undesirable
behaviour for another.
Incidentally, we face a similar problem in Scalaz -- in the implicit
scope of M[A], an implicit defined in a superclass of object M, isn't
of lower priority than an implicit in object A. Driving the priorities
with an annotation (@reluctantImplicit?) might be a solution.
-jason
Mon, 2011-05-23, 02:07
#6
Re: fallbackStringCanBuildFrom used in (Set(1, 2, 3).map(_ * 2)
On 5/22/11 2:08 PM, Jason Zaugg wrote:
> Driving the priorities
> with an annotation (@reluctantImplicit?) might be a solution.
Keep a @reluctantLanguageDesigner meta-annotation handy.
(He'll like my idea even less: implicit predicate dispatch!)
Mon, 2011-05-23, 04:49
#7
Re: fallbackStringCanBuildFrom used in (Set(1, 2, 3).map(_ * 2)
On 5/22/11 2:08 PM, Jason Zaugg wrote:
> Perhaps in this case these
> LowPriorityImpicits#fallbackStringCanBuildFrom and
> Predef.stringCanBuildFrom could be moved into a (fictional) companion
> object for String. Although perhaps that trades one set of undesirable
> behaviour for another.
>From my view the ability to do that would be a move toward desirable
behavior. Related:
https://issues.scala-lang.org/browse/SI-4338
java classes with static methods and "object not a value"
Yet another in my carnival of wontfixes! (Anyone who thinks I have it
any better than you guys should count my rejection slips.)
On 5/22/11 11:50 AM, Ismael Juma wrote:
> scala> (Set(1, 2, 3).map(_ * 2)(collection.breakOut)): Seq[Int]
> res0: Seq[Int] = Vector(2, 4, 6)
>
> (scala.this.Predef.Set.apply[Int](1, 2, 3).map[Int, Seq[Int]](((x$1:
> Int) => x$1.+(1)))(scala.collection.`package`.breakOut[scala.collection.immutable.Set[Int],
> Int, Seq[Int]](scala.this.Predef.fallbackStringCanBuildFrom[Int])):
> Seq[Int])
Not only that, it switched from multiplying by two to adding one! Nice
falsified transcript there ijuma, real believable.
I would say this is definitely a bug in terms of "is this desirable
behavior" but it is probably not a bug in terms of "is the correct
implicit being selected." This is a very unfortunate and heretofore not
known to me consequence of the implicit scope rules, which say
(summarized and simplified) that if we're looking for an implicit T:
* first, check every implicit accessible via simple identifier.
* and if that fails, check the companion of type T.
So it doesn't matter how low priority we go, if something is in predef
it is higher priority than anything in a companion.