Welcome to the Treehouse Community

The Treehouse Community is a meeting place for developers, designers, and programmers of all backgrounds and skill levels to get support. Collaborate here on code errors or bugs that you need feedback on, or asking for an extra set of eyes on your latest project. Join thousands of Treehouse students and alumni in the community today. (Note: Only Treehouse students can comment or ask questions, but non-students are welcome to browse our conversations.)

Looking to learn something new?

Treehouse offers a seven day free trial for new students. Get access to thousands of hours of content and a supportive community. Start your free trial today.

iOS Generics in Swift Generics and Protocols Extending Generic Types

Make sure the function you're adding matches the signature exactly as described

I'm doing it and it doesn't work knowing that matching the signature exactly would work too

generics.swift
protocol PrefixContaining {
  associatedtype Element

    var result: Array<Element> {get}
    func hasPrefix(_ prefix: String) -> Bool
    func filter(byPrefix prefix: String) -> [Element]
}

extension Array where Element: PrefixContaining {

func filter(byPrefix prefix: (Element) -> Bool) -> [Element] {
        var result = Array<Element>()
        for x in self where prefix(x) {

            result.append(x)
        }

        func hasPrefix(_ prefix: String) -> Bool {
            if prefix.hasPrefix("a") {

                return true
            } else {

                return false
            }

        return result

        }
    }

}



// Enter code below

7 Answers

Simon Di Giovanni
Simon Di Giovanni
8,429 Points

Hi John

Your code is far too complicated than necessary, you may have overthought it.

Firstly, you're getting that error because your filter function accepts a function as an argument, rather than simply a String.

Secondly, you've defined a 'hasPrefix' function, however this is built into swift. You have no need to define this.

I've included my code that passes this below.

If you have any questions at all about this please let me know.

extension Array where Element: PrefixContaining {
    func filter(byPrefix prefix: String) -> [Element] {
        var foundValue: [Element] = []

        for elements in self {
            if let elementsAsString = elements as? String {
                if elementsAsString.hasPrefix(prefix) {
                    foundValue.append(elements)
                } 
            }
        }

        return foundValue

        }
}

Hi Simon,

thks but the compiler is giving me an error.

Simon Di Giovanni
Simon Di Giovanni
8,429 Points

Hi John

I've doubled checked my code, and this code definitely passes the challenge so you should not have any issues.

Could you please show me how you've applied my code to your code challenge, to check for any errors?

Thanks Simon

sure: protocol PrefixContaining { associatedtype Element

func filter(byPrefix prefix: String) -> [Element]

}

extension Array where Element: PrefixContaining { func filter(byPrefix prefix: String) -> [Element] { var foundValue: [Element] = [] for elements in self { if let elementsAsString = elements as? String { if elementsAsString.hasPrefix(prefix) { foundValue.append(elements)

            }

        }

    }
    return foundValue

}

}

Simon Di Giovanni
Simon Di Giovanni
8,429 Points

Thanks John

You need to remove the 'func filter' from BEFORE the extension Array part.

Try that out , let me know how you go

do you mean from the protocol?

Simon Di Giovanni
Simon Di Giovanni
8,429 Points

Basically, you're ENTIRE code should look like this

protocol PrefixContaining {
  func hasPrefix(_ prefix: String) -> Bool
}

extension String: PrefixContaining {}

extension Array where Element: PrefixContaining {
    func filter(byPrefix prefix: String) -> [Element] {
        var foundValue: [Element] = []

        for elements in self {
            if let elementsAsString = elements as? String {
                if elementsAsString.hasPrefix(prefix) {
                    foundValue.append(elements)
                } 
            }
        }

        return foundValue

        }
}

thks Simon! it works! but as always an other murky challenge, I don't get why the filter function appear in the extension array without conforming to the protocol.

Simon Di Giovanni
Simon Di Giovanni
8,429 Points

No worries John! Please mark my answer as 'Best answer' to ensure it's marked as answered.

Regarding why the filter function appears in the extension array - let me try to explain.

We are using the 'where' keyword to say that we want to write an extension to Array where the ELEMENT conforms to the protocol PrefixContaining. NOT the Array, but the ELEMENT INSIDE the array.

So therefore, the Array does not need to conform to PrefixContaining.

Does this make sense?

absolutely, thks

Deysha Rivera
Deysha Rivera
5,088 Points

I get why we used the extension, but I do not understand how I was supposed to figure out how to write the function. I'm not even sure I've seen a "for in self" loop at this point, and I don't understand why we use "as?" here.

Deysha Rivera
Deysha Rivera
5,088 Points

I found this solution to be far simpler and easier to understand.

    func filter(byPrefix prefix: String) -> [Element] {
        var filteredArray = Array<Element>()
        for element in self {
            if(element.hasPrefix(prefix)) {
                filteredArray.append(element)
            }
        }
        return filteredArray
    }