Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Migrating a generic append function to Scala 2.13 collections

I have the following extension class that adds a myAppend method to anything SeqLike.

implicit class WithAppend[A, R](s: SeqLike[A, R]) extends AnyVal {
  def myAppend(i: A)(implicit cbf: CanBuildFrom[R, A, R]): R = s :+ i
}

How can I port this code to Scala 2.13 and retain similar performance characteristics? Bonus points if the extended class can remain an AnyVal

Few things I have tried:

class Extends1[R, S <: IsSeq[R]](c: R, isSeq: S) {
  def myAppend(a: isSeq.A): R = (isSeq(c) :+ a).asInstanceOf[R]
}

But the asInstanceOf is disappointing - is it even safe?

I could do:

class Extends3[S[_], A](c: SeqOps[A, S, S[A]]) {
  def myAppend(a: A): S[A] = c :+ a
}

but now we're constrained to collections of the form S[A] while the Scala 2.12 code can take any R.

like image 774
thesamet Avatar asked Mar 17 '19 22:03

thesamet


People also ask

What is Scala list append?

Introduction to Scala List Append The following article provides an outline for Scala List Append. Scala list are immutable which means once assign object cannot change itself. List is also a part of collection which is used to store and retrieve elements.

What is a generic class in Scala?

Most Scala generic classes are collections, such as the immutable List, Queue, Set, Map, or their mutable equivalents, and Stack. Collections are containers of zero or more objects. We also have generic containers that aren’t so obvious at first. For example, Option is a container that can take zero objects or one object.

What's new in the Scala Collections Library?

The most important changes in the Scala 2.13 collections library are: scala.Seq [+A] is now an alias for scala.collection.immutable.Seq [A] (instead of scala.collection.Seq [A] ). Note that this also changes the type of Scala varargs methods.

How to modify values present inside Scala list programmatically?

In Scala list represent linked list data structure. In a singly linked list structure we have node which contained two things data and address to the next node. We can modify the values present inside scala list programmatically through our logic. Also list can contain duplicate elements in it and maintain the insertion order as well.


1 Answers

I can come up with a method signature and implementation that works without casts:

implicit class WithAppend[Repr](private val repr: Repr) extends AnyVal { 
  def myAppend[A0, C](a: A0)(
    implicit 
    isSeq: IsSeq[Repr]{ type A = A0 }, 
    b: BuildFrom[Repr, A0, C]
  ): C = b.fromSpecific(repr)(isSeq(repr) :+ a) 
}

It's hard to give guarantees about the performance of this, but I doubt it would be significantly worse than what you used to have. An alternative is b.newBuilder(repr).addAll(isSeq(repr)).addOne(a).result().

scala> List(1,2).myAppend(3)
res3: List[Int] = List(1, 2, 3)

scala> Vector(1,2).myAppend(3)
res4: scala.collection.immutable.Vector[Int] = Vector(1, 2, 3)

scala> "Strin".myAppend('g')
res5: String = String
like image 132
Jasper-M Avatar answered Oct 15 '22 04:10

Jasper-M