0

I would like to give my STACK struct the function contains(element: Element) that returns a bool as to whether var contents contains the element provided.

struct Stack<T>: SequenceType, Equatable, Printable, DebugPrintable {
     typealias Element = T
     private var contents: [Element]
     var top: Int

     init(arrayLiteral elements: T...) {
          self.init(elements) }

     // easier initialization
     init<S: SequenceType where S.Generator.Element == Element>(_ sequence: S) {
          self.contents = [Element]()
          Swift.map(sequence) {self.contents[$0] = true }
     }

     // returns TRUE if the Stack contains <T> 'element'
     func contains(element: Element) -> Bool {
         return contents.filter(element != nil) ?? false
     }

I would like to be able to define a new STACK and search its contents like so:

 var newStack: Stack = [5, 23, 45, 100]
 newStack.contains(45)                      // returns TRUE

Currently the compiler gives an error of:

"Cannot invoke '??' with an argument list of type '(Array, BooleanLiteralConvertible)' "

jww
  • 97,681
  • 90
  • 411
  • 885
Sean
  • 377
  • 3
  • 12
  • 1
    What's the question? And what's the problem? – Antonio Jan 08 '15 at 22:32
  • Antonio — Sorry I forgot to add that... Added it to the bottom. – Sean Jan 08 '15 at 22:35
  • 1
    Something's also off about your initializer there. You're starting with a blank array, then trying to use a sequence of incoming types as indices into that array? Given that you haven't restricted Element to be a numeric type, that doesn't seem like it would work. Also, you'd immediately go off the end of your blank array and get an exception. – Brad Larson Jan 08 '15 at 22:55
  • Brad — Yes, I see what you mean to some extent. With this I'm trying to allow for initialization without the need to declare the variable first. Similar to an Array allowing assignment and initialization in one full swoop. I currently have: – Sean Jan 08 '15 at 23:35
  • init(_ sequence: S) { self.contents = [Element]() Swift.map(sequence) { self.contents[$0] } } – Sean Jan 08 '15 at 23:39
  • However it results in the following error: Cannot invoke 'subscript' with an argument list of type '(S, (($T3) -> ($T3) -> ($T2) -> (($T3) -> $... – Sean Jan 08 '15 at 23:40

1 Answers1

3

First of all, the generic element type T must conform to Equatable so that you can compare the given element with the array elements using ==:

struct Stack<T : Equatable> : YourProtocols... {

The filter methods takes a closure which tests each array element:

let filtered = contents.filter({ $0 == element})

and returns a new array containing only the elements for which the test (the "predicate") yields true. But you don't need a new array, you want to test only for membership, and that can be done with the Swift contains() function:

func contains(element: Element) -> Bool {
    return Swift.contains(contents, element)
}

Btw, your init method does not compile. It seems to be copied from a different collection type where the elements are stored in a dictionary. Here you can simply use that an array can be initialized with a sequence:

init<S: SequenceType where S.Generator.Element == Element>(_ sequence: S) {
    self.contents = Array(sequence)
}
Martin R
  • 529,903
  • 94
  • 1,240
  • 1,382