Skip to content

Instantly share code, notes, and snippets.

@GeekAndDad
Last active July 24, 2020 03:49
Show Gist options
  • Save GeekAndDad/967972d329b354b7fa5fe241895c596d to your computer and use it in GitHub Desktop.
Save GeekAndDad/967972d329b354b7fa5fe241895c596d to your computer and use it in GitHub Desktop.
Computed properties don't call specialized version of functions? Work fine when you call the specialized functions directly but not when those functions are used within a getter or setter it seems… ???
// macOS playground source
// swift 5.3, Xcode 12b2
import Cocoa
struct Foo<A> {
var subVal: Any?
let defaultValue: A
init(defaultValue: A) {
self.defaultValue = defaultValue
}
var value: A {
get {
return map(value: subVal) ?? defaultValue
}
set {
subVal = map(value: newValue)
print("subVal: \(String(describing: subVal))")
}
}
func map(value: A) -> Any? {
print("map A -> Any?")
return value
}
func map(value: Any?) -> A? {
print("map Any? -> A")
return value as? A
}
}
// make a specialization for Strings identical to the above
// except change the print to use "EXT" instead of "map"
// so we can see when the internal generic one is called
// and when the restricted one is called
extension Foo where A == String {
func map(value: A) -> Any? {
print("EXT A->Any?")
return value
}
func map(value: Any?) -> A? {
print("EXT Any?->A")
return value as? A
}
}
print("\nUse an Foo<Int> so the specialization shouldn't get involved either directly or via the computed property\n")
var f = Foo(defaultValue: 42)
print("via computed property:\n")
print(f.value)
f.value = 43
print(f.value)
print("\ncalling functions directly")
print(String(describing: f.map(value: 43)))
print(String(describing: f.map(value: "hello")), "(nil expected)") // should print nil because we are a Foo<Int>
print("\n\n*** Now use Foo<String> so the specializations should be involved calling directly OR via computed property\n")
var g = Foo(defaultValue: "hello world")
print("via computed property: \n")
print("> should see 'EXT' instead of 'map' in next print but won't 0")
print(g.value)
print("\n> should see 'EXT' instead of 'map' in next print but won't 1")
g.value = "zip!"
print("\n> should see 'EXT' instead of 'map' in next print but won't 2")
print(g.value)
print("\n> WILL see expected 'EXT' instead of 'map' in next two prints which call `map` directly\n")
print(String(describing: g.map(value: "hello")))
print(String(describing: g.map(value: 42)), "(nil expected)") // should be nil as we are a Foo<String>
hello?
Use an Foo<Int> so the specialization shouldn't get involved either directly or via the computed property
via computed property:
map Any? -> A
42
map A -> Any?
subVal: Optional(43)
map Any? -> A
43
calling functions directly
map A -> Any?
Optional(43)
map Any? -> A
nil (nil expected)
*** Now use Foo<String> so the specializations should be involved calling directly OR via computed property
via computed property:
> should see 'EXT' instead of 'map' in next print but won't 0
map Any? -> A
hello world
> should see 'EXT' instead of 'map' in next print but won't 1
map A -> Any?
subVal: Optional("zip!")
> should see 'EXT' instead of 'map' in next print but won't 2
map Any? -> A
zip!
> WILL see expected 'EXT' instead of 'map' in next two prints which call `map` directly
EXT A->Any?
Optional("hello")
EXT Any?->A
nil (nil expected)
@GeekAndDad
Copy link
Author

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment