0

I can't quite figure out how to declare "if optional" on a stack using class on Swift. Here's the generic code that I have for a stack on Swift using class (the book uses struct but I was told to use class).

class Stack {
    var items = [String]()
    func push(item: String) {
        items.append(item)
    }
    func pop() -> String {
        return items.removeLast()
    }
    func length() -> Int {
        return items.count
    }
}

I create an instance of Stack:

var stringStack = Stack()
...
stringStack.pop()

when I pop, the stack removes the last item. I want to make it so that if I do pop(0), the stack will remove the first item, but if I just do pop(), the stack only removes the last item. I was thinking of making an optional value with if ... return items.removeAtIndex(0) or else items.removeLast(). I can't seem to get the syntax right and I keep getting error. I was able to make it so that pop(0) removes the first item in the stack, but I get error if I do pop(). If someone can show me a code to do what I want to do that would be really helpful. I'm still very, very new at coding and I don't know much. Sorry for the embarrassment!

Chrine
  • 57
  • 1
  • 7

2 Answers2

1

You're looking for an optional parameter with a default value. This way you'll be able to call either pop() to remove the last item from the stack or pop(index) to remove a particular item.

Calling pop with a parameter means the optional index has a value, so the first return is used. Calling without the parameter leaves index at its default value, so the if statement fails and you remove the last item instead.

func pop(_ index: Int? = nil) -> String {
    if let i = index {
        return items.removeAtIndex(i)
    }

    return items.removeLast()
}
// ...
stack.pop(0)
stack.pop()
Nate Cook
  • 92,417
  • 32
  • 217
  • 178
0

You have to overload the pop function, i.e. create 2 versions with different signature. Also I advice to return an optional, because if the array is empty, or if you ask it to pop an item that doesn't exist, it will generate a runtime exception. This is the modified version:

class Stack {
    var items = [String]()

    func push(item: String) {
        items.append(item)
    }

    func pop() -> String? {
        return length() > 0 ? items.removeLast() : nil
    }

    func pop(index: Int) -> String? {
        return index < length() ? items.removeAtIndex(index) : nil
    }

    func length() -> Int {
        return items.count
    }
}

One of the (most appreciated features) new features Swift has compared to Objective-C is generics, so why not using it in a container class like a stack? Here it is:

class Stack<T> {
    var items = [T]()

    func push(item: T) {
        items.append(item)
    }

    func pop() -> T? {
        return length() > 0 ? items.removeLast() : nil
    }

    func pop(index: Int) -> T? {
        return index < length() ? items.removeAtIndex(index) : nil
    }

    func length() -> Int {
        return items.count
    }
}

This way you can reuse it to store data of any type, and not limiting it to just strings

Antonio
  • 71,651
  • 11
  • 148
  • 165