> On 12 Mar 2017, at 08:50, Xiaodi Wu <[email protected]> wrote:
>
> On Sun, Mar 12, 2017 at 1:39 AM, Karl Wagner <[email protected]
> <mailto:[email protected]>> wrote:
>
>> On 12 Mar 2017, at 08:21, Xiaodi Wu <[email protected]
>> <mailto:[email protected]>> wrote:
>>
>> Sorry, I'm confused. The following works:
>>
>> ```
>> protocol Promise {
>> associatedtype Result
>> }
>>
>> protocol Scanner {
>> associatedtype ScannerPromise : Promise
>> func frobnicate<T>(_: T) -> ScannerPromise
>> where ScannerPromise.Result == T
>> }
>> ```
>>
>> Why does it matter if `ScannerPromise` is generic or not?
>>
>
> That’s some pretty strange syntax. I admit I didn’t even try that.
> ScannerPromise would necessarily have to be generic in this context, because
> I want to bind one of its associated types to a generic parameter from a
> function. There is no way a non-generic type could do that.
>
> That said, even though the compiler accepts your code, it doesn’t seem to
> actually work:
>
> protocol Promise {
> associatedtype Result
> func await() -> Result
> }
>
> protocol Scanner {
> associatedtype ScannerPromise : Promise
> func frobnicate<T>(_: T) -> ScannerPromise
> where ScannerPromise.Result == T
> }
>
> func use<S: Scanner, T>(_ s: S, _ t: T) -> T {
> return s.frobnicate(t).await()
> }
>
>
> 3.0.2: Segfault
>
> 3.1:
>
> error: repl.swift:13:14: error: cannot invoke 'frobnicate' with an argument
> list of type '(T)'
> return s.frobnicate(t).await()
> ^
>
> repl.swift:13:14: note: expected an argument list of type '(T)'
> return s.frobnicate(t).await()
>
> That's because your `T` in `use` has no relationship with your `T` in
> `protocol Scanner`; you just happen to have chosen the same letter of the
> alphabet. This becomes clear if you rename:
>
> ```
> func use<S: Scanner, U>(_ s: S, _ t: U) -> U {
> return s.frobnicate(t).await()
> }
>
> // cannot invoke 'frobnicate' with an argument list of type '(U)'
> // expected an argument list of type '(T)'
> ```
>
> However, this works:
>
> ```
> func use<S: Scanner, T>(_ s: S, _ t: T) -> T
> where S.ScannerPromise.Result == T {
> return s.frobnicate(t).await()
> }
> ```
>
> ...or just this:
>
> ```
> func use<S: Scanner>(
> _ s: S, _ t: S.ScannerPromise.Result
> ) -> S.ScannerPromise.Result {
> return s.frobnicate(t).await()
> }
> ```
>
> - Karl
No, what you’ve done is something different. “frobnicate” is itself a generic
function, so it should work if you rename the parameter to “U". You’ve just
punted the constraint down the abstraction hierarchy.
This becomes clear if you try to continue working at the protocol-level:
extension Scanner {
func synchronised_frob<T>(_ t: T) -> T {
return frobnicate(t).await()
}
}
error: repl.swift:14:16: error: cannot invoke 'frobnicate' with an argument
list of type '(T)'
return frobnicate(t).await()
^
repl.swift:14:16: note: expected an argument list of type '(T)'
return frobnicate(t).await()
- Karl
_______________________________________________
swift-evolution mailing list
[email protected]
https://lists.swift.org/mailman/listinfo/swift-evolution