proposal-first-class-protocols icon indicating copy to clipboard operation
proposal-first-class-protocols copied to clipboard

Optional fields

Open Jamesernator opened this issue 8 years ago • 1 comments

Often it makes sense for a protocol to have optional fields that can be omitted entirely (but considered when they're used) but still included conceptually as part of the protocol.

For example:

protocol Hash {
    hash; // Not optional
    // Hashing might be expensive so objects can report they can be cached
    // if they want
    ?cacheable; // Optional, syntax not important
}

const hashes = new WeakMap()

function hash(value) {
    if (hashes.has(value)) {
        return value
    }

    if (!(value implements Hash)) {
        throw new Error(`Can't hash ${ value }`)
    }

    const hash_ = value[Hash.hash]()
    if (value[Hash.cacheable] && value[Hash.cacheable]()) {
        hashes.set(value, hash_)
    }
    return hash_
}

class HashTable { ... }

class Point implements Hash {
    constructor(x, y) {
        this.x = x
        this.y = y
    }

    [Hash.hash]() {
        return this.x + this.y
    }

    [Hash.cacheable]() {
        return true
    }
}

class Tuple implements Hash {
    constructor(...args) {
        this._tuple = args
    }

    [Hash.hash]() {
        return this._tuple.reduce((acc, hash) => acc + hash, 0)
    }

    // As immutable can cache
    [Hash.cacheable]() {
        return true
    }
}

Array.prototype[Hash.hash] = function() {
    return this.reduce((acc, hash) => acc + hash, 0)
}

// Hash.cacheable needn't be implemented as Array is mutable
Reflect.implement(Array.prototype, Hash)

Obviously this is a trivial example but with more complex protocols this would see better benefit.

For example if Iterator were a protocol:

protocol Iterator {
    'next'; // Not optional
    ?'return'; // Optional
    ?'throw'; // Optional
}

Jamesernator avatar Nov 14 '17 13:11 Jamesernator

It seems like what you're trying to do can be accomplished with subclassing:

protocol Hash {
  // ...
}
protocol CacheableHash extends Hash {
  // ...
}

For a trickier related concept, see the minimal implementations section of the README.

michaelficarra avatar Nov 14 '17 18:11 michaelficarra