Skip to content

Commit 4bc6f64

Browse files
committed
Add Stack.scala and ReusableBuilder.scala to stdlib
1 parent a3288d1 commit 4bc6f64

File tree

2 files changed

+200
-0
lines changed

2 files changed

+200
-0
lines changed
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
/*
2+
* Scala (https://www.scala-lang.org)
3+
*
4+
* Copyright EPFL and Lightbend, Inc.
5+
*
6+
* Licensed under Apache License 2.0
7+
* (http://www.apache.org/licenses/LICENSE-2.0).
8+
*
9+
* See the NOTICE file distributed with this work for
10+
* additional information regarding copyright ownership.
11+
*/
12+
13+
package scala
14+
package collection
15+
package mutable
16+
17+
import language.experimental.captureChecking
18+
19+
/** `ReusableBuilder` is a marker trait that indicates that a `Builder`
20+
* can be reused to build more than one instance of a collection. In
21+
* particular, calling `result()` followed by `clear()` will produce a
22+
* collection and reset the builder to begin building a new collection
23+
* of the same type.
24+
*
25+
* In general no method other than `clear()` may be called after `result()`.
26+
* It is up to subclasses to implement and to document other allowed sequences
27+
* of operations (e.g. calling other methods after `result()` in order to obtain
28+
* different snapshots of a collection under construction).
29+
*
30+
* @tparam Elem the type of elements that get added to the builder.
31+
* @tparam To the type of collection that it produced.
32+
*
33+
* @define multipleResults
34+
*
35+
* This Builder can be reused after calling `result()` without an
36+
* intermediate call to `clear()` in order to build multiple related results.
37+
*/
38+
trait ReusableBuilder[-Elem, +To] extends Builder[Elem, To] {
39+
/** Clears the contents of this builder.
40+
* After execution of this method, the builder will contain no elements.
41+
*
42+
* If executed immediately after a call to `result()`, this allows a new
43+
* instance of the same type of collection to be built.
44+
*/
45+
override def clear(): Unit // Note: overriding for Scaladoc only!
46+
47+
/** Produces a collection from the added elements.
48+
*
49+
* After a call to `result`, the behavior of all other methods is undefined
50+
* save for `clear()`. If `clear()` is called, then the builder is reset and
51+
* may be used to build another instance.
52+
*
53+
* @return a collection containing the elements added to this builder.
54+
*/
55+
override def result(): To // Note: overriding for Scaladoc only!
56+
}
Lines changed: 144 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,144 @@
1+
/*
2+
* Scala (https://www.scala-lang.org)
3+
*
4+
* Copyright EPFL and Lightbend, Inc.
5+
*
6+
* Licensed under Apache License 2.0
7+
* (http://www.apache.org/licenses/LICENSE-2.0).
8+
*
9+
* See the NOTICE file distributed with this work for
10+
* additional information regarding copyright ownership.
11+
*/
12+
13+
package scala.collection.mutable
14+
15+
import scala.annotation.{migration, nowarn}
16+
import scala.collection.generic.DefaultSerializable
17+
import scala.collection.{IterableFactoryDefaults, IterableOnce, SeqFactory, StrictOptimizedSeqFactory, StrictOptimizedSeqOps}
18+
19+
import language.experimental.captureChecking
20+
21+
/** A stack implements a data structure which allows to store and retrieve
22+
* objects in a last-in-first-out (LIFO) fashion.
23+
*
24+
* Note that operations which consume and produce iterables preserve order,
25+
* rather than reversing it (as would be expected from building a new stack
26+
* by pushing an element at a time).
27+
*
28+
* @tparam A type of the elements contained in this stack.
29+
*
30+
* @define Coll `Stack`
31+
* @define coll stack
32+
* @define orderDependent
33+
* @define orderDependentFold
34+
* @define mayNotTerminateInf
35+
* @define willNotTerminateInf
36+
*/
37+
@migration("Stack is now based on an ArrayDeque instead of a linked list", "2.13.0")
38+
class Stack[sealed A] protected (array: Array[AnyRef], start: Int, end: Int)
39+
extends ArrayDeque[A](array, start, end)
40+
with IndexedSeqOps[A, Stack, Stack[A]]
41+
with StrictOptimizedSeqOps[A, Stack, Stack[A]]
42+
with IterableFactoryDefaults[A, Stack]
43+
with ArrayDequeOps[A, Stack, Stack[A]]
44+
with Cloneable[Stack[A]]
45+
with DefaultSerializable {
46+
47+
def this(initialSize: Int = ArrayDeque.DefaultInitialSize) =
48+
this(ArrayDeque.alloc(initialSize), start = 0, end = 0)
49+
50+
override def iterableFactory: SeqFactory[Stack] = Stack
51+
52+
@nowarn("""cat=deprecation&origin=scala\.collection\.Iterable\.stringPrefix""")
53+
override protected[this] def stringPrefix = "Stack"
54+
55+
/**
56+
* Add elements to the top of this stack
57+
*
58+
* @param elem
59+
* @return
60+
*/
61+
def push(elem: A): this.type = prepend(elem)
62+
63+
/** Push two or more elements onto the stack. The last element
64+
* of the sequence will be on top of the new stack.
65+
*
66+
* @param elems the element sequence.
67+
* @return the stack with the new elements on top.
68+
*/
69+
def push(elem1: A, elem2: A, elems: A*): this.type = {
70+
val k = elems.knownSize
71+
ensureSize(length + (if(k >= 0) k + 2 else 3))
72+
prepend(elem1).prepend(elem2).pushAll(elems)
73+
}
74+
75+
/** Push all elements in the given iterable object onto the stack. The
76+
* last element in the iterable object will be on top of the new stack.
77+
*
78+
* @param elems the iterable object.
79+
* @return the stack with the new elements on top.
80+
*/
81+
def pushAll(elems: scala.collection.IterableOnce[A]): this.type =
82+
prependAll(elems match {
83+
case it: scala.collection.Seq[A] => it.view.reverse
84+
case it => IndexedSeq.from(it).view.reverse
85+
})
86+
87+
/**
88+
* Removes the top element from this stack and return it
89+
*
90+
* @return
91+
* @throws NoSuchElementException when stack is empty
92+
*/
93+
def pop(): A = removeHead()
94+
95+
/**
96+
* Pop all elements from this stack and return it
97+
*
98+
* @return The removed elements
99+
*/
100+
def popAll(): scala.collection.Seq[A] = removeAll()
101+
102+
/**
103+
* Returns and removes all elements from the top of this stack which satisfy the given predicate
104+
*
105+
* @param f the predicate used for choosing elements
106+
* @return The removed elements
107+
*/
108+
def popWhile(f: A => Boolean): scala.collection.Seq[A] = removeHeadWhile(f)
109+
110+
/** Returns the top element of the stack. This method will not remove
111+
* the element from the stack. An error is signaled if there is no
112+
* element on the stack.
113+
*
114+
* @throws NoSuchElementException
115+
* @return the top element
116+
*/
117+
@`inline` final def top: A = head
118+
119+
override protected def klone(): Stack[A] = {
120+
val bf = newSpecificBuilder
121+
bf ++= this
122+
bf.result()
123+
}
124+
125+
override protected def ofArray(array: Array[AnyRef], end: Int): Stack[A] =
126+
new Stack(array, start = 0, end)
127+
128+
}
129+
130+
/**
131+
* $factoryInfo
132+
* @define coll stack
133+
* @define Coll `Stack`
134+
*/
135+
@SerialVersionUID(3L)
136+
object Stack extends StrictOptimizedSeqFactory[Stack] {
137+
138+
def from[sealed A](source: IterableOnce[A]): Stack[A] = empty ++= source
139+
140+
def empty[sealed A]: Stack[A] = new Stack
141+
142+
def newBuilder[sealed A]: Builder[A, Stack[A]] = new GrowableBuilder[A, Stack[A]](empty)
143+
144+
}

0 commit comments

Comments
 (0)