Skip to content

Instantly share code, notes, and snippets.

@nickfargo
Last active September 4, 2015 22:54
Show Gist options
  • Save nickfargo/52b344056bbd2531b699 to your computer and use it in GitHub Desktop.
Save nickfargo/52b344056bbd2531b699 to your computer and use it in GitHub Desktop.
Delegation protocol for Channel to be proxied by arbitrary objects
class Channel

Channel.delegate

Implement the channel I/O protocol on a target object, by furnishing it with methods that delegate both to a backing entity referenced by property target[inName] for its input aspects, and to one referenced by target[outName] for its output aspects. If only one property name is provided, then both input and output are delegated to the same backing entity.

  @delegate = (target, inName, outName) =>
    @delegate.input target, inName
    @delegate.output target, outName ? inName

  @delegate.input = ->
    delegate arguments..., "in canProcessReceive isClosed enqueue"

  @delegate.output = ->
    delegate arguments..., "out canProcessSend isDone dequeue"

  delegate = (target, instancePropertyName, methodNames) ->

    createMethod = (methodName) =>
      target[methodName] = ->
        @[instancePropertyName][methodName] arguments...

    if typeof methodNames is 'string'
      methodNames = methodNames.split /\s+/

    createMethod name for name in methodNames
    target

One typical use case of Channel.delegate would be for defining a class as a proxy for channel I/O. The mixins added to the constructor’s prototype allow an instance to act as an indirection to the referenced channel, such that a communicating process’s channel operations (receive/send) may treat the instance as if it were a proper channel:

        class Foo {
          constructor () {
            this._process = proc(function* () {
              yield send(42);
              // ...
            });
          }
        }
        Channel.delegate( Foo.prototype, '_process' );
        // Recall that a Process already delegates to its I/O channels.
    
        // Instances of `Foo` can be used like a channel.
        let foo = new Foo;
        proc(function* () {
          let value;
          value = yield receive(foo); // >>> 42
        });

Should this be called proxy instead of delegate?

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