How to rewrite this snippet without `existentials`?


(Adrian Zubarev) #1

Existentials are still missing in the language. Any advice how to rewrite the code so it still would do its job under the hood?

protocol Proto : class {

     // `A` is a generic type and therefore should stay as an associatedtype
     associatedtype A
     func performWith(_ a: A)
}

final class SomeType<B> {

     typealias ProtoB = Any<Proto> where Proto.A == B

     var protos: [ProtoB]

     init(_ protos: [ProtoB]) {
          self.protos = protos
     }
      
     func callProtosWith(_ b: B) {
         
          self.protos.forEach {
            $0.performWith(b)
          }
     }
}
I could make protocol Proto : BaseProto and safe an array of BaseProto but how do I convert it back to Proto when needed, so I could access performWith(_:slight_smile: function?

I cannot use the generic parameter list from SomeType to enforce this, because the class that conforms to Proto might not have the same base class, which is the intended behavior.

···

--
Adrian Zubarev
Sent with Airmail


(Tino) #2

Any advice how to rewrite the code so it still would do its job under the hood?

I'm not aware of any clean way to do this (with current Swift :wink: — but this hack passes compilation:

protocol Proto : class {
  // `A` is a generic type and therefore should stay as an associatedtype
  associatedtype A
  func performWith(_ a: A)
}

struct Box<B> {
  var performWith: (B) -> Void

  init<T: Proto>(value: T) where T.A == B {
    self.performWith = value.performWith
  }
}

final class SomeType<B> {
  var protos: [Box<B>]

  init(_ protos: [Box<B>]) {
    self.protos = protos
  }

  func callProtosWith(_ b: B) {
    self.protos.forEach {
      $0.performWith(b)
    }
  }
}


(Adrian Zubarev) #3

Thanks, that works party as needed but I just realize this main idea here is exactly an example where one would need generic protocols, because I cannot overload the function with associatedtype as I’d need it.

···

--
Adrian Zubarev
Sent with Airmail

Am 2. Dezember 2016 um 13:33:37, Tino Heth (2th@gmx.de) schrieb:

Any advice how to rewrite the code so it still would do its job under the hood?
I'm not aware of any clean way to do this (with current Swift :wink: — but this hack passes compilation:

protocol Proto : class {
// `A` is a generic type and therefore should stay as an associatedtype
associatedtype A
func performWith(_ a: A)
}

struct Box<B> {
var performWith: (B) -> Void

init<T: Proto>(value: T) where T.A == B {
self.performWith = value.performWith
}
}

final class SomeType<B> {
var protos: [Box<B>]

init(_ protos: [Box<B>]) {
self.protos = protos
}

func callProtosWith(_ b: B) {
self.protos.forEach {
$0.performWith(b)
}
}
}


(Tino) #4

Thanks, that works party as needed but I just realize this main idea here is exactly an example where one would need generic protocols

That's right — and I guess they rank quite hight on the general evolution-wishlist :wink:


(Adrian Zubarev) #5

For anyone interested. The correct idea should go into this direction one day:

public class Router<B> {
     
    open protocol Connection<T> : class {
        var router: Router<T> { get set }
        func performWith(_ value: T)
    }
     
    var _connections: [Connection<B>] = []
     
    public typealias Connections = Any<Collection> where Collection.Index == Int, Collection.Iterator.Element == B
     
    // Immutable view without `append` etc.
    public connections: Connections { return self._connections }
     
    public func register(_ connection: Connection<B>) { … }
     
    public func performWith(_ value: B) {
        self._connections.forEach { $0.performWith(value) }
    }
}
The main idea is to link different nodes (class instances) and call a function on the other end with a specific type parameter. Enums with associated types would come really handy here.

···

--
Adrian Zubarev
Sent with Airmail

Am 2. Dezember 2016 um 17:35:25, Tino Heth (2th@gmx.de) schrieb:

Thanks, that works party as needed but I just realize this main idea here is exactly an example where one would need generic protocols
That's right — and I guess they rank quite hight on the general evolution-wishlist :wink: