Skip to content
This repository has been archived by the owner on Dec 22, 2021. It is now read-only.

[WIP] Add immutable array vc #16

Closed
wants to merge 3 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -10,3 +10,4 @@ target/
.history
.DS_Store
/tmp/
/bin/
29 changes: 26 additions & 3 deletions src/main/scala/strawman/collection/Iterable.scala
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
package strawman.collection
package strawman
package collection

import scala.annotation.unchecked.uncheckedVariance
import scala.reflect.ClassTag
Expand Down Expand Up @@ -54,8 +55,10 @@ trait IterableOps[+A] extends Any {
protected def coll: Iterable[A]
private def iterator() = coll.iterator()

/** Apply `f` to each element for tis side effects */
def foreach(f: A => Unit): Unit = iterator().foreach(f)
/** Apply `f` to each element for tis side effects
* Note: [U] parameter needed to help scalac's type inference.
*/
def foreach[U](f: A => U): Unit = iterator().foreach(f)

/** Fold left */
def foldLeft[B](z: B)(op: (B, A) => B): B = iterator().foldLeft(z)(op)
Expand Down Expand Up @@ -188,3 +191,23 @@ trait IterablePolyTransforms[+A, +C[A]] extends Any {
def zip[B](xs: IterableOnce[B]): C[(A @uncheckedVariance, B)] = fromIterable(View.Zip(coll, xs))
// sound bcs of VarianceNote
}

trait TagGuidedPolyTransforms[+A, +C[A]] extends Any {
import scala.reflect.ClassTag

protected def coll: Iterable[A]
def fromIterable[B: ClassTag](coll: Iterable[B]): C[B]

/** Map */
def map[B: ClassTag](f: A => B): C[B] = fromIterable(View.Map(coll, f))

/** Flatmap */
def flatMap[B: ClassTag](f: A => IterableOnce[B]): C[B] = fromIterable(View.FlatMap(coll, f))

/** Concatenation */
def ++[B >: A : ClassTag](xs: IterableOnce[B]): C[B] = fromIterable(View.Concat(coll, xs))

/** Zip. Interesting because it requires to align to source collections. */
def zip[B: ClassTag](xs: IterableOnce[B]): C[(A @uncheckedVariance, B)] = fromIterable(View.Zip(coll, xs))
// sound bcs of VarianceNote
}
5 changes: 2 additions & 3 deletions src/main/scala/strawman/collection/IterableOnce.scala
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
package strawman.collection

import strawman.collection.mutable.Iterator
package strawman
package collection

trait IterableOnce[+A] {
/** Iterator can be used only once */
Expand Down
Original file line number Diff line number Diff line change
@@ -1,17 +1,17 @@
package strawman.collection.mutable
package strawman.collection

import scala.{Boolean, Int, Unit, Nothing, NoSuchElementException}
import strawman.collection.{IndexedView, IterableOnce}

/** A core Iterator class */
trait Iterator[+A] { self =>
trait Iterator[+A] extends IterableOnce[A] { self =>
def hasNext: Boolean
def next(): A
def iterator() = this
def foldLeft[B](z: B)(op: (B, A) => B): B =
if (hasNext) foldLeft(op(z, next()))(op) else z
def foldRight[B](z: B)(op: (A, B) => B): B =
if (hasNext) op(next(), foldRight(z)(op)) else z
def foreach(f: A => Unit): Unit =
def foreach[U](f: A => U): Unit =
while (hasNext) f(next())
def indexWhere(p: A => Boolean): Int = {
var i = 0
Expand Down
1 change: 0 additions & 1 deletion src/main/scala/strawman/collection/Seq.scala
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package strawman.collection

import scala.{Any, Boolean, Int, IndexOutOfBoundsException}
import strawman.collection.mutable.Iterator
import strawman.collection.immutable.{List, Nil}

import scala.annotation.unchecked.uncheckedVariance
Expand Down
4 changes: 4 additions & 0 deletions src/main/scala/strawman/collection/Set.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
package strawman
package collection

trait Set[A] extends Iterable[A] {}
1 change: 0 additions & 1 deletion src/main/scala/strawman/collection/View.scala
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ package strawman.collection

import scala.{Int, Boolean, Nothing, annotation}
import scala.Predef.intWrapper
import strawman.collection.mutable.Iterator

/** Concrete collection type: View */
trait View[+A] extends Iterable[A] with IterableLike[A, View] {
Expand Down
17 changes: 17 additions & 0 deletions src/main/scala/strawman/collection/immutable/Array.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package strawman.collection.immutable

import java.lang.Class
import scala.{AnyVal, Int}
import scala.reflect.ClassTag
import strawman.collection.arrayToArrayOps

class Array[T](private val underlying: scala.Array[T]) extends AnyVal {
def length: Int = underlying.length
def apply(i: Int): T = underlying.apply(i)
def elemClass: Class[_] = underlying.getClass.getComponentType
}

object Array {
def apply[T: ClassTag](elems: T*): Array[T] =
scala.Array(elems: _*).readOnly
}
53 changes: 53 additions & 0 deletions src/main/scala/strawman/collection/immutable/ArrayOps.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
package strawman.collection.immutable

import strawman.collection.{Iterable, IterableOps, SeqMonoTransforms, ArrayLike, IndexedView, TagGuidedPolyTransforms, arrayToArrayOps}
import strawman.collection.mutable.{Buildable, ArrayBuffer}

import scala.{Int, AnyVal, AnyRef}
import scala.Predef.String
import scala.reflect.ClassTag

class ArrayOps[A](val xs: Array[A])
extends AnyRef
// Note: we would like this to be a value class over `immutable.Array[A]`,
// but scalac complains with
//
// error: value class may not wrap another user-defined value class
//
// This is SI-7685. dotty accepts the value class, however. We should fix
// the problem in scalac, fortunately it's scheduled to arrive for 2.13.
// Until that is the case, we have no choice but to make ArrayOps a
// normal class.
with IterableOps[A]
with SeqMonoTransforms[A, Array[A]]
with TagGuidedPolyTransforms[A, Array]
with Buildable[A, Array[A]]
with ArrayLike[A] {

override def view = new ArrayView(xs)

protected def coll = view
def iterator() = coll.iterator()

def length = xs.length
def apply(i: Int) = xs.apply(i)

def elemTag: ClassTag[A] = ClassTag(xs.elemClass)

protected def fromIterableWithSameElemType(coll: Iterable[A]): Array[A] =
coll.toArray[A](elemTag).readOnly

def fromIterable[B: ClassTag](coll: Iterable[B]): Array[B] = coll.toArray[B].readOnly

protected[this] def newBuilder = new ArrayBuffer[A].mapResult(_.toArray(elemTag).readOnly)

override def knownSize = length

override def className = "immutable.Array"
}

case class ArrayView[A](xs: Array[A]) extends IndexedView[A] {
def length = xs.length
def apply(n: Int) = xs(n)
override def className = "immutable.ArrayView"
}
3 changes: 1 addition & 2 deletions src/main/scala/strawman/collection/immutable/LazyList.scala
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
package strawman.collection.immutable

import scala.{Option, Some, None, Nothing, StringContext}
import strawman.collection.{IterableFactory, Iterable, LinearSeq, SeqLike}
import strawman.collection.mutable.Iterator
import strawman.collection.{IterableFactory, Iterable, LinearSeq, SeqLike, Iterator}

class LazyList[+A](expr: => LazyList.Evaluated[A])
extends LinearSeq[A] with SeqLike[A, LazyList] {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
package strawman.collection
package strawman.collection.immutable

import strawman.collection.immutable.List

import scala.{Array, Char, Int, AnyVal}
import scala.{Char, Int, AnyVal}
import scala.Predef.String
import strawman.collection.{Iterable, IterableOps, SeqMonoTransforms, IterablePolyTransforms, ArrayLike, IndexedView, IterableOnce, stringToStringOps}
import strawman.collection.mutable.{ArrayBuffer, Buildable, StringBuilder}

import scala.reflect.ClassTag
Expand Down Expand Up @@ -71,42 +70,3 @@ case class StringView(s: String) extends IndexedView[Char] {
def apply(n: Int) = s.charAt(n)
override def className = "StringView"
}


class ArrayOps[A](val xs: Array[A])
extends AnyVal with IterableOps[A]
with SeqMonoTransforms[A, Array[A]]
with Buildable[A, Array[A]]
with ArrayLike[A] {

protected def coll = new ArrayView(xs)
def iterator() = coll.iterator()

def length = xs.length
def apply(i: Int) = xs.apply(i)

override def view = new ArrayView(xs)

def elemTag: ClassTag[A] = ClassTag(xs.getClass.getComponentType)

protected def fromIterableWithSameElemType(coll: Iterable[A]): Array[A] = coll.toArray[A](elemTag)

def fromIterable[B: ClassTag](coll: Iterable[B]): Array[B] = coll.toArray[B]

protected[this] def newBuilder = new ArrayBuffer[A].mapResult(_.toArray(elemTag))

override def knownSize = xs.length

override def className = "Array"

def map[B: ClassTag](f: A => B): Array[B] = fromIterable(View.Map(coll, f))
def flatMap[B: ClassTag](f: A => IterableOnce[B]): Array[B] = fromIterable(View.FlatMap(coll, f))
def ++[B >: A : ClassTag](xs: IterableOnce[B]): Array[B] = fromIterable(View.Concat(coll, xs))
def zip[B: ClassTag](xs: IterableOnce[B]): Array[(A, B)] = fromIterable(View.Zip(coll, xs))
}

case class ArrayView[A](xs: Array[A]) extends IndexedView[A] {
def length = xs.length
def apply(n: Int) = xs(n)
override def className = "ArrayView"
}
Loading