> On Feb 22, 2017, at 3:00 PM, Slava Pestov <[email protected]> wrote:
>
>
>> On Dec 23, 2016, at 12:32 PM, David Sweeris via swift-evolution
>> <[email protected] <mailto:[email protected]>> wrote:
>>
>> (I feel like I’ve already written this... I looked through my sent mail and
>> didn’t see anything, but my sincerest apologies if I started this thread a
>> month ago and forgot about it or something.)
>>
>> I no longer recall exactly what first made me want to do this (probably
>> something in my on-going “teach the compiler calculus” project), but I’ve
>> been thinking lately that it could be quite handy to overload types
>> themselves based on the value of generic parameters. As a somewhat contrived
>> example:
>> struct Array <T> { /*everything exactly as it is now*/ }
>> struct Array <T> where T == Bool { /* packs every 8 bools into a UInt8 for
>> more efficient storage */ }
>>
>> We can already do this with functions… Conceptually this isn’t any different.
>
> Actually this is a major complication because of the runtime generics model.
> Imagine you have a function that takes a T and constructs an Array<T>. Now it
> has to do dynamic dispatch to find the right type metadata (is it the
> “generic” Array<T>, or the specialized Array<Bool>?)
Wouldn’t that get resolved at compile time? Oh! Wait, are you talking about
this?
func bar <T> (_ x: T) -> String { return "any T" }
func bar <T> (_ x: T) -> String where T: CustomStringConvertible { return
"\(x)" }
func foo <T> (_ x: T) -> String { return bar(x) }
and “foo()" always returns “any T” because by the time we get to `bar`, T isn’t
known to be constrained to anything at compile time?
In any case, since the point is to optimize the type's implementation rather
than change its behavior, I think the only result is that your array maker
function would return an “unoptimized” array. I’m not sure… I’d have to think
about it some more. And come up with a better illustration, since it’s been
pointed out that my original example isn’t a particularly good idea.
>> As long as the specific version exposes everything the generic version does
>> (easy for the compiler to enforce), I think everything would just work
>> (famous last words).
>
> What if another module defines an extension of Array<T>, but not ‘Array<T>
> where T == Bool’?
IIUC, that shouldn’t matter because the specific version would have to have the
same public interface as the generic version.
>> In this example, the subscript function would need to extract the specified
>> bit and return it as a Bool instead of simply returning the specified
>> element. The `Element` typealias would be `Bool` instead of `UInt8`, which
>> would mean the size/stride might be different than expected (but that’s why
>> we have `MemoryLayout<>`).
>>
>> Anyway, because generic structs & functions already can’t make assumptions
>> about a generic argument (beyond any constraints, of course), I think this
>> should be in phase 2… but I’m quite hazy on how generics work once the
>> code’s been compiled, so maybe not.
>
> Another way of modeling this might be to define a protocol, say
> “RepresentableInArray”, which implements get and set methods that take a
> pointer to a buffer, and an index. A default implementation in a protocol
> extension would just load and store the value. ‘Bool’ would define its own
> conformance which performs bitwise operations.
>
> However I think this is out of scope for stage 2 — it doesn’t fix any obvious
> major shortcoming in the language, it vastly complicates the implementation
> and it’s not required to achieve our ABI stability goals.
Fair enough. Is there a stage 3, or does that mean “out of scope until Swift
4.1+”?
- Dave Sweeris_______________________________________________
swift-evolution mailing list
[email protected]
https://lists.swift.org/mailman/listinfo/swift-evolution