[swift-users] returning an array of Protocol-conforming objects from a function
Ryan Walklin
ryan at testtoast.com
Tue Jan 26 21:51:20 CST 2016
Hi Jordan,
Thanks for your reply. I’ve since discovered the differences in memory representation that you mention, and the performance implications of the conversion.
I’ve worked around this by just using a typed array, as the eventual destination for the array is a Metal buffer via memcpy, so I need a contiguous array.
Regards,
Ryan
> On 27 Jan 2016, at 5:56 AM, Jordan Rose <jordan_rose at apple.com> wrote:
>
> The problem is that an array of protocols is stored using a different representation from an array of plain structs (or classes, for that matter). Converting from [Float] to [MyProtocol] is therefore an O(N) operation, while a normal upcast between class types is O(1) (by sharing the underlying storage).
>
> This does keep tripping people up, though, so maybe an explicit "as" should be considered good enough. The typical workarounds are either to use "as [MyProtocol]" to begin with (as Trent mentioned) or to use 'map' to build a new array ("return a.map { $0 }").
>
> (Any change in this space would need to go through the Swift Evolution Process <https://github.com/apple/swift-evolution/blob/master/process.md>.)
>
> Best,
> Jordan
>
>
>> On Jan 25, 2016, at 19:58, Ryan Walklin via swift-users <swift-users at swift.org <mailto:swift-users at swift.org>> wrote:
>>
>> Hi Austin,
>>
>> Thanks for your reply. Sorry you’re right, my struct types don’t work if they are in in existing array of type [MyType] as below.
>>
>> I’ve been trying to work round it and found that with the following code:
>>
>> extension MyType: MyProtocol {}
>>
>> var array1: [MyType]
>>
>> fun foo() -> [MyProtocol] {
>> return array1
>> }
>>
>> func foo2 -> [MyProtocol] {
>> return [myType1, myType2]
>> }
>>
>>
>> The foo pattern fails, but the foo2 pattern works. My existing code with struct type was all of type foo2, so I didn’t appreciate the error. As you stay, still seems like a problem with type inference.
>>
>> Ryan
>>
>>> On 26 Jan 2016, at 2:47 PM, Austin Zheng <austinzheng at gmail.com <mailto:austinzheng at gmail.com>> wrote:
>>>
>>> Hi Ryan,
>>>
>>> Are you sure it works with user-defined struct types? I tried the following code, and got the same error:
>>>
>>> protocol MyProtocol {}
>>>
>>> struct Blah : MyProtocol { }
>>>
>>> func foo() -> [MyProtocol] {
>>> let a = [Blah(), Blah()] as [Blah]
>>> return a
>>> }
>>>
>>> 'class Blah' works fine.
>>>
>>> Even so, this is not the behavior I would have expected. Perhaps someone else can explain why [T] can't be upcasted to [P] when T is a struct and T : P.
>>>
>>> Best,
>>> Austin
>>>
>>>
>>>> On Jan 25, 2016, at 7:36 PM, Ryan Walklin via swift-users <swift-users at swift.org <mailto:swift-users at swift.org>> wrote:
>>>>
>>>> Hi All,
>>>>
>>>> I have a function which returns a closure, which then returns an array of objects conforming to a protocol.
>>>>
>>>> ie.
>>>>
>>>> protocol MyProtocol {}
>>>>
>>>> extension Float: MyProtocol {}
>>>> extension OtherType: MyProtocol {}
>>>>
>>>> When I try to return an array of Floats, I get the error “Cannot convert value of type '[Float]' to closure result type ‘[MyProtocol]”.
>>>>
>>>> Other struct-based types work fine.
>>>>
>>>> Is this not possible with standard library types?
>>>>
>>>> Regards,
>>>>
>>>> Ryan
>>>> _______________________________________________
>>>> swift-users mailing list
>>>> swift-users at swift.org <mailto:swift-users at swift.org>
>>>> https://lists.swift.org/mailman/listinfo/swift-users <https://lists.swift.org/mailman/listinfo/swift-users>
>>>
>>
>> _______________________________________________
>> swift-users mailing list
>> swift-users at swift.org <mailto:swift-users at swift.org>
>> https://lists.swift.org/mailman/listinfo/swift-users
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.swift.org/pipermail/swift-users/attachments/20160127/15caa0dc/attachment.html>
More information about the swift-users
mailing list