<div dir="ltr">That will not work since R can be different types depending on T (R == (T, T) for S2 and R == (T, T, T) for S3).<div>I guess Swift would have to support generic associated type for it to work:</div><div><div style="font-size:12.800000190734863px">protocol P {</div><div style="font-size:12.800000190734863px"> associatedtype R<U></div><div style="font-size:12.800000190734863px"> static func foo<T>(_ v: T) -> R<T></div><div style="font-size:12.800000190734863px">}<br></div><div style="font-size:12.800000190734863px">struct S2 : P {</div><div style="font-size:12.800000190734863px"> typealias R<U> = (U, U)</div><div style="font-size:12.800000190734863px"> static func foo<T>(_ v: T) -> R<T> {</div><div style="font-size:12.800000190734863px"> return (v, v)</div><div style="font-size:12.800000190734863px"> }</div><div style="font-size:12.800000190734863px">}</div><div style="font-size:12.800000190734863px">struct S3 : P {</div><div style="font-size:12.800000190734863px"> typealias R<U> = (U, U, U)</div><div style="font-size:12.800000190734863px"> static func foo<T>(_ v: T) -> R<T> {</div><div style="font-size:12.800000190734863px"> return (v, v, v)</div><div style="font-size:12.800000190734863px"> }</div><div style="font-size:12.800000190734863px">}</div></div><div style="font-size:12.800000190734863px"><br></div><div style="font-size:12.800000190734863px">But (sadly) according to previous discussions it seems like generic associated types are very much out of scope for Swift 4.</div><div style="font-size:12.800000190734863px"><br></div><div style="font-size:12.800000190734863px">PS</div><div style="font-size:12.800000190734863px"><br></div><div style="font-size:12.800000190734863px">The generic static func was only a (what I guess is another) failed attempt at a workaround, and what I'm really trying to achieve is something that is perhaps better described like this:</div><div style="font-size:12.800000190734863px"><br></div><div style="font-size:12.800000190734863px">protocol VectorCount {</div><div style="font-size:12.800000190734863px"> associatedtype Storage<E></div><div style="font-size:12.800000190734863px">}</div><div style="font-size:12.800000190734863px">…</div><div style="font-size:12.800000190734863px">enum VectorCount2 : VectorCount {</div><div style="font-size:12.800000190734863px"> typealias Storage<E> = (E, E)</div><div style="font-size:12.800000190734863px"> …</div><div style="font-size:12.800000190734863px">}</div><div style="font-size:12.800000190734863px">enum VectorCount3 : VectorCount {</div><div style="font-size:12.800000190734863px"> typealias Storage<E> = (E, E, E)</div><div style="font-size:12.800000190734863px"> …</div><div style="font-size:12.800000190734863px">}</div><div style="font-size:12.800000190734863px">…</div><div style="font-size:12.800000190734863px">struct Vector<Count: VectorCount, Element> {</div><div style="font-size:12.800000190734863px"> var elements: Count.Storage<Element></div><div style="font-size:12.800000190734863px"> …</div><div style="font-size:12.800000190734863px">}</div><div style="font-size:12.800000190734863px"><br></div><div style="font-size:12.800000190734863px">That is, Vector is a statically allocated array type, with type level Count and Element as type parameters.</div><div style="font-size:12.800000190734863px">I currently have a solution which is based around separate generic vector types for each VectorCountX type, but they are generic only over Element not both Count and Element, like this:</div><div style="font-size:12.800000190734863px">…</div><div style="font-size:12.800000190734863px">protocol VectorProtocol {</div><div style="font-size:12.800000190734863px"> associatedtype Count: VectorCount</div><div style="font-size:12.800000190734863px"> associatedtype Element</div><div style="font-size:12.800000190734863px"> …</div><div style="font-size:12.800000190734863px">}</div><div style="font-size:12.800000190734863px">struct V2<Element> : VectorProtocol {</div><div style="font-size:12.800000190734863px"> typealias Count = VectorCount2</div><div style="font-size:12.800000190734863px"> var elements: (Element, Element)</div><div style="font-size:12.800000190734863px"> …</div><div style="font-size:12.800000190734863px">}</div><div style="font-size:12.800000190734863px">struct V3<Element> : VectorProtocol {</div><div style="font-size:12.800000190734863px"> typealias Count = VectorCount3</div><div style="font-size:12.800000190734863px"> var elements: (Element, Element, Element)</div><div style="font-size:12.800000190734863px"> …</div><div style="font-size:12.800000190734863px">}<br></div><div style="font-size:12.800000190734863px">…</div><div style="font-size:12.800000190734863px">And you can of course also make specific types like eg:</div><div style="font-size:12.800000190734863px">struct RgbaFloatsSrgbGamma : Vector {</div><div style="font-size:12.800000190734863px"> typealias Count = VectorCount4</div><div style="font-size:12.800000190734863px"> typealias Element = Float</div><div style="font-size:12.800000190734863px"> …</div><div style="font-size:12.800000190734863px">}</div><div style="font-size:12.800000190734863px"><br></div><div style="font-size:12.800000190734863px">It's working and it can be written in a way such that the optimizer can do a good job, vectorizing operations on vectors of 4 floats etc. It also makes it possible to write generic Table<Element, Index> where Index is an N-dimensional vector of Int elements, which enables me to write N-dimensional data processing generically, eg a calculating a summed area table for data of any dimension, etc. But it would be much better to base the vector types around a concept in which both Element and Count are type parameters, and not just Element, ie Vector<Count, Element> rather than V1<Element>, V2<Element>, …</div><div style="font-size:12.800000190734863px"><br></div><div style="font-size:12.800000190734863px">/Jens</div><div style="font-size:12.800000190734863px"><br></div></div><div class="gmail_extra"><br><div class="gmail_quote">On Fri, Jul 7, 2017 at 6:49 PM, Slava Pestov <span dir="ltr"><<a href="mailto:spestov@apple.com" target="_blank">spestov@apple.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Try using an associated type for the result of foo():<br>
<br>
protocol P {<br>
associatedtype R<br>
<br>
static func foo<T>(_ v: T) -> R<br>
}<br>
<br>
Slava<br>
<div><div class="h5"><br>
> On Jul 7, 2017, at 1:50 AM, Jens Persson via swift-users <<a href="mailto:swift-users@swift.org">swift-users@swift.org</a>> wrote:<br>
><br>
> protocol P {<br>
> // …<br>
> // For example the following will not work:<br>
> // static func foo<T, R>(_ v: T) -> R<br>
> // Is there some other way?<br>
> // …<br>
> }<br>
> struct S2 : P {<br>
> static func foo<T>(_ v: T) -> (T, T) {<br>
> return (v, v)<br>
> }<br>
> }<br>
> struct S3 : P {<br>
> static func foo<T>(_ v: T) -> (T, T, T) {<br>
> return (v, v, v)<br>
> }<br>
> }<br>
><br>
> (I'm guessing but am not sure that I've run into (yet) a(nother) situation which would require higher kinded types?)<br>
</div></div>> ______________________________<wbr>_________________<br>
> swift-users mailing list<br>
> <a href="mailto:swift-users@swift.org">swift-users@swift.org</a><br>
> <a href="https://lists.swift.org/mailman/listinfo/swift-users" rel="noreferrer" target="_blank">https://lists.swift.org/<wbr>mailman/listinfo/swift-users</a><br>
<br>
</blockquote></div><br></div>