diff options
Diffstat (limited to 'src/library')
-rw-r--r-- | src/library/scala/collection/JavaConverters.scala | 12 | ||||
-rw-r--r-- | src/library/scala/collection/immutable/FilteredTraversableInternal.scala | 104 | ||||
-rw-r--r-- | src/library/scala/collection/immutable/List.scala | 2 | ||||
-rw-r--r-- | src/library/scala/collection/immutable/Map.scala | 2 | ||||
-rw-r--r-- | src/library/scala/collection/immutable/Set.scala | 2 | ||||
-rw-r--r-- | src/library/scala/collection/mutable/ArrayOps.scala | 76 | ||||
-rw-r--r-- | src/library/scala/collection/mutable/ListBuffer.scala | 4 | ||||
-rw-r--r-- | src/library/scala/collection/mutable/WrappedArray.scala | 71 | ||||
-rw-r--r-- | src/library/scala/concurrent/BatchingExecutor.scala | 2 | ||||
-rw-r--r-- | src/library/scala/concurrent/ExecutionContext.scala | 42 | ||||
-rw-r--r-- | src/library/scala/concurrent/package.scala | 43 | ||||
-rw-r--r-- | src/library/scala/sys/process/ProcessBuilder.scala | 7 | ||||
-rw-r--r-- | src/library/scala/util/Either.scala | 614 | ||||
-rw-r--r-- | src/library/scala/util/Properties.scala | 2 | ||||
-rw-r--r-- | src/library/scala/util/matching/Regex.scala | 46 |
15 files changed, 410 insertions, 619 deletions
diff --git a/src/library/scala/collection/JavaConverters.scala b/src/library/scala/collection/JavaConverters.scala index d48a1764e9..2337f0ef84 100644 --- a/src/library/scala/collection/JavaConverters.scala +++ b/src/library/scala/collection/JavaConverters.scala @@ -18,12 +18,12 @@ import convert._ * * The following conversions are supported via `asScala` and `asJava`: *{{{ - * scala.collection.Iterable <=> java.lang.Iterable - * scala.collection.Iterator <=> java.util.Iterator - * scala.collection.mutable.Buffer <=> java.util.List - * scala.collection.mutable.Set <=> java.util.Set - * scala.collection.mutable.Map <=> java.util.Map - * scala.collection.mutable.concurrent.Map <=> java.util.concurrent.ConcurrentMap + * scala.collection.Iterable <=> java.lang.Iterable + * scala.collection.Iterator <=> java.util.Iterator + * scala.collection.mutable.Buffer <=> java.util.List + * scala.collection.mutable.Set <=> java.util.Set + * scala.collection.mutable.Map <=> java.util.Map + * scala.collection.concurrent.Map <=> java.util.concurrent.ConcurrentMap *}}} * The following conversions are supported via `asScala` and through * specially-named extension methods to convert to Java collections, as shown: diff --git a/src/library/scala/collection/immutable/FilteredTraversableInternal.scala b/src/library/scala/collection/immutable/FilteredTraversableInternal.scala deleted file mode 100644 index 35585b7826..0000000000 --- a/src/library/scala/collection/immutable/FilteredTraversableInternal.scala +++ /dev/null @@ -1,104 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2003-2013, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - -package scala -package collection -package immutable - -import scala.annotation.tailrec - -/** - * Optimised filter functions for List - * n.b. this is an internal class to help maintain compatibility and should not be used directly. - */ -private[immutable] trait FilteredTraversableInternal[+A, +Repr <: AnyRef with TraversableLike[A, Repr]] extends TraversableLike[A, Repr] { - - // Optimized for List - - override def filter(p: A => Boolean): Self = filterImpl(p, isFlipped = false) - - override def filterNot(p: A => Boolean): Self = filterImpl(p, isFlipped = true) - - private[this] def filterImpl(p: A => Boolean, isFlipped: Boolean): Self = { - - // everything seen so far so far is not included - @tailrec def noneIn(l: Repr): Repr = { - if (l.isEmpty) - Nil.asInstanceOf[Repr] - else { - val h = l.head - val t = l.tail - if (p(h) != isFlipped) - allIn(l, t) - else - noneIn(t) - } - } - - // everything from 'start' is included, if everything from this point is in we can return the origin - // start otherwise if we discover an element that is out we must create a new partial list. - @tailrec def allIn(start: Repr, remaining: Repr): Repr = { - if (remaining.isEmpty) - start - else { - val x = remaining.head - if (p(x) != isFlipped) - allIn(start, remaining.tail) - else - partialFill(start, remaining) - } - } - - // we have seen elements that should be included then one that should be excluded, start building - def partialFill(origStart: Repr, firstMiss: Repr): Repr = { - val newHead = new ::(origStart.head, Nil) - var toProcess = origStart.tail - var currentLast = newHead - - // we know that all elements are :: until at least firstMiss.tail - while (!(toProcess eq firstMiss)) { - val newElem = new ::(toProcess.head, Nil) - currentLast.tl = newElem - currentLast = newElem - toProcess = toProcess.tail - } - - // at this point newHead points to a list which is a duplicate of all the 'in' elements up to the first miss. - // currentLast is the last element in that list. - - // now we are going to try and share as much of the tail as we can, only moving elements across when we have to. - var next = firstMiss.tail - var nextToCopy = next // the next element we would need to copy to our list if we cant share. - while (!next.isEmpty) { - // generally recommended is next.isNonEmpty but this incurs an extra method call. - val head: A = next.head - if (p(head) != isFlipped) { - next = next.tail - } else { - // its not a match - do we have outstanding elements? - while (!(nextToCopy eq next)) { - val newElem = new ::(nextToCopy.head, Nil) - currentLast.tl = newElem - currentLast = newElem - nextToCopy = nextToCopy.tail - } - nextToCopy = next.tail - next = next.tail - } - } - - // we have remaining elements - they are unchanged attach them to the end - if (!nextToCopy.isEmpty) - currentLast.tl = nextToCopy.asInstanceOf[List[A]] - - newHead.asInstanceOf[Repr] - } - - noneIn(repr) - } -}
\ No newline at end of file diff --git a/src/library/scala/collection/immutable/List.scala b/src/library/scala/collection/immutable/List.scala index e12ce7c2eb..550b987cb6 100644 --- a/src/library/scala/collection/immutable/List.scala +++ b/src/library/scala/collection/immutable/List.scala @@ -88,7 +88,6 @@ sealed abstract class List[+A] extends AbstractSeq[A] with Product with GenericTraversableTemplate[A, List] with LinearSeqOptimized[A, List[A]] - with FilteredTraversableInternal[A, List[A]] with scala.Serializable { override def companion: GenericCompanion[List] = List @@ -414,7 +413,6 @@ sealed abstract class List[+A] extends AbstractSeq[A] // Create a proxy for Java serialization that allows us to avoid mutation // during deserialization. This is the Serialization Proxy Pattern. protected final def writeReplace(): AnyRef = new List.SerializationProxy(this) - } /** The empty list. diff --git a/src/library/scala/collection/immutable/Map.scala b/src/library/scala/collection/immutable/Map.scala index cbdf7b39f5..4107b6414d 100644 --- a/src/library/scala/collection/immutable/Map.scala +++ b/src/library/scala/collection/immutable/Map.scala @@ -198,7 +198,7 @@ object Map extends ImmutableMapFactory[Map] { else if (key == key2) new Map4(key1, value1, key2, value, key3, value3, key4, value4) else if (key == key3) new Map4(key1, value1, key2, value2, key3, value, key4, value4) else if (key == key4) new Map4(key1, value1, key2, value2, key3, value3, key4, value) - else new HashMap + ((key1, value1), (key2, value2), (key3, value3), (key4, value4), (key, value)) + else (new HashMap).updated(key1,value1).updated(key2, value2).updated(key3, value3).updated(key4, value4).updated(key, value) def + [V1 >: V](kv: (K, V1)): Map[K, V1] = updated(kv._1, kv._2) def - (key: K): Map[K, V] = if (key == key1) new Map3(key2, value2, key3, value3, key4, value4) diff --git a/src/library/scala/collection/immutable/Set.scala b/src/library/scala/collection/immutable/Set.scala index 047ea736bd..0f16f97cb0 100644 --- a/src/library/scala/collection/immutable/Set.scala +++ b/src/library/scala/collection/immutable/Set.scala @@ -193,7 +193,7 @@ object Set extends ImmutableSetFactory[Set] { elem == elem1 || elem == elem2 || elem == elem3 || elem == elem4 def + (elem: A): Set[A] = if (contains(elem)) this - else new HashSet[A] + (elem1, elem2, elem3, elem4, elem) + else new HashSet[A] + elem1 + elem2 + elem3 + elem4 + elem def - (elem: A): Set[A] = if (elem == elem1) new Set3(elem2, elem3, elem4) else if (elem == elem2) new Set3(elem1, elem3, elem4) diff --git a/src/library/scala/collection/mutable/ArrayOps.scala b/src/library/scala/collection/mutable/ArrayOps.scala index 5de3dad256..0f83fd92c1 100644 --- a/src/library/scala/collection/mutable/ArrayOps.scala +++ b/src/library/scala/collection/mutable/ArrayOps.scala @@ -10,8 +10,6 @@ package scala package collection package mutable -import java.util - import scala.reflect.ClassTag import parallel.mutable.ParArray @@ -182,23 +180,6 @@ sealed trait ArrayOps[T] extends Any with ArrayLike[T, Array[T]] with CustomPara def seq = thisCollection } -/** to provide binary compat for 2.11 and 2.12 this class contains - * functionality that should be migrated to ArrayOps in 2.13 - * - */ -private[mutable] sealed trait ArrayOpsImpl[T] extends Any with ArrayOps[T] { - override final def slice(from: Int, until: Int): Array[T] = { - val start = if (from < 0) 0 else from - if (until <= start || start >= repr.length) - return emptyImpl - val end = if (until > length) length else until - sliceImpl(start, end) - } - protected def emptyImpl: Array[T] - protected def sliceImpl(from: Int, until: Int): Array[T] - -} - /** * A companion object for `ArrayOps`. * @@ -206,24 +187,12 @@ private[mutable] sealed trait ArrayOpsImpl[T] extends Any with ArrayOps[T] { */ object ArrayOps { - private val emptyByteArray = new Array[Byte](0) - private val emptyShortArray = new Array[Short](0) - private val emptyIntArray = new Array[Int](0) - private val emptyLongArray = new Array[Long](0) - private val emptyFloatArray = new Array[Float](0) - private val emptyDoubleArray = new Array[Double](0) - private val emptyUnitArray = new Array[Unit](0) - private val emptyCharArray = new Array[Char](0) - private val emptyBooleanArray = new Array[Boolean](0) - - /** A subclass of `ArrayOps` for arrays containing reference types. */ - final class ofRef[T <: AnyRef](override val repr: Array[T]) extends AnyVal with ArrayOpsImpl[T] with ArrayLike[T, Array[T]] { + /** A class of `ArrayOps` for arrays containing reference types. */ + final class ofRef[T <: AnyRef](override val repr: Array[T]) extends AnyVal with ArrayOps[T] with ArrayLike[T, Array[T]] { override protected[this] def thisCollection: WrappedArray[T] = new WrappedArray.ofRef[T](repr) override protected[this] def toCollection(repr: Array[T]): WrappedArray[T] = new WrappedArray.ofRef[T](repr) override protected[this] def newBuilder = new ArrayBuilder.ofRef[T]()(ClassTag[T](repr.getClass.getComponentType)) - protected override def emptyImpl:Array[T] = util.Arrays.copyOf[T](repr,0) - protected override def sliceImpl(from: Int, until: Int): Array[T] = util.Arrays.copyOfRange[T](repr, from, until) def length: Int = repr.length def apply(index: Int): T = repr(index) @@ -231,13 +200,11 @@ object ArrayOps { } /** A subclass of `ArrayOps` for arrays containing `Byte`s. */ - final class ofByte(override val repr: Array[Byte]) extends AnyVal with ArrayOpsImpl[Byte] with ArrayLike[Byte, Array[Byte]] { + final class ofByte(override val repr: Array[Byte]) extends AnyVal with ArrayOps[Byte] with ArrayLike[Byte, Array[Byte]] { override protected[this] def thisCollection: WrappedArray[Byte] = new WrappedArray.ofByte(repr) override protected[this] def toCollection(repr: Array[Byte]): WrappedArray[Byte] = new WrappedArray.ofByte(repr) override protected[this] def newBuilder = new ArrayBuilder.ofByte - protected override def emptyImpl = emptyByteArray - protected override def sliceImpl(from: Int, until: Int) = util.Arrays.copyOfRange(repr, from, until) def length: Int = repr.length def apply(index: Int): Byte = repr(index) @@ -245,13 +212,11 @@ object ArrayOps { } /** A subclass of `ArrayOps` for arrays containing `Short`s. */ - final class ofShort(override val repr: Array[Short]) extends AnyVal with ArrayOpsImpl[Short] with ArrayLike[Short, Array[Short]] { + final class ofShort(override val repr: Array[Short]) extends AnyVal with ArrayOps[Short] with ArrayLike[Short, Array[Short]] { override protected[this] def thisCollection: WrappedArray[Short] = new WrappedArray.ofShort(repr) override protected[this] def toCollection(repr: Array[Short]): WrappedArray[Short] = new WrappedArray.ofShort(repr) override protected[this] def newBuilder = new ArrayBuilder.ofShort - protected override def emptyImpl = emptyShortArray - protected override def sliceImpl(from: Int, until: Int) = util.Arrays.copyOfRange(repr, from, until) def length: Int = repr.length def apply(index: Int): Short = repr(index) @@ -259,13 +224,11 @@ object ArrayOps { } /** A subclass of `ArrayOps` for arrays containing `Char`s. */ - final class ofChar(override val repr: Array[Char]) extends AnyVal with ArrayOpsImpl[Char] with ArrayLike[Char, Array[Char]] { + final class ofChar(override val repr: Array[Char]) extends AnyVal with ArrayOps[Char] with ArrayLike[Char, Array[Char]] { override protected[this] def thisCollection: WrappedArray[Char] = new WrappedArray.ofChar(repr) override protected[this] def toCollection(repr: Array[Char]): WrappedArray[Char] = new WrappedArray.ofChar(repr) override protected[this] def newBuilder = new ArrayBuilder.ofChar - protected override def emptyImpl = emptyCharArray - protected override def sliceImpl(from: Int, until: Int) = util.Arrays.copyOfRange(repr, from, until) def length: Int = repr.length def apply(index: Int): Char = repr(index) @@ -273,13 +236,11 @@ object ArrayOps { } /** A subclass of `ArrayOps` for arrays containing `Int`s. */ - final class ofInt(override val repr: Array[Int]) extends AnyVal with ArrayOpsImpl[Int] with ArrayLike[Int, Array[Int]] { + final class ofInt(override val repr: Array[Int]) extends AnyVal with ArrayOps[Int] with ArrayLike[Int, Array[Int]] { override protected[this] def thisCollection: WrappedArray[Int] = new WrappedArray.ofInt(repr) override protected[this] def toCollection(repr: Array[Int]): WrappedArray[Int] = new WrappedArray.ofInt(repr) override protected[this] def newBuilder = new ArrayBuilder.ofInt - protected override def emptyImpl = emptyIntArray - protected override def sliceImpl(from: Int, until: Int) = util.Arrays.copyOfRange(repr, from, until) def length: Int = repr.length def apply(index: Int): Int = repr(index) @@ -287,13 +248,11 @@ object ArrayOps { } /** A subclass of `ArrayOps` for arrays containing `Long`s. */ - final class ofLong(override val repr: Array[Long]) extends AnyVal with ArrayOpsImpl[Long] with ArrayLike[Long, Array[Long]] { + final class ofLong(override val repr: Array[Long]) extends AnyVal with ArrayOps[Long] with ArrayLike[Long, Array[Long]] { override protected[this] def thisCollection: WrappedArray[Long] = new WrappedArray.ofLong(repr) override protected[this] def toCollection(repr: Array[Long]): WrappedArray[Long] = new WrappedArray.ofLong(repr) override protected[this] def newBuilder = new ArrayBuilder.ofLong - protected override def emptyImpl = emptyLongArray - protected override def sliceImpl(from: Int, until: Int) = util.Arrays.copyOfRange(repr, from, until) def length: Int = repr.length def apply(index: Int): Long = repr(index) @@ -301,13 +260,11 @@ object ArrayOps { } /** A subclass of `ArrayOps` for arrays containing `Float`s. */ - final class ofFloat(override val repr: Array[Float]) extends AnyVal with ArrayOpsImpl[Float] with ArrayLike[Float, Array[Float]] { + final class ofFloat(override val repr: Array[Float]) extends AnyVal with ArrayOps[Float] with ArrayLike[Float, Array[Float]] { override protected[this] def thisCollection: WrappedArray[Float] = new WrappedArray.ofFloat(repr) override protected[this] def toCollection(repr: Array[Float]): WrappedArray[Float] = new WrappedArray.ofFloat(repr) override protected[this] def newBuilder = new ArrayBuilder.ofFloat - protected override def emptyImpl = emptyFloatArray - protected override def sliceImpl(from: Int, until: Int) = util.Arrays.copyOfRange(repr, from, until) def length: Int = repr.length def apply(index: Int): Float = repr(index) @@ -315,13 +272,11 @@ object ArrayOps { } /** A subclass of `ArrayOps` for arrays containing `Double`s. */ - final class ofDouble(override val repr: Array[Double]) extends AnyVal with ArrayOpsImpl[Double] with ArrayLike[Double, Array[Double]] { + final class ofDouble(override val repr: Array[Double]) extends AnyVal with ArrayOps[Double] with ArrayLike[Double, Array[Double]] { override protected[this] def thisCollection: WrappedArray[Double] = new WrappedArray.ofDouble(repr) override protected[this] def toCollection(repr: Array[Double]): WrappedArray[Double] = new WrappedArray.ofDouble(repr) override protected[this] def newBuilder = new ArrayBuilder.ofDouble - protected override def emptyImpl = emptyDoubleArray - protected override def sliceImpl(from: Int, until: Int) = util.Arrays.copyOfRange(repr, from, until) def length: Int = repr.length def apply(index: Int): Double = repr(index) @@ -329,13 +284,11 @@ object ArrayOps { } /** A subclass of `ArrayOps` for arrays containing `Boolean`s. */ - final class ofBoolean(override val repr: Array[Boolean]) extends AnyVal with ArrayOpsImpl[Boolean] with ArrayLike[Boolean, Array[Boolean]] { + final class ofBoolean(override val repr: Array[Boolean]) extends AnyVal with ArrayOps[Boolean] with ArrayLike[Boolean, Array[Boolean]] { override protected[this] def thisCollection: WrappedArray[Boolean] = new WrappedArray.ofBoolean(repr) override protected[this] def toCollection(repr: Array[Boolean]): WrappedArray[Boolean] = new WrappedArray.ofBoolean(repr) override protected[this] def newBuilder = new ArrayBuilder.ofBoolean - protected override def emptyImpl = emptyBooleanArray - protected override def sliceImpl(from: Int, until: Int) = util.Arrays.copyOfRange(repr, from, until) def length: Int = repr.length def apply(index: Int): Boolean = repr(index) @@ -343,18 +296,11 @@ object ArrayOps { } /** A subclass of `ArrayOps` for arrays of `Unit` types. */ - final class ofUnit(override val repr: Array[Unit]) extends AnyVal with ArrayOpsImpl[Unit] with ArrayLike[Unit, Array[Unit]] { + final class ofUnit(override val repr: Array[Unit]) extends AnyVal with ArrayOps[Unit] with ArrayLike[Unit, Array[Unit]] { override protected[this] def thisCollection: WrappedArray[Unit] = new WrappedArray.ofUnit(repr) override protected[this] def toCollection(repr: Array[Unit]): WrappedArray[Unit] = new WrappedArray.ofUnit(repr) override protected[this] def newBuilder = new ArrayBuilder.ofUnit - protected override def emptyImpl = emptyUnitArray - protected override def sliceImpl(from: Int, until: Int) = { - // cant use util.Arrays.copyOfRange[Unit](repr, from, until) - Unit is special and doesnt compile - val res = new Array[Unit](until-from) - System.arraycopy(repr, from, res, 0, res.size) - res - } def length: Int = repr.length def apply(index: Int): Unit = repr(index) diff --git a/src/library/scala/collection/mutable/ListBuffer.scala b/src/library/scala/collection/mutable/ListBuffer.scala index 3bb7004184..aa79e972d5 100644 --- a/src/library/scala/collection/mutable/ListBuffer.scala +++ b/src/library/scala/collection/mutable/ListBuffer.scala @@ -119,6 +119,10 @@ final class ListBuffer[A] // Don't use the inherited size, which forwards to a List and is O(n). override def size = length + // Override with efficient implementations using the extra size information available to ListBuffer. + override def isEmpty: Boolean = len == 0 + override def nonEmpty: Boolean = len > 0 + // Implementations of abstract methods in Buffer override def apply(n: Int): A = diff --git a/src/library/scala/collection/mutable/WrappedArray.scala b/src/library/scala/collection/mutable/WrappedArray.scala index d0919c4357..0b5ebe7e9a 100644 --- a/src/library/scala/collection/mutable/WrappedArray.scala +++ b/src/library/scala/collection/mutable/WrappedArray.scala @@ -85,26 +85,12 @@ extends AbstractSeq[T] */ override protected[this] def newBuilder: Builder[T, WrappedArray[T]] = new WrappedArrayBuilder[T](elemTag) -} - -private[mutable] abstract class WrappedArrayImpl[T] extends WrappedArray[T] { - override def slice(from: Int, until: Int): WrappedArray[T] = { - val start = if (from < 0) 0 else from - if (until <= start || start >= repr.length) - return emptyImpl - val end = if (until > length) length else until - sliceImpl(start, end) - } - protected def emptyImpl: WrappedArray[T] - - protected def sliceImpl(from: Int, until: Int): WrappedArray[T] } /** A companion object used to create instances of `WrappedArray`. */ object WrappedArray { - import java.util // This is reused for all calls to empty. private val EmptyWrappedArray = new ofRef[AnyRef](new Array[AnyRef](0)) def empty[T <: AnyRef]: WrappedArray[T] = EmptyWrappedArray.asInstanceOf[WrappedArray[T]] @@ -138,17 +124,7 @@ object WrappedArray { def newBuilder[A]: Builder[A, IndexedSeq[A]] = new ArrayBuffer - private val emptyWrappedByte = new ofByte(new Array[Byte](0)) - private val emptyWrappedShort = new ofShort(new Array[Short](0)) - private val emptyWrappedInt = new ofInt(new Array[Int](0)) - private val emptyWrappedLong = new ofLong(new Array[Long](0)) - private val emptyWrappedFloat = new ofFloat(new Array[Float](0)) - private val emptyWrappedDouble = new ofDouble(new Array[Double](0)) - private val emptyWrappedUnit = new ofUnit(new Array[Unit](0)) - private val emptyWrappedChar = new ofChar(new Array[Char](0)) - private val emptyWrappedBoolean = new ofBoolean(new Array[Boolean](0)) - - final class ofRef[T <: AnyRef](val array: Array[T]) extends WrappedArrayImpl[T] with Serializable { + final class ofRef[T <: AnyRef](val array: Array[T]) extends WrappedArray[T] with Serializable { lazy val elemTag = ClassTag[T](array.getClass.getComponentType) def length: Int = array.length def apply(index: Int): T = array(index).asInstanceOf[T] @@ -158,11 +134,9 @@ object WrappedArray { case that: ofRef[_] => Arrays.equals(array.asInstanceOf[Array[AnyRef]], that.array.asInstanceOf[Array[AnyRef]]) case _ => super.equals(that) } - protected override def emptyImpl = new ofRef(util.Arrays.copyOf[T](array,0)) - protected override def sliceImpl(from: Int, until: Int) = new ofRef[T](util.Arrays.copyOfRange[T](array, from, until)) } - final class ofByte(val array: Array[Byte]) extends WrappedArrayImpl[Byte] with Serializable { + final class ofByte(val array: Array[Byte]) extends WrappedArray[Byte] with Serializable { def elemTag = ClassTag.Byte def length: Int = array.length def apply(index: Int): Byte = array(index) @@ -172,11 +146,9 @@ object WrappedArray { case that: ofByte => Arrays.equals(array, that.array) case _ => super.equals(that) } - protected override def emptyImpl = emptyWrappedByte - protected override def sliceImpl(from: Int, until: Int) = new ofByte(util.Arrays.copyOfRange(array, from, until)) } - final class ofShort(val array: Array[Short]) extends WrappedArrayImpl[Short] with Serializable { + final class ofShort(val array: Array[Short]) extends WrappedArray[Short] with Serializable { def elemTag = ClassTag.Short def length: Int = array.length def apply(index: Int): Short = array(index) @@ -186,11 +158,9 @@ object WrappedArray { case that: ofShort => Arrays.equals(array, that.array) case _ => super.equals(that) } - protected override def emptyImpl = emptyWrappedShort - protected override def sliceImpl(from: Int, until: Int) = new ofShort(util.Arrays.copyOfRange(array, from, until)) } - final class ofChar(val array: Array[Char]) extends WrappedArrayImpl[Char] with Serializable { + final class ofChar(val array: Array[Char]) extends WrappedArray[Char] with Serializable { def elemTag = ClassTag.Char def length: Int = array.length def apply(index: Int): Char = array(index) @@ -200,11 +170,9 @@ object WrappedArray { case that: ofChar => Arrays.equals(array, that.array) case _ => super.equals(that) } - protected override def emptyImpl = emptyWrappedChar - protected override def sliceImpl(from: Int, until: Int) = new ofChar(util.Arrays.copyOfRange(array, from, until)) } - final class ofInt(val array: Array[Int]) extends WrappedArrayImpl[Int] with Serializable { + final class ofInt(val array: Array[Int]) extends WrappedArray[Int] with Serializable { def elemTag = ClassTag.Int def length: Int = array.length def apply(index: Int): Int = array(index) @@ -214,11 +182,9 @@ object WrappedArray { case that: ofInt => Arrays.equals(array, that.array) case _ => super.equals(that) } - protected override def emptyImpl = emptyWrappedInt - protected override def sliceImpl(from: Int, until: Int) = new ofInt(util.Arrays.copyOfRange(array, from, until)) } - final class ofLong(val array: Array[Long]) extends WrappedArrayImpl[Long] with Serializable { + final class ofLong(val array: Array[Long]) extends WrappedArray[Long] with Serializable { def elemTag = ClassTag.Long def length: Int = array.length def apply(index: Int): Long = array(index) @@ -228,11 +194,9 @@ object WrappedArray { case that: ofLong => Arrays.equals(array, that.array) case _ => super.equals(that) } - protected override def emptyImpl = emptyWrappedLong - protected override def sliceImpl(from: Int, until: Int) = new ofLong(util.Arrays.copyOfRange(array, from, until)) } - final class ofFloat(val array: Array[Float]) extends WrappedArrayImpl[Float] with Serializable { + final class ofFloat(val array: Array[Float]) extends WrappedArray[Float] with Serializable { def elemTag = ClassTag.Float def length: Int = array.length def apply(index: Int): Float = array(index) @@ -242,11 +206,9 @@ object WrappedArray { case that: ofFloat => Arrays.equals(array, that.array) case _ => super.equals(that) } - protected override def emptyImpl = emptyWrappedFloat - protected override def sliceImpl(from: Int, until: Int) = new ofFloat(util.Arrays.copyOfRange(array, from, until)) } - final class ofDouble(val array: Array[Double]) extends WrappedArrayImpl[Double] with Serializable { + final class ofDouble(val array: Array[Double]) extends WrappedArray[Double] with Serializable { def elemTag = ClassTag.Double def length: Int = array.length def apply(index: Int): Double = array(index) @@ -256,11 +218,9 @@ object WrappedArray { case that: ofDouble => Arrays.equals(array, that.array) case _ => super.equals(that) } - protected override def emptyImpl = emptyWrappedDouble - protected override def sliceImpl(from: Int, until: Int) = new ofDouble(util.Arrays.copyOfRange(array, from, until)) } - final class ofBoolean(val array: Array[Boolean]) extends WrappedArrayImpl[Boolean] with Serializable { + final class ofBoolean(val array: Array[Boolean]) extends WrappedArray[Boolean] with Serializable { def elemTag = ClassTag.Boolean def length: Int = array.length def apply(index: Int): Boolean = array(index) @@ -270,11 +230,9 @@ object WrappedArray { case that: ofBoolean => Arrays.equals(array, that.array) case _ => super.equals(that) } - protected override def emptyImpl = emptyWrappedBoolean - protected override def sliceImpl(from: Int, until: Int) = new ofBoolean(util.Arrays.copyOfRange(array, from, until)) } - final class ofUnit(val array: Array[Unit]) extends WrappedArrayImpl[Unit] with Serializable { + final class ofUnit(val array: Array[Unit]) extends WrappedArray[Unit] with Serializable { def elemTag = ClassTag.Unit def length: Int = array.length def apply(index: Int): Unit = array(index) @@ -284,14 +242,5 @@ object WrappedArray { case that: ofUnit => array.length == that.array.length case _ => super.equals(that) } - protected override def emptyImpl = emptyWrappedUnit - protected override def sliceImpl(from: Int, until: Int) = { - // cant use - // new ofUnit(util.Arrays.copyOfRange[Unit](array, from, until)) - Unit is special and doesnt compile - // cant use util.Arrays.copyOfRange[Unit](repr, from, until) - Unit is special and doesnt compile - val res = new Array[Unit](until-from) - System.arraycopy(repr, from, res, 0, until-from) - new ofUnit(res) - } } } diff --git a/src/library/scala/concurrent/BatchingExecutor.scala b/src/library/scala/concurrent/BatchingExecutor.scala index a0d7aaea47..fd31f3470e 100644 --- a/src/library/scala/concurrent/BatchingExecutor.scala +++ b/src/library/scala/concurrent/BatchingExecutor.scala @@ -103,7 +103,7 @@ private[concurrent] trait BatchingExecutor extends Executor { override def execute(runnable: Runnable): Unit = { if (batchable(runnable)) { // If we can batch the runnable _tasksLocal.get match { - case null => unbatchedExecute(new Batch(List(runnable))) // If we aren't in batching mode yet, enqueue batch + case null => unbatchedExecute(new Batch(runnable :: Nil)) // If we aren't in batching mode yet, enqueue batch case some => _tasksLocal.set(runnable :: some) // If we are already in batching mode, add to batch } } else unbatchedExecute(runnable) // If not batchable, just delegate to underlying diff --git a/src/library/scala/concurrent/ExecutionContext.scala b/src/library/scala/concurrent/ExecutionContext.scala index fe684e4d46..f46f294387 100644 --- a/src/library/scala/concurrent/ExecutionContext.scala +++ b/src/library/scala/concurrent/ExecutionContext.scala @@ -25,21 +25,20 @@ import scala.annotation.implicitNotFound * and an implicit `ExecutionContext`. The implicit `ExecutionContext` * will be used to execute the callback. * - * It is possible to simply import + * While it is possible to simply import * `scala.concurrent.ExecutionContext.Implicits.global` to obtain an - * implicit `ExecutionContext`. This global context is a reasonable - * default thread pool. - * - * However, application developers should carefully consider where they - * want to set policy; ideally, one place per application (or per - * logically-related section of code) will make a decision about - * which `ExecutionContext` to use. That is, you might want to avoid - * hardcoding `scala.concurrent.ExecutionContext.Implicits.global` all - * over the place in your code. - * One approach is to add `(implicit ec: ExecutionContext)` - * to methods which need an `ExecutionContext`. Then import a specific - * context in one place for the entire application or module, - * passing it implicitly to individual methods. + * implicit `ExecutionContext`, application developers should carefully + * consider where they want to set execution policy; + * ideally, one place per application—or per logically related section of code— + * will make a decision about which `ExecutionContext` to use. + * That is, you will mostly want to avoid hardcoding, especially via an import, + * `scala.concurrent.ExecutionContext.Implicits.global`. + * The recommended approach is to add `(implicit ec: ExecutionContext)` to methods, + * or class constructor parameters, which need an `ExecutionContext`. + * + * Then locally import a specific `ExecutionContext` in one place for the entire + * application or module, passing it implicitly to individual methods. + * Alternatively define a local implicit val with the required `ExecutionContext`. * * A custom `ExecutionContext` may be appropriate to execute code * which blocks on IO or performs long-running computations. @@ -111,9 +110,18 @@ object ExecutionContext { * The explicit global `ExecutionContext`. Invoke `global` when you want to provide the global * `ExecutionContext` explicitly. * - * The default `ExecutionContext` implementation is backed by a work-stealing thread pool. By default, - * the thread pool uses a target number of worker threads equal to the number of - * [[https://docs.oracle.com/javase/8/docs/api/java/lang/Runtime.html#availableProcessors-- available processors]]. + * The default `ExecutionContext` implementation is backed by a work-stealing thread pool. + * It can be configured via the following [[scala.sys.SystemProperties]]: + * + * `scala.concurrent.context.minThreads` = defaults to "1" + * `scala.concurrent.context.numThreads` = defaults to "x1" (i.e. the current number of available processors * 1) + * `scala.concurrent.context.maxThreads` = defaults to "x1" (i.e. the current number of available processors * 1) + * `scala.concurrent.context.maxExtraThreads` = defaults to "256" + * + * The pool size of threads is then `numThreads` bounded by `minThreads` on the lower end and `maxThreads` on the high end. + * + * The `maxExtraThreads` is the maximum number of extra threads to have at any given time to evade deadlock, + * see [[scala.concurrent.BlockContext]]. * * @return the global `ExecutionContext` */ diff --git a/src/library/scala/concurrent/package.scala b/src/library/scala/concurrent/package.scala index 667a7547ac..0695ee3351 100644 --- a/src/library/scala/concurrent/package.scala +++ b/src/library/scala/concurrent/package.scala @@ -22,12 +22,31 @@ import scala.annotation.implicitNotFound * == Common Imports == * * When working with Futures, you will often find that importing the whole concurrent - * package is convenient, furthermore you are likely to need an implicit ExecutionContext - * in scope for many operations involving Futures and Promises: + * package is convenient: * * {{{ * import scala.concurrent._ - * import ExecutionContext.Implicits.global + * }}} + * + * When using things like `Future`s, it is often required to have an implicit `ExecutionContext` + * in scope. The general advice for these implicits are as follows. + * + * If the code in question is a class or method definition, and no `ExecutionContext` is available, + * request one from the caller by adding an implicit parameter list: + * + * {{{ + * def myMethod(myParam: MyType)(implicit ec: ExecutionContext) = … + * //Or + * class MyClass(myParam: MyType)(implicit ec: ExecutionContext) { … } + * }}} + * + * This allows the caller of the method, or creator of the instance of the class, to decide which + * `ExecutionContext` should be used. + * + * For typical REPL usage and experimentation, importing the global `ExecutionContext` is often desired. + * + * {{{ + * import scala.concurrent.ExcutionContext.Implicits.global * }}} * * == Specifying Durations == @@ -140,17 +159,20 @@ package concurrent { /** * `Await` is what is used to ensure proper handling of blocking for `Awaitable` instances. * - * While occasionally useful, e.g. for testing, it is recommended that you avoid Await - * when possible in favor of callbacks and combinators like onComplete and use in - * for comprehensions. Await will block the thread on which it runs, and could cause - * performance and deadlock issues. + * While occasionally useful, e.g. for testing, it is recommended that you avoid Await whenever possible— + * instead favoring combinators and/or callbacks. + * Await's `result` and `ready` methods will block the calling thread's execution until they return, + * which will cause performance degradation, and possibly, deadlock issues. */ object Await { /** * Await the "completed" state of an `Awaitable`. * * Although this method is blocking, the internal use of [[scala.concurrent.blocking blocking]] ensures that - * the underlying [[ExecutionContext]] is prepared to properly manage the blocking. + * the underlying [[ExecutionContext]] is given an opportunity to properly manage the blocking. + * + * WARNING: It is strongly discouraged to supply lengthy timeouts since the progress of the calling thread will be + * suspended—blocked—until either the `Awaitable` becomes ready or the timeout expires. * * @param awaitable * the `Awaitable` to be awaited @@ -172,7 +194,10 @@ package concurrent { * Await and return the result (of type `T`) of an `Awaitable`. * * Although this method is blocking, the internal use of [[scala.concurrent.blocking blocking]] ensures that - * the underlying [[ExecutionContext]] to properly detect blocking and ensure that there are no deadlocks. + * the underlying [[ExecutionContext]] is given an opportunity to properly manage the blocking. + * + * WARNING: It is strongly discouraged to supply lengthy timeouts since the progress of the calling thread will be + * suspended—blocked—until either the `Awaitable` has a result or the timeout expires. * * @param awaitable * the `Awaitable` to be awaited diff --git a/src/library/scala/sys/process/ProcessBuilder.scala b/src/library/scala/sys/process/ProcessBuilder.scala index b7966b0341..d0745e5833 100644 --- a/src/library/scala/sys/process/ProcessBuilder.scala +++ b/src/library/scala/sys/process/ProcessBuilder.scala @@ -257,10 +257,9 @@ trait ProcessBuilder extends Source with Sink { */ def run(connectInput: Boolean): Process - /** Starts the process represented by this builder, blocks until it exits, and - * returns the exit code. Standard output and error are sent to the given - * ProcessLogger. The newly started process reads from standard input of the - * current process if `connectInput` is true. + /** Starts the process represented by this builder. Standard output and error + * are sent to the given ProcessLogger. The newly started process reads from + * standard input of the current process if `connectInput` is true. */ def run(log: ProcessLogger, connectInput: Boolean): Process diff --git a/src/library/scala/util/Either.scala b/src/library/scala/util/Either.scala index 523c10c483..d295478698 100644 --- a/src/library/scala/util/Either.scala +++ b/src/library/scala/util/Either.scala @@ -6,54 +6,52 @@ ** |/ ** \* */ - - package scala package util /** Represents a value of one of two possible types (a disjoint union.) - * An instance of Either is either an instance of [[scala.util.Left]] or [[scala.util.Right]]. + * An instance of `Either` is an instance of either [[scala.util.Left]] or [[scala.util.Right]]. * - * A common use of Either is as an alternative to [[scala.Option]] for dealing - * with possible missing values. In this usage, [[scala.None]] is replaced + * A common use of `Either` is as an alternative to [[scala.Option]] for dealing + * with possibly missing values. In this usage, [[scala.None]] is replaced * with a [[scala.util.Left]] which can contain useful information. * [[scala.util.Right]] takes the place of [[scala.Some]]. Convention dictates - * that Left is used for failure and Right is used for success. + * that `Left` is used for failure and `Right` is used for success. * - * For example, you could use `Either[String, Int]` to detect whether a - * received input is a String or an Int. + * For example, you could use `Either[String, Int]` to indicate whether a + * received input is a `String` or an `Int`. * * {{{ - * val in = Console.readLine("Type Either a string or an Int: ") - * val result: Either[String,Int] = try { - * Right(in.toInt) - * } catch { - * case e: Exception => - * Left(in) - * } + * import scala.io.StdIn._ + * val in = readLine("Type Either a string or an Int: ") + * val result: Either[String,Int] = + * try Right(in.toInt) + * catch { + * case e: NumberFormatException => Left(in) + * } * - * println(result match { + * result match { * case Right(x) => s"You passed me the Int: $x, which I will increment. $x + 1 = ${x+1}" * case Left(x) => s"You passed me the String: $x" - * }) + * } * }}} * - * Either is right-biased, which means that Right is assumed to be the default case to - * operate on. If it is Left, operations like map, flatMap, ... return the Left value - * unchanged: + * `Either` is right-biased, which means that `Right` is assumed to be the default case to + * operate on. If it is `Left`, operations like `map` and `flatMap` return the `Left` value unchanged: * * {{{ - * Right(12).map(_ * 2) // Right(24) - * Left(23).map(_ * 2) // Left(23) + * def doubled(i: Int) = i * 2 + * Right(42).map(doubled) // Right(84) + * Left(42).map(doubled) // Left(42) * }}} * - * As Either defines the methods `map` and `flatMap`, it can also be used in for comprehensions: + * Since `Either` defines the methods `map` and `flatMap`, it can also be used in for comprehensions: * {{{ - * val right1: Right[Double, Int] = Right(1) - * val right2 = Right(2) - * val right3 = Right(3) - * val left23: Left[Double, Int] = Left(23.0) - * val left42 = Left(42.0) + * val right1 = Right(1) : Right[Double, Int] + * val right2 = Right(2) + * val right3 = Right(3) + * val left23 = Left(23.0) : Left[Double, Int] + * val left42 = Left(42.0) * * for { * a <- right1 @@ -73,8 +71,9 @@ package util * c <- right2 * } yield a + b + c // Left(23.0) * - * // It is advisable to provide the type of the “missing” value (especially the right value for `Left`) - * // as otherwise that type might be inferred as `Nothing` without context: + * // It may be necessary to provide the type of the “missing” value, especially the type + * // of the right value for `Left`. Otherwise, without any context that constrains the type, + * // it might be inferred as `Nothing`: * for { * a <- left23 * b <- right1 @@ -92,77 +91,69 @@ package util * @since 2.7 */ sealed abstract class Either[+A, +B] extends Product with Serializable { - /** - * Projects this `Either` as a `Left`. - */ + /** Projects this `Either` as a `Left`. */ def left = Either.LeftProjection(this) - /** - * Projects this `Either` as a `Right`. + /** Projects this `Either` as a `Right`. * - * Because `Either` is right-biased, this method is not normally needed. - * (It is retained in the API for now for easy cross-compilation between Scala - * 2.11 and 2.12.) + * Because `Either` is right-biased, this method is not normally needed. */ def right = Either.RightProjection(this) - /** - * Applies `fa` if this is a `Left` or `fb` if this is a `Right`. + /** Applies `fa` if this is a `Left` or `fb` if this is a `Right`. * - * @example {{{ - * val result: Either[Exception, Value] = possiblyFailingOperation() - * log(result.fold( - * ex => s"Operation failed with $ex", - * v => s"Operation produced value: $v" - * )) - * }}} + * @example {{{ + * val result = util.Try("42".toInt).toEither + * result.fold( + * e => s"Operation failed with $e", + * v => s"Operation produced value: $v" + * ) + * }}} * - * @param fa the function to apply if this is a `Left` - * @param fb the function to apply if this is a `Right` - * @return the results of applying the function + * @param fa the function to apply if this is a `Left` + * @param fb the function to apply if this is a `Right` + * @return the results of applying the function */ def fold[C](fa: A => C, fb: B => C): C = this match { case Right(b) => fb(b) case Left(a) => fa(a) } - /** - * If this is a `Left`, then return the left value in `Right` or vice versa. + /** If this is a `Left`, then return the left value in `Right` or vice versa. * - * @example {{{ - * val left: Either[String, Int] = Left("left") - * val right: Either[Int, String] = l.swap // Result: Right("left") - * }}} - * @example {{{ - * val right = Right(2) - * val left = Left(3) - * for { - * r1 <- right - * r2 <- left.swap - * } yield r1 * r2 // Right(6) - * }}} + * @example {{{ + * val left: Either[String, Int] = Left("left") + * val right: Either[Int, String] = left.swap // Result: Right("left") + * }}} + * @example {{{ + * val right = Right(2) + * val left = Left(3) + * for { + * r1 <- right + * r2 <- left.swap + * } yield r1 * r2 // Right(6) + * }}} */ def swap: Either[B, A] = this match { case Left(a) => Right(a) case Right(b) => Left(b) } - /** - * Joins an `Either` through `Right`. + /** Joins an `Either` through `Right`. * - * This method requires that the right side of this Either is itself an - * Either type. That is, this must be some type like: {{{ - * Either[A, Either[A, C]] - * }}} (which respects the type parameter bounds, shown below.) + * This method requires that the right side of this `Either` is itself + * an `Either` type. That is, this must be some type like: {{{ + * Either[A, Either[A, C]] + * }}} (which respects the type parameter bounds, shown below.) * - * If this instance is a Right[Either[A, C]] then the contained Either[A, C] - * will be returned, otherwise this value will be returned unmodified. + * If this instance is a `Right[Either[A, C]]` then the contained `Either[A, C]` + * will be returned, otherwise this value will be returned unmodified. * - * @example {{{ - * Right[String, Either[String, Int]](Right(12)).joinRight // Result: Right(12) - * Right[String, Either[String, Int]](Left("flower")).joinRight // Result: Left("flower") - * Left[String, Either[String, Int]]("flower").joinRight // Result: Left("flower") - * }}} + * @example {{{ + * Right[String, Either[String, Int]](Right(12)).joinRight // Result: Right(12) + * Right[String, Either[String, Int]](Left("flower")).joinRight // Result: Left("flower") + * Left[String, Either[String, Int]]("flower").joinRight // Result: Left("flower") + * }}} * * This method, and `joinLeft`, are analogous to `Option#flatten` */ @@ -172,51 +163,48 @@ sealed abstract class Either[+A, +B] extends Product with Serializable { } - /** - * Joins an `Either` through `Left`. + /** Joins an `Either` through `Left`. * - * This method requires that the left side of this Either is itself an - * Either type. That is, this must be some type like: {{{ - * Either[Either[C, B], B] - * }}} (which respects the type parameter bounds, shown below.) + * This method requires that the left side of this `Either` is itself an + * `Either` type. That is, this must be some type like: {{{ + * Either[Either[C, B], B] + * }}} (which respects the type parameter bounds, shown below.) * - * If this instance is a Left[Either[C, B]] then the contained Either[C, B] - * will be returned, otherwise this value will be returned unmodified. + * If this instance is a `Left[Either[C, B]]` then the contained `Either[C, B]` + * will be returned, otherwise this value will be returned unmodified. * - * {{{ - * Left[Either[Int, String], String](Right("flower")).joinLeft // Result: Right("flower") - * Left[Either[Int, String], String](Left(12)).joinLeft // Result: Left(12) - * Right[Either[Int, String], String]("daisy").joinLeft // Result: Right("daisy") - * }}} + * {{{ + * Left[Either[Int, String], String](Right("flower")).joinLeft // Result: Right("flower") + * Left[Either[Int, String], String](Left(12)).joinLeft // Result: Left(12) + * Right[Either[Int, String], String]("daisy").joinLeft // Result: Right("daisy") + * }}} * - * This method, and `joinRight`, are analogous to `Option#flatten` + * This method, and `joinRight`, are analogous to `Option#flatten`. */ def joinLeft[A1 >: A, B1 >: B, C](implicit ev: A1 <:< Either[C, B1]): Either[C, B1] = this match { case Left(a) => a case Right(b) => this.asInstanceOf[Either[C, B1]] } - /** - * Executes the given side-effecting function if this is a `Right`. + /** Executes the given side-effecting function if this is a `Right`. * - * {{{ - * Right(12).foreach(x => println(x)) // prints "12" - * Left(12).foreach(x => println(x)) // doesn't print - * }}} - * @param f The side-effecting function to execute. + * {{{ + * Right(12).foreach(println) // prints "12" + * Left(12).foreach(println) // doesn't print + * }}} + * @param f The side-effecting function to execute. */ def foreach[U](f: B => U): Unit = this match { case Right(b) => f(b) case Left(_) => } - /** - * Returns the value from this `Right` or the given argument if this is a `Left`. + /** Returns the value from this `Right` or the given argument if this is a `Left`. * - * {{{ - * Right(12).getOrElse(17) // 12 - * Left(12).getOrElse(17) // 17 - * }}} + * {{{ + * Right(12).getOrElse(17) // 12 + * Left(12).getOrElse(17) // 17 + * }}} */ def getOrElse[BB >: B](or: => BB): BB = this match { case Right(b) => b @@ -233,7 +221,7 @@ sealed abstract class Either[+A, +B] extends Product with Serializable { * // Returns false because value of Right is "something" which does not equal "anything". * Right("something") contains "anything" * - * // Returns false because there is no value for Right. + * // Returns false because it's not a Right value. * Left("something") contains "something" * }}} * @@ -245,53 +233,49 @@ sealed abstract class Either[+A, +B] extends Product with Serializable { case Left(_) => false } - /** - * Returns `true` if `Left` or returns the result of the application of - * the given predicate to the `Right` value. + /** Returns `true` if `Left` or returns the result of the application of + * the given predicate to the `Right` value. * - * {{{ - * Right(12).forall(_ > 10) // true - * Right(7).forall(_ > 10) // false - * Left(12).forall(_ > 10) // true - * }}} + * {{{ + * Right(12).forall(_ > 10) // true + * Right(7).forall(_ > 10) // false + * Left(12).forall(_ => false) // true + * }}} */ def forall(f: B => Boolean): Boolean = this match { case Right(b) => f(b) case Left(_) => true } - /** - * Returns `false` if `Left` or returns the result of the application of - * the given predicate to the `Right` value. + /** Returns `false` if `Left` or returns the result of the application of + * the given predicate to the `Right` value. * - * {{{ - * Right(12).exists(_ > 10) // true - * Right(7).exists(_ > 10) // false - * Left(12).exists(_ > 10) // false - * }}} + * {{{ + * Right(12).exists(_ > 10) // true + * Right(7).exists(_ > 10) // false + * Left(12).exists(_ => true) // false + * }}} */ def exists(p: B => Boolean): Boolean = this match { case Right(b) => p(b) case Left(_) => false } - /** - * Binds the given function across `Right`. + /** Binds the given function across `Right`. * - * @param f The function to bind across `Right`. + * @param f The function to bind across `Right`. */ def flatMap[AA >: A, Y](f: B => Either[AA, Y]): Either[AA, Y] = this match { case Right(b) => f(b) case Left(a) => this.asInstanceOf[Either[AA, Y]] } - /** - * The given function is applied if this is a `Right`. + /** The given function is applied if this is a `Right`. * - * {{{ - * Right(12).map(x => "flower") // Result: Right("flower") - * Left(12).map(x => "flower") // Result: Left(12) - * }}} + * {{{ + * Right(12).map(x => "flower") // Result: Right("flower") + * Left(12).map(x => "flower") // Result: Left(12) + * }}} */ def map[Y](f: B => Y): Either[A, Y] = this match { case Right(b) => Right(f(b)) @@ -303,9 +287,9 @@ sealed abstract class Either[+A, +B] extends Product with Serializable { * returns `Left` with the existing value of `Left` if this is a `Left`. * * {{{ - * Right(12).filterOrElse(_ > 10, -1) // Right(12) - * Right(7).filterOrElse(_ > 10, -1) // Left(-1) - * Left(12).filterOrElse(_ > 10, -1) // Left(12) + * Right(12).filterOrElse(_ > 10, -1) // Right(12) + * Right(7).filterOrElse(_ > 10, -1) // Left(-1) + * Left(7).filterOrElse(_ => false, -1) // Left(7) * }}} */ def filterOrElse[AA >: A](p: B => Boolean, zero: => AA): Either[AA, B] = this match { @@ -344,32 +328,29 @@ sealed abstract class Either[+A, +B] extends Product with Serializable { case Left(a) => Failure(a) } - /** - * Returns `true` if this is a `Left`, `false` otherwise. + /** Returns `true` if this is a `Left`, `false` otherwise. * - * {{{ - * Left("tulip").isLeft // true - * Right("venus fly-trap").isLeft // false - * }}} + * {{{ + * Left("tulip").isLeft // true + * Right("venus fly-trap").isLeft // false + * }}} */ def isLeft: Boolean - /** - * Returns `true` if this is a `Right`, `false` otherwise. + /** Returns `true` if this is a `Right`, `false` otherwise. * - * {{{ - * Left("tulip").isRight // false - * Right("venus fly-trap").isRight // true - * }}} + * {{{ + * Left("tulip").isRight // false + * Right("venus fly-trap").isRight // true + * }}} */ def isRight: Boolean } -/** - * The left side of the disjoint union, as opposed to the [[scala.util.Right]] side. +/** The left side of the disjoint union, as opposed to the [[scala.util.Right]] side. * - * @author <a href="mailto:research@workingmouse.com">Tony Morris</a>, Workingmouse - * @version 1.0, 11/10/2008 + * @author <a href="mailto:research@workingmouse.com">Tony Morris</a>, Workingmouse + * @version 1.0, 11/10/2008 */ final case class Left[+A, +B](@deprecatedName('a, "2.12.0") value: A) extends Either[A, B] { def isLeft = true @@ -378,11 +359,10 @@ final case class Left[+A, +B](@deprecatedName('a, "2.12.0") value: A) extends Ei @deprecated("Use .value instead.", "2.12.0") def a: A = value } -/** - * The right side of the disjoint union, as opposed to the [[scala.util.Left]] side. +/** The right side of the disjoint union, as opposed to the [[scala.util.Left]] side. * - * @author <a href="mailto:research@workingmouse.com">Tony Morris</a>, Workingmouse - * @version 1.0, 11/10/2008 + * @author <a href="mailto:research@workingmouse.com">Tony Morris</a>, Workingmouse + * @version 1.0, 11/10/2008 */ final case class Right[+A, +B](@deprecatedName('b, "2.12.0") value: B) extends Either[A, B] { def isLeft = false @@ -396,27 +376,26 @@ object Either { /** If the condition is satisfied, return the given `B` in `Right`, * otherwise, return the given `A` in `Left`. * - * {{{ - * val userInput: String = ... - * Either.cond( - * userInput.forall(_.isDigit) && userInput.size == 10, - * PhoneNumber(userInput), - * "The input (%s) does not look like a phone number".format(userInput) - * }}} + * {{{ + * val userInput: String = ... + * Either.cond( + * userInput.forall(_.isDigit) && userInput.size == 10, + * PhoneNumber(userInput), + * "The input (%s) does not look like a phone number".format(userInput) + * }}} */ def cond[X, Y](test: Boolean, right: => Y, left: => X): Either[X, Y] = if (test) Right(right) else Left(left) - /** - * Allows use of a `merge` method to extract values from Either instances - * regardless of whether they are Left or Right. + /** Allows use of a `merge` method to extract values from Either instances + * regardless of whether they are Left or Right. * - * {{{ - * val l = Left(List(1)): Either[List[Int], Vector[Int]] - * val r = Right(Vector(1)): Either[List[Int], Vector[Int]] - * l.merge: Seq[Int] // List(1) - * r.merge: Seq[Int] // Vector(1) - * }}} + * {{{ + * val l = Left(List(1)): Either[List[Int], Vector[Int]] + * val r = Right(Vector(1)): Either[List[Int], Vector[Int]] + * l.merge: Seq[Int] // List(1) + * r.merge: Seq[Int] // Vector(1) + * }}} */ implicit class MergeableEither[A](private val x: Either[A, A]) extends AnyVal { def merge: A = x match { @@ -425,65 +404,58 @@ object Either { } } - /** - * Projects an `Either` into a `Left`. - * - * This allows for-comprehensions over the left side of Either instances, - * reversing Either's usual right-bias. + /** Projects an `Either` into a `Left`. * - * For example {{{ - * for (s <- Left("flower").left) yield s.length // Left(6) - * }}} + * This allows for-comprehensions over the left side of Either instances, + * reversing Either's usual right-bias. * - * Continuing the analogy with [[scala.Option]], a `LeftProjection` declares - * that `Left` should be analogous to `Some` in some code. + * For example {{{ + * for (s <- Left("flower").left) yield s.length // Left(6) + * }}} * - * {{{ - * // using Option: - * def interactWithDB(x: Query): Option[Result] = - * try { - * Some(getResultFromDatabase(x)) - * } catch { - * case ex => None - * } + * Continuing the analogy with [[scala.Option]], a `LeftProjection` declares + * that `Left` should be analogous to `Some` in some code. * - * // this will only be executed if interactWithDB returns a Some - * val report = - * for (r <- interactWithDB(someQuery)) yield generateReport(r) - * if (report.isDefined) - * send(report) - * else - * log("report not generated, not sure why...") - * }}} + * {{{ + * // using Option: + * def interactWithDB(x: Query): Option[Result] = + * try Some(getResultFromDatabase(x)) + * catch { + * case _: SQLException => None + * } + * + * // this will only be executed if interactWithDB returns a Some + * val report = for (result <- interactWithDB(someQuery)) yield generateReport(result) + * report match { + * case Some(r) => send(r) + * case None => log("report not generated, not sure why...") + * }}} * - * {{{ - * // using Either - * def interactWithDB(x: Query): Either[Exception, Result] = - * try { - * Right(getResultFromDatabase(x)) - * } catch { - * case ex => Left(ex) + * {{{ + * // using Either + * def interactWithDB(x: Query): Either[Exception, Result] = + * try Right(getResultFromDatabase(x)) + * catch { + * case e: SQLException => Left(e) + * } + * + * // this will only be executed if interactWithDB returns a Right + * val report = for (result <- interactWithDB(someQuery).right) yield generateReport(result) + * report match { + * case Right(r) => send(r) + * case Left(e) => log(s"report not generated, reason was $e") * } + * }}} * - * // this will only be executed if interactWithDB returns a Right - * val report = - * for (r <- interactWithDB(someQuery).right) yield generateReport(r) - * if (report.isRight) - * send(report) - * else - * log("report not generated, reason was " + report.left.get) - * }}} - * - * @author <a href="mailto:research@workingmouse.com">Tony Morris</a>, Workingmouse - * @version 1.0, 11/10/2008 + * @author <a href="mailto:research@workingmouse.com">Tony Morris</a>, Workingmouse + * @version 1.0, 11/10/2008 */ final case class LeftProjection[+A, +B](e: Either[A, B]) { - /** - * Returns the value from this `Left` or throws `java.util.NoSuchElementException` - * if this is a `Right`. + /** Returns the value from this `Left` or throws `java.util.NoSuchElementException` + * if this is a `Right`. * * {{{ - * Left(12).left.get // 12 + * Left(12).left.get // 12 * Right(12).left.get // NoSuchElementException * }}} * @@ -494,8 +466,7 @@ object Either { case Right(_) => throw new NoSuchElementException("Either.left.get on Right") } - /** - * Executes the given side-effecting function if this is a `Left`. + /** Executes the given side-effecting function if this is a `Left`. * * {{{ * Left(12).left.foreach(x => println(x)) // prints "12" @@ -508,116 +479,105 @@ object Either { case Right(_) => } - /** - * Returns the value from this `Left` or the given argument if this is a `Right`. - * - * {{{ - * Left(12).left.getOrElse(17) // 12 - * Right(12).left.getOrElse(17) // 17 - * }}} + /** Returns the value from this `Left` or the given argument if this is a `Right`. * + * {{{ + * Left(12).left.getOrElse(17) // 12 + * Right(12).left.getOrElse(17) // 17 + * }}} */ def getOrElse[AA >: A](or: => AA): AA = e match { case Left(a) => a case Right(_) => or } - /** - * Returns `true` if `Right` or returns the result of the application of - * the given function to the `Left` value. - * - * {{{ - * Left(12).left.forall(_ > 10) // true - * Left(7).left.forall(_ > 10) // false - * Right(12).left.forall(_ > 10) // true - * }}} + /** Returns `true` if `Right` or returns the result of the application of + * the given function to the `Left` value. * + * {{{ + * Left(12).left.forall(_ > 10) // true + * Left(7).left.forall(_ > 10) // false + * Right(12).left.forall(_ > 10) // true + * }}} */ def forall(@deprecatedName('f) p: A => Boolean): Boolean = e match { case Left(a) => p(a) case Right(_) => true } - /** - * Returns `false` if `Right` or returns the result of the application of - * the given function to the `Left` value. - * - * {{{ - * Left(12).left.exists(_ > 10) // true - * Left(7).left.exists(_ > 10) // false - * Right(12).left.exists(_ > 10) // false - * }}} + /** Returns `false` if `Right` or returns the result of the application of + * the given function to the `Left` value. * + * {{{ + * Left(12).left.exists(_ > 10) // true + * Left(7).left.exists(_ > 10) // false + * Right(12).left.exists(_ > 10) // false + * }}} */ def exists(@deprecatedName('f) p: A => Boolean): Boolean = e match { case Left(a) => p(a) case Right(_) => false } - /** - * Binds the given function across `Left`. + /** Binds the given function across `Left`. * - * {{{ - * Left(12).left.flatMap(x => Left("scala")) // Left("scala") - * Right(12).left.flatMap(x => Left("scala") // Right(12) - * }}} - * @param f The function to bind across `Left`. + * {{{ + * Left(12).left.flatMap(x => Left("scala")) // Left("scala") + * Right(12).left.flatMap(x => Left("scala")) // Right(12) + * }}} + * @param f The function to bind across `Left`. */ def flatMap[BB >: B, X](f: A => Either[X, BB]): Either[X, BB] = e match { case Left(a) => f(a) case Right(b) => e.asInstanceOf[Either[X, BB]] } - /** - * Maps the function argument through `Left`. + /** Maps the function argument through `Left`. * - * {{{ - * Left(12).left.map(_ + 2) // Left(14) - * Right[Int, Int](12).left.map(_ + 2) // Right(12) - * }}} + * {{{ + * Left(12).left.map(_ + 2) // Left(14) + * Right[Int, Int](12).left.map(_ + 2) // Right(12) + * }}} */ def map[X](f: A => X): Either[X, B] = e match { case Left(a) => Left(f(a)) case Right(b) => e.asInstanceOf[Either[X, B]] } - /** - * Returns `None` if this is a `Right` or if the given predicate - * `p` does not hold for the left value, otherwise, returns a `Left`. + /** Returns `None` if this is a `Right` or if the given predicate + * `p` does not hold for the left value, otherwise, returns a `Left`. * - * {{{ - * Left(12).left.filter(_ > 10) // Some(Left(12)) - * Left(7).left.filter(_ > 10) // None - * Right(12).left.filter(_ > 10) // None - * }}} + * {{{ + * Left(12).left.filter(_ > 10) // Some(Left(12)) + * Left(7).left.filter(_ > 10) // None + * Right(12).left.filter(_ > 10) // None + * }}} */ def filter[Y](p: A => Boolean): Option[Either[A, Y]] = e match { case Left(a) => if(p(a)) Some(Left(a)) else None case Right(b) => None } - /** - * Returns a `Seq` containing the `Left` value if it exists or an empty - * `Seq` if this is a `Right`. + /** Returns a `Seq` containing the `Left` value if it exists or an empty + * `Seq` if this is a `Right`. * - * {{{ - * Left(12).left.toSeq // Seq(12) - * Right(12).left.toSeq // Seq() - * }}} + * {{{ + * Left(12).left.toSeq // Seq(12) + * Right(12).left.toSeq // Seq() + * }}} */ def toSeq: Seq[A] = e match { case Left(a) => Seq(a) case Right(_) => Seq.empty } - /** - * Returns a `Some` containing the `Left` value if it exists or a - * `None` if this is a `Right`. + /** Returns a `Some` containing the `Left` value if it exists or a + * `None` if this is a `Right`. * - * {{{ - * Left(12).left.toOption // Some(12) - * Right(12).left.toOption // None - * }}} + * {{{ + * Left(12).left.toOption // Some(12) + * Right(12).left.toOption // None + * }}} */ def toOption: Option[A] = e match { case Left(a) => Some(a) @@ -625,26 +585,24 @@ object Either { } } - /** - * Projects an `Either` into a `Right`. + /** Projects an `Either` into a `Right`. * - * Because `Either` is already right-biased, this class is not normally needed. - * (It is retained in the library for now for easy cross-compilation between Scala - * 2.11 and 2.12.) + * Because `Either` is already right-biased, this class is not normally needed. + * (It is retained in the library for now for easy cross-compilation between Scala + * 2.11 and 2.12.) * - * @author <a href="mailto:research@workingmouse.com">Tony Morris</a>, Workingmouse - * @version 1.0, 11/10/2008 + * @author <a href="mailto:research@workingmouse.com">Tony Morris</a>, Workingmouse + * @version 1.0, 11/10/2008 */ final case class RightProjection[+A, +B](e: Either[A, B]) { - /** - * Returns the value from this `Right` or throws - * `java.util.NoSuchElementException` if this is a `Left`. + /** Returns the value from this `Right` or throws + * `java.util.NoSuchElementException` if this is a `Left`. * - * {{{ - * Right(12).right.get // 12 - * Left(12).right.get // NoSuchElementException - * }}} + * {{{ + * Right(12).right.get // 12 + * Left(12).right.get // NoSuchElementException + * }}} * * @throws java.util.NoSuchElementException if the projection is `Left`. */ @@ -653,80 +611,74 @@ object Either { case Left(_) => throw new NoSuchElementException("Either.right.get on Left") } - /** - * Executes the given side-effecting function if this is a `Right`. + /** Executes the given side-effecting function if this is a `Right`. * - * {{{ - * Right(12).right.foreach(x => println(x)) // prints "12" - * Left(12).right.foreach(x => println(x)) // doesn't print - * }}} - * @param f The side-effecting function to execute. + * {{{ + * Right(12).right.foreach(x => println(x)) // prints "12" + * Left(12).right.foreach(x => println(x)) // doesn't print + * }}} + * @param f The side-effecting function to execute. */ def foreach[U](f: B => U): Unit = e match { case Right(b) => f(b) case Left(_) => } - /** - * Returns the value from this `Right` or the given argument if this is a `Left`. + /** Returns the value from this `Right` or the given argument if this is a `Left`. * - * {{{ - * Right(12).right.getOrElse(17) // 12 - * Left(12).right.getOrElse(17) // 17 - * }}} + * {{{ + * Right(12).right.getOrElse(17) // 12 + * Left(12).right.getOrElse(17) // 17 + * }}} */ def getOrElse[BB >: B](or: => BB): BB = e match { case Right(b) => b case Left(_) => or } - /** - * Returns `true` if `Left` or returns the result of the application of - * the given function to the `Right` value. + /** Returns `true` if `Left` or returns the result of the application of + * the given function to the `Right` value. * - * {{{ - * Right(12).right.forall(_ > 10) // true - * Right(7).right.forall(_ > 10) // false - * Left(12).right.forall(_ > 10) // true - * }}} + * {{{ + * Right(12).right.forall(_ > 10) // true + * Right(7).right.forall(_ > 10) // false + * Left(12).right.forall(_ > 10) // true + * }}} */ def forall(f: B => Boolean): Boolean = e match { case Right(b) => f(b) case Left(_) => true } - /** - * Returns `false` if `Left` or returns the result of the application of - * the given function to the `Right` value. + /** Returns `false` if `Left` or returns the result of the application of + * the given function to the `Right` value. * - * {{{ - * Right(12).right.exists(_ > 10) // true - * Right(7).right.exists(_ > 10) // false - * Left(12).right.exists(_ > 10) // false - * }}} + * {{{ + * Right(12).right.exists(_ > 10) // true + * Right(7).right.exists(_ > 10) // false + * Left(12).right.exists(_ > 10) // false + * }}} */ def exists(@deprecatedName('f) p: B => Boolean): Boolean = e match { case Right(b) => p(b) case Left(_) => false } - /** - * Binds the given function across `Right`. + /** Binds the given function across `Right`. * - * @param f The function to bind across `Right`. + * @param f The function to bind across `Right`. */ def flatMap[AA >: A, Y](f: B => Either[AA, Y]): Either[AA, Y] = e match { case Right(b) => f(b) case Left(a) => e.asInstanceOf[Either[AA, Y]] } - /** - * The given function is applied if this is a `Right`. + /** The given function is applied if this is a `Right`. * - * {{{ - * Right(12).right.map(x => "flower") // Result: Right("flower") - * Left(12).right.map(x => "flower") // Result: Left(12) - * }}} + * {{{ + * Right(12).right.map(x => "flower") // Result: Right("flower") + * Left(12).right.map(x => "flower") // Result: Left(12) + * }}} */ def map[Y](f: B => Y): Either[A, Y] = e match { case Right(b) => Right(f(b)) diff --git a/src/library/scala/util/Properties.scala b/src/library/scala/util/Properties.scala index 29a635fcbe..101a6437ec 100644 --- a/src/library/scala/util/Properties.scala +++ b/src/library/scala/util/Properties.scala @@ -105,7 +105,7 @@ private[scala] trait PropertiesTrait { * or "version (unknown)" if it cannot be determined. */ val versionString = "version " + scalaPropOrElse("version.number", "(unknown)") - val copyrightString = scalaPropOrElse("copyright.string", "Copyright 2002-2016, LAMP/EPFL and Lightbend, Inc.") + val copyrightString = scalaPropOrElse("copyright.string", "Copyright 2002-2017, LAMP/EPFL and Lightbend, Inc.") /** This is the encoding to use reading in source files, overridden with -encoding. * Note that it uses "prop" i.e. looks in the scala jar, not the system properties. diff --git a/src/library/scala/util/matching/Regex.scala b/src/library/scala/util/matching/Regex.scala index ea9f02f85b..4822fe02b4 100644 --- a/src/library/scala/util/matching/Regex.scala +++ b/src/library/scala/util/matching/Regex.scala @@ -41,11 +41,13 @@ import java.util.regex.{ Pattern, Matcher } * implicitly for strings: * * {{{ - * val date = """(\d\d\d\d)-(\d\d)-(\d\d)""".r + * val date = raw"(\d{4})-(\d{2})-(\d{2})".r * }}} * * Since escapes are not processed in multi-line string literals, using triple quotes * avoids having to escape the backslash character, so that `"\\d"` can be written `"""\d"""`. + * The same result is achieved with certain interpolators, such as `raw"\d".r` or + * a custom interpolator `r"\d"` that also compiles the `Regex`. * * === Extraction === * To extract the capturing groups when a `Regex` is matched, use it as @@ -116,29 +118,41 @@ import java.util.regex.{ Pattern, Matcher } * while (mi.hasNext) { * val d = mi.next * if (mi.group(1).toInt < 1960) println(s"$d: An oldie but goodie.") + * } * }}} * - * Note that `findAllIn` finds matches that don't overlap. (See [[findAllIn]] for more examples.) + * Although the `MatchIterator` returned by `findAllIn` is used like any `Iterator`, + * with alternating calls to `hasNext` and `next`, `hasNext` has the additional + * side effect of advancing the underlying matcher to the next unconsumed match. + * This effect is visible in the `MatchData` representing the "current match". * * {{{ - * val num = """(\d+)""".r - * val all = num.findAllIn("123").toList // List("123"), not List("123", "23", "3") + * val r = "(ab+c)".r + * val s = "xxxabcyyyabbczzz" + * r.findAllIn(s).start // 3 + * val mi = r.findAllIn(s) + * mi.hasNext // true + * mi.start // 3 + * mi.next() // "abc" + * mi.start // 3 + * mi.hasNext // true + * mi.start // 9 + * mi.next() // "abbc" * }}} * - * Also, the "current match" of a `MatchIterator` may be advanced by either `hasNext` or `next`. - * By comparison, the `Iterator[Match]` returned by `findAllMatchIn` or `findAllIn.matchData` - * produces `Match` objects that remain valid after the iterator is advanced. + * The example shows that methods on `MatchData` such as `start` will advance to + * the first match, if necessary. It also shows that `hasNext` will advance to + * the next unconsumed match, if `next` has already returned the current match. + * + * The current `MatchData` can be captured using the `matchData` method. + * Alternatively, `findAllMatchIn` returns an `Iterator[Match]`, where there + * is no interaction between the iterator and `Match` objects it has already produced. + * + * Note that `findAllIn` finds matches that don't overlap. (See [[findAllIn]] for more examples.) * * {{{ - * val ns = num.findAllIn("1 2 3") - * ns.start // 0 - * ns.hasNext // true - * ns.start // 2 - * val ms = num.findAllMatchIn("1 2 3") - * val m = ms.next() - * m.start // 0 - * ms.hasNext // true - * m.start // still 0 + * val num = raw"(\d+)".r + * val all = num.findAllIn("123").toList // List("123"), not List("123", "23", "3") * }}} * * === Replace Text === |