7 Replies
      Latest reply: Oct 9, 2016 11:48 AM by ahltorp RSS
      substractOne Level 1 Level 1 (0 points)

        Xcode Version 8.0 (8A218a); Playground;  Swift 3;

         

        sample1: initial code

        func fooA<C: Collection>(_ x: C)
            where C.Iterator.Element == UInt8, C.IndexDistance == Int
        {
            let a = x.prefix(10).first(where: {$0 == 0xbf})
            //        ^^^^ ##ERROR##: Ambiguous reference to member `prefix`
            print(a)
        }
        

         

        sample2: A few iterations later, trying to break expressions into simpler calls and removed inference.

        func fooD<C: Collection>(_ x: C)
            where C.Iterator.Element == UInt8, C.IndexDistance == Int
        {
            let x2: C.SubSequence = x.prefix(10)
            let z: UInt8 = 0xbf
            let a: UInt8? = x2.first(where: {
                // ##ERROR##: Cannot convert value of type `(UInt8) -> Bool` to expected argument type `(_) -> Bool`
                (a1: UInt8) -> Bool in
                return a1 == z
            })
            print(a)
        }
        

         

         

        I don't understand where's the ambiguity in "sample2".  I would greatly appreciate if someone could indicate where my failings.  Thank you!

        • Re: Removed Inference but code is seemingly still ambiguous
          ahltorp Level 3 Level 3 (410 points)

          Add the requirement C.SubSequence.Iterator.Element == UInt8:

           

          func fooD<C: Collection>(_ x: C)
              where C.IndexDistance == Int, C.SubSequence.Iterator.Element == UInt8
          
          
            • Re: Removed Inference but code is seemingly still ambiguous
              eskimo Apple Staff Apple Staff (6,250 points)

              Add the requirement C.SubSequence.Iterator.Element == UInt8:

              Yeah, that’s a fun gotcha: the elements of a subsequence don’t necessarily have to be of the same type as that of the parent sequence.  In situations like this I usually add the C.Iterator.Element == C.SubSequence.Iterator.Element requirement.

              Share and Enjoy

              Quinn “The Eskimo!”
              Apple Developer Relations, Developer Technical Support, Core OS/Hardware
              let myEmail = "eskimo" + "1" + "@apple.com"

                • Re: Removed Inference but code is seemingly still ambiguous
                  ahltorp Level 3 Level 3 (410 points)

                  Yes, I added that first, but then I figured it was easier to just change the requirement. This is bound to pop up now and then, so it should probably be a documented best practice somewhere. Which brings us to the question: what is the proper forum for best practices? The swift-evolution process doesn't seem to fit, or does it?

                  • Re: Removed Inference but code is seemingly still ambiguous
                    substractOne Level 1 Level 1 (0 points)

                    Interesting!

                     

                    Out of curiosity (and a bit of discussion), is there a known usecase where that — having a subsequence with different element type — would be needed?

                     

                    Not that having the potential is bad… Just asking to see if there's something I'm overlooking and could learn… Much like with cases where Sequence != SubSequence taught me about Slices.

                      • Re: Removed Inference but code is seemingly still ambiguous
                        eskimo Apple Staff Apple Staff (6,250 points)

                        Out of curiosity (and a bit of discussion), is there a known usecase where … having a subsequence with different element type … would be needed?

                        I think that we expect Sequence and SubSequence to always have the same element types but the Swift language can’t express that in the definition of those types and thus you have to do it yourself.  This is based on my reading of the Generics Manifesto, and specifically this quote:

                        Currently, a new protocol can inherit from other protocols, introduce new associated types, and add new conformance constraints to associated types (by redeclaring an associated type from an inherited protocol). However, one cannot express more general constraints. Building on the example from "Recursive protocol constraints", we really want the element type of a Sequence's SubSequence to be the same as the element type of the Sequence

                        If you want to go deeper into this I (again) recommend swift-users because we’re really butting up against the limits of my understanding of this stuff.

                        Share and Enjoy

                        Quinn “The Eskimo!”
                        Apple Developer Relations, Developer Technical Support, Core OS/Hardware
                        let myEmail = "eskimo" + "1" + "@apple.com"

                          • Re: Removed Inference but code is seemingly still ambiguous
                            ahltorp Level 3 Level 3 (410 points)

                            SE-0142:

                            Currently, associated type declarations can only express simple inheritance constraints and not the more sophisticated constraints available to generic types with the `where` clause. Some designs, including many in the Standard Library, require more powerful constraints for associated types to be truly elegant. For example, the `SequenceType` protocol could be declared as follows if the current proposal was accepted:
                            protocol Sequence {
                                associatedtype Iterator : IteratorProtocol
                                associatedtype SubSequence : Sequence where SubSequence.Iterator.Element == Iterator.Element
                                ...
                            }
                            

                             

                            This proposal has been accepted for Swift 4.