迅速普遍存在 [英] Swift Generalized Existentials

查看:115
本文介绍了迅速普遍存在的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

除了冗余介绍之外,我想要的是这样的:

  let collection:Any< Sequence where .Iterator.Element ==字符串> = ... 

  let collection:Sequence< where .Iterator.Element == String> = ... 

这在 Apple's Generics Manifesto 。 (我认为)我真的需要一些用例和这个:


协议'P'只能用作通用因为
具有Self或相关类型的要求。

使得第一种面向协议的语言对我来说很麻烦理解。缺乏这个使我打败Swift的类型系统,并创建不利的通用抽象类,其中应该有一个协议,其中 associatedtype



下面是一个例子,这个例子给我带来了最大的委托:泛型类的委托:

$ p $协议GenericClassDelegate类{
associatedtype ItemType
func didDoThat(who:GenericClass< ItemType>)
}

class GenericClass< T> {
weak var delegate:GenericClassDelegate< where .ItemType == T> ;? //不能这样做

func notify(){
委托?.didDoThat(who:self)
}
}
GenericClassDelegate 协议,但我(目前在Swift 3中)可以使用c code

>

没有该类型的变量或常量(或符合限制的任何类型)。 不要将此问题与如何使用泛型协议作为变量类型 Swift委托协议class ,因为我的问题是:


  1. 目前是否有任何建议或讨论介绍将广义存在变为Swift,计划是什么?如果不是,我该如何参与并影响它?

  2. 如果Swift是这样设计的(使用关联类型但没有广义存在),也许这意味着一些架构转变。我希望用什么方式取代委托模式?

当你在闭包中捕获委托函数时,不要建议使用类型删除的thunk,这是非常错误和误导性的,我甚至称它为拐杖。



意外找到了另一个解决方案,但我并不完全满意:

 协议GenericClassDelegate:class {
associatedtype ItemType
$ func didDoThat(who:GenericClass< ItemType,Self>)
}

class GenericClass< T,Delegate:GenericClassDelegate> Delegate.ItemType == T {
weak var delegate:Delegate?

func notify(){
delegate?.didDoThat(who:self)
}

init(_ delegate:Delegate?){
self.delegate = delegate
}
}

//委托必须是最终类,否则它不会编译
//因为我在GenericClassDelegate中使用了Self
final class GenericClassDelegateImp< T> :GenericClassDelegate {
typealias ItemType = T
func didDoThat(GenericClass< T,GenericClassDelegateImp>){
print(who)
}
}

//用法:
var delegate = GenericClassDelegateImp< Int>()
var genericClass = GenericClass< Int,GenericClassDelegateImp< Int>>(delegate)


解决方案


有没有关于将广义存在斯威夫特,有什么计划?如果不是,我该如何参与并影响它?


这是一个常见的功能,并且已经在swift上进行了初步设计-演化。但目前,核心团队和社区都关注ABI稳定性影响功能,或者Lattner定义为Swift 4 Phase 1。

你一定会听到第二阶段开始时更多关于它。如果Swift是这样设计的(使用关联类型,但没有泛化)存在),也许它意味着一些建筑转变。我期望用什么替换委托模式?


您可以使用删除类型的包装器作为传递解决方案。通常,它利用动态分派和类的继承来擦除类型。

 协议花式{
associatedtype值
var value:值
}

struct FancyMatter< Value> {
let value:Value
}

class AnyFancyBoxBase< P:FancyProtocol> ;: AnyFancyBox< P.Value> {
let base:P
覆盖var值:P.Value {返回base.value}
init(_ base:P){self.base = base}
}

类AnyFancyBox<值> {
var value:Value {fatalError()}
}

var box:AnyFancyBox< Int> = AnyFancyBoxBase(FancyMatter(1))

你可以看看标准库如何实现删除类型的包装器


Redundant introduction aside, I want to have something like this:

let collection : Any<Sequence where .Iterator.Element == String> = ...

or

let collection : Sequence<where .Iterator.Element == String> = ...

This is referred to as "Generalized existentials" in Apple's Generics Manifesto. (I think) I really need this for a number of use cases and this:

protocol 'P' can only be used as a generic constraint because it has Self or associated type requirements.

makes "the first Protocol Oriented Language" be cumbersome for me to understand. Lack of this makes me fight Swift's type system and create adverse generic "abstract" classes where there should be a protocol with associatedtype.

Here's one example, that hit me the most, delegate for a generic class:

protocol GenericClassDelegate : class {
    associatedtype ItemType
    func didDoThat(who : GenericClass<ItemType>) 
}

class GenericClass<T> {
    weak var delegate : GenericClassDelegate<where .ItemType == T>? // can't do that

    func notify() {
        delegate?.didDoThat(who: self)
    }
}

While I can describe GenericClassDelegate protocol, I (currently in Swift 3) can't have a variable or constant of that type (or any type conforming to restrictions).

Don't confuse this question with How to use generic protocol as a variable type or Swift delegate protocol for generic class, as my questions are:

  1. Are there any proposals or discussions currently present on introducing Generalized Existentials into Swift, what are the plans? If no, how can I participate and affect this?
  2. If Swift was designed that way (with Associated Types, but without Generalized Existentials), maybe it implies some architectural shift. What am I expected to replace delegation pattern with?

P.S. Don't suggest thunks with type erasure when you capture delegate's function in a closure, that is so much wrong and misleading, I'd even call it a crutch.

Accidentally found another solution, but I'm not satisfied with it completely:

protocol GenericClassDelegate : class {
    associatedtype ItemType
    func didDoThat(who : GenericClass<ItemType, Self>)
}

class GenericClass<T, Delegate : GenericClassDelegate> where Delegate.ItemType == T {
    weak var delegate : Delegate?

    func notify() {
        delegate?.didDoThat(who: self)
    }

    init(_ delegate : Delegate?) {
        self.delegate = delegate
    }
}

// Delegates must be final classes, otherwise it does not compile
// because I used Self in GenericClassDelegate
final class GenericClassDelegateImp<T> : GenericClassDelegate {
    typealias ItemType = T
    func didDoThat(who: GenericClass<T, GenericClassDelegateImp>) {
        print(who)
    }
}

// Usage:
var delegate = GenericClassDelegateImp<Int>()
var genericClass = GenericClass<Int, GenericClassDelegateImp<Int>>(delegate)

解决方案

Are there any proposals or discussions currently present on introducing Generalized Existentials into Swift, what are the plans? If no, how can I participate and affect this?

It is a commonly requested feature, and there was already preliminary design effort on swift-evolution. But at this moment, the core team and the community are focusing on ABI stability affecting features, or what Lattner defines as "Swift 4 Phase 1".

You would definitely hear more about it when Phase 2 commences. Given its popularity, it is expected to be part of Swift 4.

If Swift was designed that way (with Associated Types, but without Generalized Existentials), maybe it implies some architectural shift. What am I expected to replace delegation pattern with?

You can use type-erased wrappers as a transitive solution. In general, it exploits the dynamic dispatch and the inheritance of classes to erase the type.

protocol Fancy {
    associatedtype Value
    var value: Value
}

struct FancyMatter<Value> {
    let value: Value
}

class AnyFancyBoxBase<P: FancyProtocol>: AnyFancyBox<P.Value> {
    let base: P
    override var value: P.Value { return base.value }
    init(_ base: P) { self.base = base }
}

class AnyFancyBox<Value> {
    var value: Value { fatalError() }
}

var box: AnyFancyBox<Int> = AnyFancyBoxBase(FancyMatter(1))

You may take a look at how the Standard Library implements type-erased wrappers.

这篇关于迅速普遍存在的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆