Skip to content

Instantly share code, notes, and snippets.

What would you like to do?
/// Conform references types for use in the COW wrapper to this protocol
protocol Cowable: class {
/// Make a new unique instance of `copied`
static func makeUnique(_ copied: Self) -> Self
/// A wrapper that turns a Cowable reference type into a value-semantic
/// type with access to all of its properties
struct COW<Cowed: Cowable> {
private var _cowed: Cowed
init(_ cowing: Cowed) {
_cowed = cowing
public subscript<T>(dynamicMember keyPath: KeyPath<Cowed,T>) -> T {
get { _cowed[keyPath: keyPath] }
public subscript<T>(dynamicMember keyPath: WritableKeyPath<Cowed,T>) -> T {
get { _cowed[keyPath: keyPath] }
set {
if !isKnownUniquelyReferenced(&_cowed) { _cowed = .makeUnique(_cowed) }
_cowed[keyPath: keyPath] = newValue
extension COW: CustomStringConvertible where Cowed: CustomStringConvertible {
var description: String { _cowed.description }
extension Texture: CustomStringConvertible {
var description: String { "Texture(isSparkly: \(isSparkly)" }
final class Texture {
init(isSparkly: Bool) { self.isSparkly = isSparkly }
var isSparkly: Bool
extension Texture: Cowable {
static func makeUnique(_ copied: Texture) -> Texture {
Texture(isSparkly: copied.isSparkly)
struct Material {
public var roughness: Float
public var texture: COW<Texture> = COW(Texture(isSparkly: false))
var m1 = Material(roughness: 0.5)
var m2 = m1
m1.texture.isSparkly = true

This comment has been minimized.

Copy link

commented Jun 7, 2019


private var _cowed: Cowed


private let _cowed: Cowed

since Cowed is constrained to class types (by Cowable restrictions) anyway?


This comment has been minimized.

Copy link

commented Jun 13, 2019

In the talk they used ReferenceWritableKeyPath, but this gist just uses WritableKeyPath. I admit I'm not sure what the practical difference is (the keypath documentation is rather lacking).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.