1

I'm learning Scala and am making some Stack implementations as practice. I made this and there are some apparent issues.

class LinkedStack[T] extends Stack[T] {
  var current: Node = null
  var n: Int = 0

  private class Node(e: T, prev: Node) {
    val element: T = e
    var previous: Node = prev
  }

  override def pop(): T = {
    if (n == 0) {
      throw new NoSuchElementException
    }
    val popNode: Node = current
    current = current.previous
    popNode.previous = null
    n -= 1

    popNode.element
  }

  override def peek(): T = {
    if (n == 0) {
      throw new NoSuchElementException
    }

    current.element
  }

  override def push(element: T): Unit = {
    if (element == null) {
      throw new NullPointerException
    }
    val newNode: Node = new Node(element, current)
    current = newNode

    n += 1
  }

  override def size(): Int = {
    n
  }

  override def toString(): String = {
    val builder = new StringBuilder("Stack top [")
    var temp: Node = current

    if (n == 0) {
      builder.append("]")
      return builder.toString()
    }
    while (temp.previous != null) {
      builder.append(temp.element).append(", ")
      temp = temp.previous
    }

    builder.append(temp.element).append("]")

    builder.toString()
  }
}

The trait includes all of the elements except toString. My main problem is that I'm using null pretty liberally. I know this shouldn't be done at all in Scala, and the line

var current: Node = null

in the constructor generates a compile error. How should I implement a constructor to create an empty stack? What's the best substitution for null?

Edit: You may have noticed that the Node class should be rewritten as

private class Node(val element: T, var previous: Node) {}

I realized this after reading Rex Kerr's answer. I forgot that I was programming in Scala when I first wrote that.

3
  • 2
    To avoid null, immutability must be favored (no var) Commented Jul 12, 2015 at 20:48
  • mutable.Stack is based on ListBuffer with source github.com/scala/scala/blob/v2.10.4/src/library/scala/… in which "val empty: Stack[Nothing] = new Stack(Nil)". Immutable.Stack is based on List with source in github.com/scala/scala/blob/v2.10.4/src/library/scala/… and the issue is avoided essentially by using the Nil of the empty List as the empty Stack. Both are good references for Scala stack design. Commented Jul 12, 2015 at 21:47
  • 1
    @cchantep - The converse is more true. If you have immutability, null is an even bigger pain to deal with. You can avoid null easily enough mutably, though. Commented Jul 13, 2015 at 3:21

2 Answers 2

2

There's nothing terribly wrong with using null as part of the internals for your class as long as those nulls never leak out and the logic is straightforward enough so you can be sure of that.

But if you want to not use null for practice, you have two choices. One is to use a built-in alternative: instead of Node use Option[Node] and use None for null. Given that your list is invariant, this is the easier way.

Second, you can replace Node with a hierarchy like so:

trait Node
class Elt(val element: T, val previous: Node) extends Node {}
object End extends Node

And then you use End wherever you use null now, and match on the Node any time you need to walk or do something, e.g.

def peek = current match {
  case End => throw new NoSuchElementException
  case Elt(e, _) => e
}

Of course this means each list has to create an extra object (End), and there are various other drawbacks, most of which can be gotten around to some extent. But for an exercise in avoiding null, you can ignore those complications.

Sign up to request clarification or add additional context in comments.

3 Comments

Agreed that nothing is terribly wrong by using null internally but still I would make the fact - that a var might be null - explicit by using an Option , independent of the whole structure being mutable or immutable (a very very tiny memory and time overhead but a huge advantage of avoiding mistakes and such).
@RexKerr The first option would make pushing the first element problematic since node.previous cannot point to a none instance. Is there any way around that?
@user3599828 - You make node.previous hold Option[Node].
1

i'm also scala learning my stack implementation ,it;s simple i used scala mutable array buffer

object Stack{
var stack=scala.collection.mutable.ArrayBuffer[Int]()

def isEmpty():Boolean={
  if(stack.length==0) true
  else false
}

def push(input:Int):Unit={
  stack+=input
}

def size():Int={
  stack.length
}

 def pop():Int={
   stack.remove(stack.length-1)
 }

def peek()={
   stack(stack.length-1)
 }

}

1 Comment

ArrayBuffer is mutable. There is no reason to make stack a var as well.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.