Skip to content

Instantly share code, notes, and snippets.

@smac89
Forked from lambda-hacker/immutable-stack.scala
Last active May 4, 2021 18:28
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save smac89/94b2c347f95a76d0f2214af46fd81ddd to your computer and use it in GitHub Desktop.
Save smac89/94b2c347f95a76d0f2214af46fd81ddd to your computer and use it in GitHub Desktop.
Stack using List [Scala]
// Immutable Stack Type using List
case class Stack[A] (elems: Seq[A] = List.empty[A]) {
def push(v: A) : Stack[A] = Stack(v +: elems)
def pushAll(xs: Iterable[A]) : Stack[A] =
xs.foldLeft (this) ((accStack, e) => accStack.push(e))
def pop(): Either[String, (A, Stack[A])] = {
if (isEmpty) Left("Cannot pop from empty stack")
else Right((elems.head, Stack(elems.tail)))
}
def top: Either[String, A] = {
if (isEmpty) Left("Cannot pop from empty stack")
else Right(elems.head)
}
def size: Int = elems.length
def isEmpty : Boolean = elems.isEmpty
def <(e: A) : Stack[A] = push(e)
def ^(f: A => Unit = _ => ()): Stack[A] = {
pop().map({case (h, rest) => f(h); rest}).getOrElse(this)
}
def ^(n: Int): Stack[A] = {
(0 until n).foldLeft (this) ((stack, _) => stack ^ ())
}
override def toString: String = elems.mkString("\n")
}
// Stack was tested against Scala REPL
// Stack Type using List
import scala.util.{Failure, Success, Try}
class Stack[A] (private var elems: List[A] = List.empty[A]) {
def push(v: A) : Stack[A] = {
elems = v :: elems
this
}
def pushAll(xs: Iterable[A]) : Stack[A] = {
xs.foreach(push)
this
}
def pop() : Try[A] = {
if (this.isEmpty) {
Failure(new IllegalStateException("Empty Stack"))
} else {
val popped = elems.head
elems = elems.tail
Success(popped)
}
}
def top : Try[A] = {
if (this.isEmpty) {
Failure(new NoSuchElementException("Empty Stack"))
} else Success(elems.head)
}
def isEmpty : Boolean = elems.isEmpty
def size : Int = elems.length
def <(e: A) : Stack[A] = push(e)
def ^(f: A => Unit = _ => ()): Stack[A] = {
pop().map(f)
this
}
def ^(n: Int): Stack[A] = {
0 until n foreach (_ => pop())
this
}
override def toString: String = elems.mkString("\n")
}
// Stack was tested against Scala REPL
// Defining Main
object Main extends App {
val myStack = new Stack[String]
myStack.push("Wow").push("Err").push("Hi").push("Hackers")
println ("Stack Size = " + myStack.size)
println ("Stack: \n" + myStack)
println
println ("Is Empty = " + myStack.isEmpty)
myStack.top.map(elem => println (s"Top = $elem"))
println
myStack.pop().map(elem => println (s"Popping... $elem"))
myStack.pop().map(elem => println (s"Popping... $elem"))
myStack.pushAll(Vector("Universe", "World", "Earth")).pushAll(List("Scala", "Haskell"))
println ("Stack: \n" + myStack)
myStack.pop().map(elem => println (s"Popping... $elem"))
myStack.pop().map(elem => println (s"Popping... $elem"))
println ("Stack Size = " + myStack.size)
myStack.top.map(elem => println (s"Top = $elem"))
while (!myStack.isEmpty) myStack.pop().map(elem => println (s"Popping... $elem"))
println ("Is Empty = " + myStack.isEmpty)
println ("Stack Size = " + myStack.size)
myStack < "Yay" < "Foo" < "Wohoo" < "Bar"
println (myStack)
myStack ^ () // Pops
c ^ (2) ^ { third => // Pops 3 times
println(s"Third item popped is $third")
}
myStack.pop() match { // Should throw an exception which is handled by the Failure block
case Failure(except) =>
println("There was an exception")
except.printStackTrace
case _ => throw new IllegalStateException("Pop should not have worked on an empty stack")
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment