Skip to content

Explicitly use scala.collection.Seq to allow use of mutable collections in Scala 2.13 #176

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Conversation

tmccarthy
Copy link
Contributor

@tmccarthy tmccarthy commented Apr 10, 2020

Since Scala 2.13, the universal Seq type alias has referred to scala.collection.immutable.Seq. Prior to this, it referred to scala.collection.Seq, which is the supertype for both mutable and immutable sequences (see migration note).

Since #121, this has caused an inconsistency in how plotly-scala handles Seq between the Scala 2.13 and 2.12 versions. In Scala 2.12, mutable collections like ArrayBuffer have an implicit conversion to plotly.Sequence. In Scala 2.13, no conversion exists, and clients are required to convert to immutable.Seq. An example of code that compiles in 2.12 but not 2.13 is included in this PR as a unit test.

This PR fixes this issue by explicitly importing scala.collection.Seq wherever it is used. In Scala 2.12 this is a no-op, since Seq is simply an alias for this type. In Scala 2.13 it restores the old behaviour from before #121.

Let me know if you have any questions or feedback!

Timothy McCarthy added 2 commits April 10, 2020 13:57
Test fails for ./sbt tests/test, passes for ./sbt ++2.12.10! tests/test
Scala 2.12 aliases Seq to scala.collection.Seq, whereas Scala 2.13 aliases to scala.collection.immutable.Seq. Explicitly using scala.collection.Seq allows the use of both mutable and immutable sequences, and retains the behaviour before the Scala 2.13 migration.
@alexarchambault
Copy link
Owner

alexarchambault commented Apr 15, 2020

@tmccarthy Thanks for opening this!

AFAIC I've always tended to rely on immutable collections when using plotly-scala, so I didn't run into that problem.

I think using immutable collections may actually be more consistent. All classes in plotly-scala are already immutable, and have with* methods to change fields, that actually return new instances of the underlying class.

Do you think it would be possible to go the other way around in your uses of plotly-scala, and only pass immutable collections to it? Or is it really too cumbersome? My understanding is that calling .toSeq on mutable collections right before passing them to plotly-scala should be enough.

@alexarchambault
Copy link
Owner

Actually, the implicit conversion from mutable Seq to to plotly.Sequence can't hurt… I think I'd be ok merging the first commit of this PR.

@tmccarthy
Copy link
Contributor Author

tmccarthy commented Apr 18, 2020

Thanks for the response Alex!

In Scala 2.12 and earlier, Seq referred to a supertype for both mutable and immutable collections. This type is what is used throughout plotly-scala, meaning that in 2.12, the project is broadly written against collections that can be mutable. This is not the case in Scala 2.13, where the Seq alias now refers to the supertype for immutable sequences only.

To be clear, I'm all in favour of targeting immutable collections. The .toSeq call is certainly not too cumbersome. My concern is that in plotly-scala 0.7.3, the Scala 2.12 artefact supports and uses potentially-mutable sequences but the 2.13 one doesn't.

Seeing as I'm the one that introduced this problem in #121, I thought I should fix it by restoring the previous behaviour 😅. That behaviour was to use the potentially-mutable Seq through the project.

I agree that it would be a nicer approach to make all sequences within plotly-scala immutable, and to provide an implicit conversion to plotly.Sequence for mutable collections. I'm happy to update this PR accordingly 👍.

Timothy McCarthy added 2 commits April 18, 2020 14:41
…ons from mutable sequences to plotly.Sequence, with Scala-version-specific implementations.
…t once on the Sequence companion. Previous solution was over-engineered.
Comment on lines 51 to 55
private def makeImmutableSeq[A](mutableSeq: BaseScalaSeq[A]): Seq[A] =
mutableSeq match {
case asImmutableSeq: Seq[A] => asImmutableSeq
case _ => mutableSeq.toVector
}
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is basically equivalent to the .toSeq method in Scala 2.13. Since we are cross-compiling with Scala 2.12, we require a dedicated implementation here.

Copy link
Owner

@alexarchambault alexarchambault left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks! Just added a comment about keeping the default Seq by default (except in the Sequences conversions).

@@ -4,6 +4,7 @@ import java.lang.{Boolean => JBoolean, Double => JDouble, Integer => JInt}

import almond.interpreter.api.{DisplayData, OutputHandler}

import scala.collection.immutable.Seq
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's keep relying on the default Seq. That makes the API slightly different in 2.12 and 2.13, but that these APIs accept Seq(…) in both cases, which is not the case in 2.12 if we require scala.collection.immutable.Seq explicitly.

@@ -1,5 +1,6 @@
package plotly

import scala.collection.immutable.Seq
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same as above, let's keep the default Seq, even though it's slightly different in 2.12 and 2.13, here and in all scala.collection.immutable.Seq added below.

…scala.collection.Seq` data type only in Scala 2.13 and up.
@tmccarthy tmccarthy marked this pull request as draft April 19, 2020 12:19
@tmccarthy tmccarthy marked this pull request as ready for review April 19, 2020 12:23
@tmccarthy
Copy link
Contributor Author

If we're happy with the split between Seq implementations between 2.12 and 2.13, I think this is the easiest approach. I've simply provided a set of implicit conversions from scala.collection.Seq to plotly.Sequence in 2.13 only. This minimises the change footprint, but allows mutable collections to be converted to Sequence. Let me know if this hits the mark 🙂.

@alexarchambault
Copy link
Owner

That looks fine, thanks @tmccarthy!

@alexarchambault alexarchambault merged commit a9ea8c3 into alexarchambault:master Apr 19, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants