summaryrefslogtreecommitdiff
path: root/src/library/scala
diff options
context:
space:
mode:
authorLukas Rytz <lukas.rytz@gmail.com>2015-04-01 16:47:22 +0200
committerLukas Rytz <lukas.rytz@gmail.com>2015-04-01 16:47:22 +0200
commitdcd9a83916f9e0128ef6869def82d4f23bdea0e0 (patch)
treee58331aebe8ba06fd1c15faf36fdbb3f77b489b9 /src/library/scala
parentebf0976c363c67e6a46c66d70b39704f1ce5e74a (diff)
parentfcc20fe4d3ac5caceb50965bc202b880e61f984c (diff)
downloadscala-dcd9a83916f9e0128ef6869def82d4f23bdea0e0.tar.gz
scala-dcd9a83916f9e0128ef6869def82d4f23bdea0e0.tar.bz2
scala-dcd9a83916f9e0128ef6869def82d4f23bdea0e0.zip
Merge commit 'fcc20fe' into merge/2.11-to-2.12-apr-1
Diffstat (limited to 'src/library/scala')
-rw-r--r--src/library/scala/collection/IterableLike.scala15
-rw-r--r--src/library/scala/collection/SeqLike.scala75
-rw-r--r--src/library/scala/collection/SeqViewLike.scala2
-rw-r--r--src/library/scala/collection/SetLike.scala30
-rw-r--r--src/library/scala/collection/concurrent/TrieMap.scala38
-rw-r--r--src/library/scala/collection/generic/GenericTraversableTemplate.scala2
-rw-r--r--src/library/scala/collection/immutable/List.scala2
-rw-r--r--src/library/scala/collection/immutable/Stream.scala21
-rw-r--r--src/library/scala/collection/immutable/StringLike.scala31
-rw-r--r--src/library/scala/collection/immutable/Vector.scala2
-rw-r--r--src/library/scala/collection/mutable/BitSet.scala9
-rw-r--r--src/library/scala/collection/mutable/LinkedHashMap.scala1
-rw-r--r--src/library/scala/collection/mutable/LinkedHashSet.scala1
-rw-r--r--src/library/scala/collection/mutable/MapLike.scala4
-rw-r--r--src/library/scala/collection/mutable/MutableList.scala17
-rw-r--r--src/library/scala/concurrent/Promise.scala7
-rw-r--r--src/library/scala/concurrent/package.scala74
-rw-r--r--src/library/scala/reflect/ClassTag.scala39
-rw-r--r--src/library/scala/util/Random.scala10
19 files changed, 292 insertions, 88 deletions
diff --git a/src/library/scala/collection/IterableLike.scala b/src/library/scala/collection/IterableLike.scala
index 91ab1f6ac2..ecf64624e8 100644
--- a/src/library/scala/collection/IterableLike.scala
+++ b/src/library/scala/collection/IterableLike.scala
@@ -179,6 +179,7 @@ self =>
/** Groups elements in fixed size blocks by passing a "sliding window"
* over them (as opposed to partitioning them, as is done in grouped.)
+ * "Sliding window" step is 1 by default.
* @see [[scala.collection.Iterator]], method `sliding`
*
* @param size the number of elements per group
@@ -194,7 +195,7 @@ self =>
*
* @param size the number of elements per group
* @param step the distance between the first elements of successive
- * groups (defaults to 1)
+ * groups
* @return An iterator producing ${coll}s of size `size`, except the
* last and the only element will be truncated if there are
* fewer elements than size.
@@ -217,12 +218,12 @@ self =>
val b = newBuilder
b.sizeHintBounded(n, this)
val lead = this.iterator drop n
- var go = false
- for (x <- this) {
- if (lead.hasNext) lead.next()
- else go = true
- if (go) b += x
+ val it = this.iterator
+ while (lead.hasNext) {
+ lead.next()
+ it.next()
}
+ while (it.hasNext) b += it.next()
b.result()
}
@@ -282,7 +283,7 @@ self =>
var i = 0
for (x <- this) {
b += ((x, i))
- i +=1
+ i += 1
}
b.result()
}
diff --git a/src/library/scala/collection/SeqLike.scala b/src/library/scala/collection/SeqLike.scala
index 329273df5b..66fce0f902 100644
--- a/src/library/scala/collection/SeqLike.scala
+++ b/src/library/scala/collection/SeqLike.scala
@@ -447,9 +447,11 @@ trait SeqLike[+A, +Repr] extends Any with IterableLike[A, Repr] with GenSeqLike[
def diff[B >: A](that: GenSeq[B]): Repr = {
val occ = occCounts(that.seq)
val b = newBuilder
- for (x <- this)
- if (occ(x) == 0) b += x
- else occ(x) -= 1
+ for (x <- this) {
+ val ox = occ(x) // Avoid multiple map lookups
+ if (ox == 0) b += x
+ else occ(x) = ox - 1
+ }
b.result()
}
@@ -476,11 +478,13 @@ trait SeqLike[+A, +Repr] extends Any with IterableLike[A, Repr] with GenSeqLike[
def intersect[B >: A](that: GenSeq[B]): Repr = {
val occ = occCounts(that.seq)
val b = newBuilder
- for (x <- this)
- if (occ(x) > 0) {
+ for (x <- this) {
+ val ox = occ(x) // Avoid multiple map lookups
+ if (ox > 0) {
b += x
- occ(x) -= 1
+ occ(x) = ox - 1
}
+ }
b.result()
}
@@ -509,22 +513,35 @@ trait SeqLike[+A, +Repr] extends Any with IterableLike[A, Repr] with GenSeqLike[
def patch[B >: A, That](from: Int, patch: GenSeq[B], replaced: Int)(implicit bf: CanBuildFrom[Repr, B, That]): That = {
val b = bf(repr)
- val (prefix, rest) = this.splitAt(from)
- b ++= toCollection(prefix)
+ var i = 0
+ val it = this.iterator
+ while (i < from && it.hasNext) {
+ b += it.next()
+ i += 1
+ }
b ++= patch.seq
- b ++= toCollection(rest).view drop replaced
+ i = replaced
+ while (i > 0 && it.hasNext) {
+ it.next()
+ i -= 1
+ }
+ while (it.hasNext) b += it.next()
b.result()
}
def updated[B >: A, That](index: Int, elem: B)(implicit bf: CanBuildFrom[Repr, B, That]): That = {
if (index < 0) throw new IndexOutOfBoundsException(index.toString)
val b = bf(repr)
- val (prefix, rest) = this.splitAt(index)
- val restColl = toCollection(rest)
- if (restColl.isEmpty) throw new IndexOutOfBoundsException(index.toString)
- b ++= toCollection(prefix)
+ var i = 0
+ val it = this.iterator
+ while (i < index && it.hasNext) {
+ b += it.next()
+ i += 1
+ }
+ if (!it.hasNext) throw new IndexOutOfBoundsException(index.toString)
b += elem
- b ++= restColl.view.tail
+ it.next()
+ while (it.hasNext) b += it.next()
b.result()
}
@@ -544,8 +561,9 @@ trait SeqLike[+A, +Repr] extends Any with IterableLike[A, Repr] with GenSeqLike[
def padTo[B >: A, That](len: Int, elem: B)(implicit bf: CanBuildFrom[Repr, B, That]): That = {
val b = bf(repr)
- b.sizeHint(length max len)
- var diff = len - length
+ val L = length
+ b.sizeHint(math.max(L, len))
+ var diff = len - L
b ++= thisCollection
while (diff > 0) {
b += elem
@@ -617,16 +635,23 @@ trait SeqLike[+A, +Repr] extends Any with IterableLike[A, Repr] with GenSeqLike[
*/
def sorted[B >: A](implicit ord: Ordering[B]): Repr = {
val len = this.length
- val arr = new ArraySeq[A](len)
- var i = 0
- for (x <- this) {
- arr(i) = x
- i += 1
- }
- java.util.Arrays.sort(arr.array, ord.asInstanceOf[Ordering[Object]])
val b = newBuilder
- b.sizeHint(len)
- for (x <- arr) b += x
+ if (len == 1) b ++= this
+ else if (len > 1) {
+ b.sizeHint(len)
+ val arr = new Array[AnyRef](len) // Previously used ArraySeq for more compact but slower code
+ var i = 0
+ for (x <- this) {
+ arr(i) = x.asInstanceOf[AnyRef]
+ i += 1
+ }
+ java.util.Arrays.sort(arr, ord.asInstanceOf[Ordering[Object]])
+ i = 0
+ while (i < arr.length) {
+ b += arr(i).asInstanceOf[A]
+ i += 1
+ }
+ }
b.result()
}
diff --git a/src/library/scala/collection/SeqViewLike.scala b/src/library/scala/collection/SeqViewLike.scala
index 587ec133a5..1fbcb6531e 100644
--- a/src/library/scala/collection/SeqViewLike.scala
+++ b/src/library/scala/collection/SeqViewLike.scala
@@ -83,7 +83,7 @@ trait SeqViewLike[+A,
}
def length = index(self.length)
def apply(idx: Int) = {
- if (idx < 0 || idx >= self.length) throw new IndexOutOfBoundsException(idx.toString)
+ if (idx < 0 || idx >= length) throw new IndexOutOfBoundsException(idx.toString)
val row = findRow(idx, 0, self.length - 1)
mapping(self(row)).seq.toSeq(idx - index(row))
}
diff --git a/src/library/scala/collection/SetLike.scala b/src/library/scala/collection/SetLike.scala
index 80a344e6a8..d03c808c2c 100644
--- a/src/library/scala/collection/SetLike.scala
+++ b/src/library/scala/collection/SetLike.scala
@@ -116,22 +116,36 @@ self =>
*/
def + (elem: A): This
- /** Creates a new $coll with additional elements.
+ /** Creates a new $coll with additional elements, omitting duplicates.
*
- * This method takes two or more elements to be added. Another overloaded
- * variant of this method handles the case where a single element is added.
+ * This method takes two or more elements to be added. Elements that already exist in the $coll will
+ * not be added. Another overloaded variant of this method handles the case where a single element is added.
+ *
+ * Example:
+ * {{{
+ * scala> val a = Set(1, 3) + 2 + 3
+ * a: scala.collection.immutable.Set[Int] = Set(1, 3, 2)
+ * }}}
*
* @param elem1 the first element to add.
* @param elem2 the second element to add.
* @param elems the remaining elements to add.
- * @return a new $coll with the given elements added.
+ * @return a new $coll with the given elements added, omitting duplicates.
*/
def + (elem1: A, elem2: A, elems: A*): This = this + elem1 + elem2 ++ elems
- /** Creates a new $coll by adding all elements contained in another collection to this $coll.
+ /** Creates a new $coll by adding all elements contained in another collection to this $coll, omitting duplicates.
+ *
+ * This method takes a collection of elements and adds all elements, omitting duplicates, into $coll.
+ *
+ * Example:
+ * {{{
+ * scala> val a = Set(1, 2) ++ Set(2, "a")
+ * a: scala.collection.immutable.Set[Any] = Set(1, 2, a)
+ * }}}
*
- * @param elems the collection containing the added elements.
- * @return a new $coll with the given elements added.
+ * @param elems the collection containing the elements to add.
+ * @return a new $coll with the given elements added, omitting duplicates.
*/
def ++ (elems: GenTraversableOnce[A]): This = (repr /: elems.seq)(_ + _)
@@ -180,7 +194,7 @@ self =>
*
* @return the iterator.
*/
- def subsets: Iterator[This] = new AbstractIterator[This] {
+ def subsets(): Iterator[This] = new AbstractIterator[This] {
private val elms = self.toIndexedSeq
private var len = 0
private var itr: Iterator[This] = Iterator.empty
diff --git a/src/library/scala/collection/concurrent/TrieMap.scala b/src/library/scala/collection/concurrent/TrieMap.scala
index fccc1d81b9..bcfea7a463 100644
--- a/src/library/scala/collection/concurrent/TrieMap.scala
+++ b/src/library/scala/collection/concurrent/TrieMap.scala
@@ -873,6 +873,44 @@ extends scala.collection.concurrent.Map[K, V]
insertifhc(k, hc, v, INode.KEY_ABSENT)
}
+ // TODO once computeIfAbsent is added to concurrent.Map,
+ // move the comment there and tweak the 'at most once' part
+ /** If the specified key is not already in the map, computes its value using
+ * the given thunk `op` and enters it into the map.
+ *
+ * Since concurrent maps cannot contain `null` for keys or values,
+ * a `NullPointerException` is thrown if the thunk `op`
+ * returns `null`.
+ *
+ * If the specified mapping function throws an exception,
+ * that exception is rethrown.
+ *
+ * Note: This method will invoke op at most once.
+ * However, `op` may be invoked without the result being added to the map if
+ * a concurrent process is also trying to add a value corresponding to the
+ * same key `k`.
+ *
+ * @param k the key to modify
+ * @param op the expression that computes the value
+ * @return the newly added value
+ */
+ override def getOrElseUpdate(k: K, op: =>V): V = {
+ val oldv = lookup(k)
+ if (oldv != null) oldv.asInstanceOf[V]
+ else {
+ val v = op
+ if (v == null) {
+ throw new NullPointerException("Concurrent TrieMap values cannot be null.")
+ } else {
+ val hc = computeHash(k)
+ insertifhc(k, hc, v, INode.KEY_ABSENT) match {
+ case Some(oldv) => oldv
+ case None => v
+ }
+ }
+ }
+ }
+
def remove(k: K, v: V): Boolean = {
val hc = computeHash(k)
removehc(k, v, hc).nonEmpty
diff --git a/src/library/scala/collection/generic/GenericTraversableTemplate.scala b/src/library/scala/collection/generic/GenericTraversableTemplate.scala
index 54455c531a..bdd91ba7a4 100644
--- a/src/library/scala/collection/generic/GenericTraversableTemplate.scala
+++ b/src/library/scala/collection/generic/GenericTraversableTemplate.scala
@@ -216,7 +216,7 @@ trait GenericTraversableTemplate[+A, +CC[X] <: GenTraversable[X]] extends HasNew
val bs: IndexedSeq[Builder[B, CC[B]]] = IndexedSeq.fill(headSize)(genericBuilder[B])
for (xs <- sequential) {
var i = 0
- for (x <- asTraversable(xs)) {
+ for (x <- asTraversable(xs).seq) {
if (i >= headSize) fail
bs(i) += x
i += 1
diff --git a/src/library/scala/collection/immutable/List.scala b/src/library/scala/collection/immutable/List.scala
index 89b4ee1145..48a6ca5699 100644
--- a/src/library/scala/collection/immutable/List.scala
+++ b/src/library/scala/collection/immutable/List.scala
@@ -324,7 +324,7 @@ sealed abstract class List[+A] extends AbstractSeq[A]
var h: ::[B] = null
var t: ::[B] = null
while (rest ne Nil) {
- f(rest.head).foreach{ b =>
+ f(rest.head).seq.foreach{ b =>
if (!found) {
h = new ::(b, Nil)
t = h
diff --git a/src/library/scala/collection/immutable/Stream.scala b/src/library/scala/collection/immutable/Stream.scala
index 8be0b2fee2..5fff727c36 100644
--- a/src/library/scala/collection/immutable/Stream.scala
+++ b/src/library/scala/collection/immutable/Stream.scala
@@ -697,16 +697,18 @@ self =>
b append end
return b
}
- if ((cursor ne scout) && scout.tailDefined) {
+ if (cursor ne scout) {
cursor = scout
- scout = scout.tail
- // Use 2x 1x iterator trick for cycle detection; slow iterator can add strings
- while ((cursor ne scout) && scout.tailDefined) {
- b append sep append cursor.head
- n += 1
- cursor = cursor.tail
+ if (scout.tailDefined) {
scout = scout.tail
- if (scout.tailDefined) scout = scout.tail
+ // Use 2x 1x iterator trick for cycle detection; slow iterator can add strings
+ while ((cursor ne scout) && scout.tailDefined) {
+ b append sep append cursor.head
+ n += 1
+ cursor = cursor.tail
+ scout = scout.tail
+ if (scout.tailDefined) scout = scout.tail
+ }
}
}
if (!scout.tailDefined) { // Not a cycle, scout hit an end
@@ -715,6 +717,9 @@ self =>
n += 1
cursor = cursor.tail
}
+ if (cursor.nonEmpty) {
+ b append sep append cursor.head
+ }
}
else {
// Cycle.
diff --git a/src/library/scala/collection/immutable/StringLike.scala b/src/library/scala/collection/immutable/StringLike.scala
index f0daaf25a5..1ead894faf 100644
--- a/src/library/scala/collection/immutable/StringLike.scala
+++ b/src/library/scala/collection/immutable/StringLike.scala
@@ -10,7 +10,7 @@ package scala
package collection
package immutable
-import mutable.Builder
+import mutable.{ ArrayBuilder, Builder }
import scala.util.matching.Regex
import scala.math.ScalaNumber
import scala.reflect.ClassTag
@@ -203,8 +203,33 @@ self =>
private def escape(ch: Char): String = "\\Q" + ch + "\\E"
- @throws(classOf[java.util.regex.PatternSyntaxException])
- def split(separator: Char): Array[String] = toString.split(escape(separator))
+ def split(separator: Char): Array[String] = {
+ val thisString = toString
+ var pos = thisString.indexOf(separator)
+
+ if (pos != -1) {
+ val res = new ArrayBuilder.ofRef[String]
+
+ var prev = 0
+ do {
+ res += thisString.substring(prev, pos)
+ prev = pos + 1
+ pos = thisString.indexOf(separator, prev)
+ } while (pos != -1)
+
+ if (prev != thisString.size)
+ res += thisString.substring(prev, thisString.size)
+
+ val initialResult = res.result()
+ pos = initialResult.length
+ while (pos > 0 && initialResult(pos - 1).isEmpty) pos = pos - 1
+ if (pos != initialResult.length) {
+ val trimmed = new Array[String](pos)
+ Array.copy(initialResult, 0, trimmed, 0, pos)
+ trimmed
+ } else initialResult
+ } else Array[String](thisString)
+ }
@throws(classOf[java.util.regex.PatternSyntaxException])
def split(separators: Array[Char]): Array[String] = {
diff --git a/src/library/scala/collection/immutable/Vector.scala b/src/library/scala/collection/immutable/Vector.scala
index c7da447f72..47a623a616 100644
--- a/src/library/scala/collection/immutable/Vector.scala
+++ b/src/library/scala/collection/immutable/Vector.scala
@@ -215,7 +215,7 @@ override def companion: GenericCompanion[Vector] = Vector
import Vector.{Log2ConcatFaster, TinyAppendFaster}
if (that.isEmpty) this.asInstanceOf[That]
else {
- val again = if (!that.isTraversableAgain) that.toVector else that
+ val again = if (!that.isTraversableAgain) that.toVector else that.seq
again.size match {
// Often it's better to append small numbers of elements (or prepend if RHS is a vector)
case n if n <= TinyAppendFaster || n < (this.size >> Log2ConcatFaster) =>
diff --git a/src/library/scala/collection/mutable/BitSet.scala b/src/library/scala/collection/mutable/BitSet.scala
index faa4155317..e92d48cfeb 100644
--- a/src/library/scala/collection/mutable/BitSet.scala
+++ b/src/library/scala/collection/mutable/BitSet.scala
@@ -121,8 +121,10 @@ class BitSet(protected final var elems: Array[Long]) extends AbstractSet[Int]
* @return the bitset itself.
*/
def &= (other: BitSet): this.type = {
- ensureCapacity(other.nwords - 1)
- for (i <- 0 until other.nwords)
+ // Different from other operations: no need to ensure capacity because
+ // anything beyond the capacity is 0. Since we use other.word which is 0
+ // off the end, we also don't need to make sure we stay in bounds there.
+ for (i <- 0 until nwords)
elems(i) = elems(i) & other.word(i)
this
}
@@ -160,6 +162,9 @@ class BitSet(protected final var elems: Array[Long]) extends AbstractSet[Int]
*
* @return an immutable set containing all the elements of this set.
*/
+ @deprecated("If this BitSet contains a value that is 128 or greater, the result of this method is an 'immutable' " +
+ "BitSet that shares state with this mutable BitSet. Thus, if the mutable BitSet is modified, it will violate the " +
+ "immutability of the result.", "2.11.6")
def toImmutable = immutable.BitSet.fromBitMaskNoCopy(elems)
override def clone(): BitSet = {
diff --git a/src/library/scala/collection/mutable/LinkedHashMap.scala b/src/library/scala/collection/mutable/LinkedHashMap.scala
index b64504be3d..275f490675 100644
--- a/src/library/scala/collection/mutable/LinkedHashMap.scala
+++ b/src/library/scala/collection/mutable/LinkedHashMap.scala
@@ -160,6 +160,7 @@ class LinkedHashMap[A, B] extends AbstractMap[A, B]
override def clear() {
clearTable()
firstEntry = null
+ lastEntry = null
}
private def writeObject(out: java.io.ObjectOutputStream) {
diff --git a/src/library/scala/collection/mutable/LinkedHashSet.scala b/src/library/scala/collection/mutable/LinkedHashSet.scala
index 1768c946ed..756a2f73c1 100644
--- a/src/library/scala/collection/mutable/LinkedHashSet.scala
+++ b/src/library/scala/collection/mutable/LinkedHashSet.scala
@@ -112,6 +112,7 @@ class LinkedHashSet[A] extends AbstractSet[A]
override def clear() {
clearTable()
firstEntry = null
+ lastEntry = null
}
private def writeObject(out: java.io.ObjectOutputStream) {
diff --git a/src/library/scala/collection/mutable/MapLike.scala b/src/library/scala/collection/mutable/MapLike.scala
index 42000e5918..949e5e3536 100644
--- a/src/library/scala/collection/mutable/MapLike.scala
+++ b/src/library/scala/collection/mutable/MapLike.scala
@@ -190,6 +190,10 @@ trait MapLike[A, B, +This <: MapLike[A, B, This] with Map[A, B]]
*
* Otherwise, computes value from given expression `op`, stores with key
* in map and returns that value.
+ *
+ * Concurrent map implementations may evaluate the expression `op`
+ * multiple times, or may evaluate `op` without inserting the result.
+ *
* @param key the key to test
* @param op the computation yielding the value to associate with `key`, if
* `key` is previously unbound.
diff --git a/src/library/scala/collection/mutable/MutableList.scala b/src/library/scala/collection/mutable/MutableList.scala
index b852a4747b..646023f469 100644
--- a/src/library/scala/collection/mutable/MutableList.scala
+++ b/src/library/scala/collection/mutable/MutableList.scala
@@ -13,7 +13,6 @@ package mutable
import generic._
import immutable.{List, Nil}
-// !!! todo: convert to LinkedListBuffer?
/**
* This class is used internally to represent mutable lists. It is the
* basis for the implementation of the class `Queue`.
@@ -113,9 +112,21 @@ extends AbstractSeq[A]
}
}
- /** Returns an iterator over all elements of this list.
+ /** Returns an iterator over up to `length` elements of this list.
*/
- override def iterator: Iterator[A] = first0.iterator
+ override def iterator: Iterator[A] = if (isEmpty) Iterator.empty else
+ new AbstractIterator[A] {
+ var elems = first0
+ var count = len
+ def hasNext = count > 0 && elems.nonEmpty
+ def next() = {
+ if (!hasNext) throw new NoSuchElementException
+ count = count - 1
+ val e = elems.elem
+ elems = if (count == 0) null else elems.next
+ e
+ }
+ }
override def last = {
if (isEmpty) throw new NoSuchElementException("MutableList.empty.last")
diff --git a/src/library/scala/concurrent/Promise.scala b/src/library/scala/concurrent/Promise.scala
index dc4376eba4..894b134e83 100644
--- a/src/library/scala/concurrent/Promise.scala
+++ b/src/library/scala/concurrent/Promise.scala
@@ -60,12 +60,7 @@ trait Promise[T] {
*
* @return This promise
*/
- final def completeWith(other: Future[T]): this.type = {
- if (other ne this.future) { // this completeWith this doesn't make much sense
- other.onComplete(this complete _)(Future.InternalCallbackExecutor)
- }
- this
- }
+ final def completeWith(other: Future[T]): this.type = tryCompleteWith(other)
/** Attempts to complete this promise with the specified future, once that future is completed.
*
diff --git a/src/library/scala/concurrent/package.scala b/src/library/scala/concurrent/package.scala
index 4843d28679..d159dda414 100644
--- a/src/library/scala/concurrent/package.scala
+++ b/src/library/scala/concurrent/package.scala
@@ -12,6 +12,75 @@ import scala.concurrent.duration.Duration
import scala.annotation.implicitNotFound
/** This package object contains primitives for concurrent and parallel programming.
+ *
+ * == Guide ==
+ *
+ * A more detailed guide to Futures and Promises, including discussion and examples
+ * can be found at
+ * [[http://docs.scala-lang.org/overviews/core/futures.html]].
+ *
+ * == 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:
+ *
+ * {{{
+ * import scala.concurrent._
+ * import ExecutionContext.Implicits.global
+ * }}}
+ *
+ * == Specifying Durations ==
+ *
+ * Operations often require a duration to be specified. A duration DSL is available
+ * to make defining these easier:
+ *
+ * {{{
+ * import scala.concurrent.duration._
+ * val d: Duration = 10.seconds
+ * }}}
+ *
+ * == Using Futures For Non-blocking Computation ==
+ *
+ * Basic use of futures is easy with the factory method on Future, which executes a
+ * provided function asynchronously, handing you back a future result of that function
+ * without blocking the current thread. In order to create the Future you will need
+ * either an implicit or explicit ExecutionContext to be provided:
+ *
+ * {{{
+ * import scala.concurrent._
+ * import ExecutionContext.Implicits.global // implicit execution context
+ *
+ * val firstZebra: Future[Int] = Future {
+ * val source = scala.io.Source.fromFile("/etc/dictionaries-common/words")
+ * source.toSeq.indexOfSlice("zebra")
+ * }
+ * }}}
+ *
+ * == Avoid Blocking ==
+ *
+ * Although blocking is possible in order to await results (with a mandatory timeout duration):
+ *
+ * {{{
+ * import scala.concurrent.duration._
+ * Await.result(firstZebra, 10.seconds)
+ * }}}
+ *
+ * and although this is sometimes necessary to do, in particular for testing purposes, blocking
+ * in general is discouraged when working with Futures and concurrency in order to avoid
+ * potential deadlocks and improve performance. Instead, use callbacks or combinators to
+ * remain in the future domain:
+ *
+ * {{{
+ * val animalRange: Future[Int] = for {
+ * aardvark <- firstAardvark
+ * zebra <- firstZebra
+ * } yield zebra - aardvark
+ *
+ * animalRange.onSuccess {
+ * case x if x > 500000 => println("It's a long way from Aardvark to Zebra")
+ * }
+ * }}}
*/
package object concurrent {
type ExecutionException = java.util.concurrent.ExecutionException
@@ -70,6 +139,11 @@ 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.
*/
object Await {
/**
diff --git a/src/library/scala/reflect/ClassTag.scala b/src/library/scala/reflect/ClassTag.scala
index 2f4aa9cb84..9dd96183da 100644
--- a/src/library/scala/reflect/ClassTag.scala
+++ b/src/library/scala/reflect/ClassTag.scala
@@ -69,22 +69,22 @@ trait ClassTag[T] extends ClassManifestDeprecatedApis[T] with Equals with Serial
* `SomeExtractor(...)` is turned into `ct(SomeExtractor(...))` if `T` in `SomeExtractor.unapply(x: T)`
* is uncheckable, but we have an instance of `ClassTag[T]`.
*/
- def unapply(x: Any): Option[T] = x match {
- case null => None
- case b: Byte => unapply(b)
- case s: Short => unapply(s)
- case c: Char => unapply(c)
- case i: Int => unapply(i)
- case l: Long => unapply(l)
- case f: Float => unapply(f)
- case d: Double => unapply(d)
- case b: Boolean => unapply(b)
- case u: Unit => unapply(u)
- case a: Any => unapplyImpl(a)
- }
+ def unapply(x: Any): Option[T] =
+ if (null != x && (
+ (runtimeClass.isInstance(x))
+ || (x.isInstanceOf[Byte] && runtimeClass.isAssignableFrom(classOf[Byte]))
+ || (x.isInstanceOf[Short] && runtimeClass.isAssignableFrom(classOf[Short]))
+ || (x.isInstanceOf[Char] && runtimeClass.isAssignableFrom(classOf[Char]))
+ || (x.isInstanceOf[Int] && runtimeClass.isAssignableFrom(classOf[Int]))
+ || (x.isInstanceOf[Long] && runtimeClass.isAssignableFrom(classOf[Long]))
+ || (x.isInstanceOf[Float] && runtimeClass.isAssignableFrom(classOf[Float]))
+ || (x.isInstanceOf[Double] && runtimeClass.isAssignableFrom(classOf[Double]))
+ || (x.isInstanceOf[Boolean] && runtimeClass.isAssignableFrom(classOf[Boolean]))
+ || (x.isInstanceOf[Unit] && runtimeClass.isAssignableFrom(classOf[Unit])))
+ ) Some(x.asInstanceOf[T])
+ else None
- // TODO: Inline the bodies of these into the Any-accepting unapply overload above and delete them.
- // This cannot be done until at least 2.12.0 for reasons of binary compatibility
+ // TODO: deprecate overloads in 2.12.0, remove in 2.13.0
def unapply(x: Byte) : Option[T] = unapplyImpl(x, classOf[Byte])
def unapply(x: Short) : Option[T] = unapplyImpl(x, classOf[Short])
def unapply(x: Char) : Option[T] = unapplyImpl(x, classOf[Char])
@@ -94,11 +94,10 @@ trait ClassTag[T] extends ClassManifestDeprecatedApis[T] with Equals with Serial
def unapply(x: Double) : Option[T] = unapplyImpl(x, classOf[Double])
def unapply(x: Boolean) : Option[T] = unapplyImpl(x, classOf[Boolean])
def unapply(x: Unit) : Option[T] = unapplyImpl(x, classOf[Unit])
-
- private[this] def unapplyImpl(x: Any, alternative: jClass[_] = null): Option[T] = {
- val conforms = runtimeClass.isAssignableFrom(x.getClass) || (alternative != null && runtimeClass.isAssignableFrom(alternative))
- if (conforms) Some(x.asInstanceOf[T]) else None
- }
+
+ private[this] def unapplyImpl(x: Any, primitiveCls: java.lang.Class[_]): Option[T] =
+ if (runtimeClass.isInstance(x) || runtimeClass.isAssignableFrom(primitiveCls)) Some(x.asInstanceOf[T])
+ else None
// case class accessories
override def canEqual(x: Any) = x.isInstanceOf[ClassTag[_]]
diff --git a/src/library/scala/util/Random.scala b/src/library/scala/util/Random.scala
index 8d68c5be38..2d38c9d4a0 100644
--- a/src/library/scala/util/Random.scala
+++ b/src/library/scala/util/Random.scala
@@ -121,15 +121,21 @@ class Random(val self: java.util.Random) extends AnyRef with Serializable {
(bf(xs) ++= buf).result()
}
+ @deprecated("Preserved for backwards binary compatibility. To remove in 2.12.x.", "2.11.6")
+ final def `scala$util$Random$$isAlphaNum$1`(c: Char) = (c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z') || (c >= '0' && c <= '9')
+
/** Returns a Stream of pseudorandomly chosen alphanumeric characters,
* equally chosen from A-Z, a-z, and 0-9.
*
* @since 2.8
*/
def alphanumeric: Stream[Char] = {
- def isAlphaNum(c: Char) = (c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z') || (c >= '0' && c <= '9')
+ def nextAlphaNum: Char = {
+ val chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"
+ chars charAt (self nextInt chars.length)
+ }
- Stream continually nextPrintableChar filter isAlphaNum
+ Stream continually nextAlphaNum
}
}