Otherwise, I'm stuck creating properties for every type of generic I want to observe. Considering I'm using this for networking and other async source, that would be quite a few, so it's not really scalable without some general support. Ideas?
I think a good part of this restriction came from the fact that it's unclear whether Foo<X>.value and Foo<Y>.value share the same storage. There's actually only one answer that works, but it's still non-obvious enough that we weren't sure if it was a good idea to allow it.
On the implementation side, it's also non-trivial to implement, since new generic types can be created ad infinitum at runtime.
Since globals are already lazily-initialized, I think the only question here is whether there's value in also supporting the truly-unique case â which would have to be semantically restricted to not refer to the type parameters, of course â in addition to the generic case. But I suppose it's pretty clear from precedent elsewhere that static doesn't mean the former, so yeah, it's just a matter of implementation.
It seems to me we could potentially hide the true uniqueness behind the ABI (at least when it isn't exposed as a stored property with @_fixed_layout) and treat it as an optimization. If the property is a let and its initializer independent of the type context, we could collapse it into a unique variable.
I also encountered a use for this recently, but I didnât want to bump the thread. Since itâs already bumped thoughâŚ
While playing around with some numerical things, I wrote a memoized, recursive, O(log(n)) Fibonacci function using the relations:
F2n = (Fn-1 + Fn+1) ¡ Fn
F2n+1 = Fn2 + Fn+12
First I implemented it concretely for Int:
Fibonacci for Int
private var fibonacciCache: [Int: Int] = [0: 0, 1: 1]
func fibonacci(_ x: Int) -> Int {
if let y = fibonacciCache[x] { return y }
precondition(x >= 0)
let h = x/2
let a = fibonacci(h-1)
let b = fibonacci(h)
let c = a+b
let y = x.isEven ? b*(a+c) : b*b + c*c
fibonacciCache[x] = y
return y
}
let x = fibonacci(92)
print(x) // 7540113804746346429
Then I decided to make it generic over BinaryInteger. My first thought was to store the cache as a static property of a generic type:
But of course that doesnât work because static stored properties are not supported in generic types.
I ended up hacking together a really ugly workaround, which to spare everyoneâs sensibilities I will refrain from posting. Letâs just say it involves [ObjectIdentifier: Any] and a lot of casting. :-)
I have encountered this issue recently, I try to implement a type-erased container of one of my protocol that have multiple static properties.
protocol Custom {
static var name: String { get }
var tabBarName: String? { get }
}
struct AnyCustom<Inner : Custom> : Custom {
let value : Inner
static var name: String = Inner.name
var tabBarName: String? { get { self.value.tabBarName } }
init(_ value : Inner) {
self.value = value
}
}
It's not clear from the response above if it will be supported or not. I there a way to go around it ?
Generic type-associated stored properties seems like a useful feature. AA tree algorithms use a sentinel node (a type associated property) to avoid constantly checking for null.