### Define and Implement a Protocol Source: https://github.com/zkat/protoduck/blob/latest/README.md This example demonstrates defining a protocol with default implementations, enforcing it in a function, and implementing it for a class. ```javascript const protoduck = require('protoduck') // Quackable is a protocol that defines three methods const Quackable = protoduck.define({ walk: [], talk: [], isADuck: [() => true] // default implementation -- it's optional! }) // `duck` must implement `Quackable` for this function to work. It doesn't // matter what type or class duck is, as long as it implements Quackable. function doStuffToDucks (duck) { if (!duck.isADuck()) { throw new Error('I want a duck!') } else { console.log(duck.walk()) console.log(duck.talk()) } } // ...In a different package: const ducks = require('./ducks') class Duck () {} // Implement the protocol on the Duck class. ducks.Quackable.impl(Duck, { walk () { return "*hobble hobble*" } talk () { return "QUACK QUACK" } }) // main.js ducks.doStuffToDucks(new Duck()) // works! ``` -------------------------------- ### Implement a multi-dispatched protocol Source: https://github.com/zkat/protoduck/blob/latest/README.md Demonstrates defining a protocol with a target type and providing multiple implementations for different types. ```javascript import protoduck from 'protoduck' // Multi-dispatched protocols const Comparable = protoduck.define(['target'], { compare: ['target'], }) class Foo {} class Bar {} class Baz {} Comparable.impl(Foo, [Bar], { compare (bar) { return 'bars are ok' } }) Comparable.impl(Foo, [Baz], { compare (baz) { return 'but bazzes are better' } }) const foo = new Foo() const bar = new Bar() const baz = new Baz() foo.compare(bar) // 'bars are ok' foo.compare(baz) // 'but bazzes are better' ``` -------------------------------- ### Implement a singly-dispatched protocol Source: https://github.com/zkat/protoduck/blob/latest/README.md Demonstrates defining a protocol without types and implementing it for a class Foo. ```javascript import protoduck from 'protoduck' // Singly-dispatched protocols const Show = protoduck.define({ show: [] }) class Foo { constructor (name) { this.name = name } } Show.impl(Foo, { show () { return `[object Foo(${this.name})]` } }) const f = new Foo('alex') f.show() === '[object Foo(alex)]' ``` -------------------------------- ### Implement a Protocol for a Class Source: https://github.com/zkat/protoduck/blob/latest/README.md Use the .impl method to add protocol methods to a class. These methods become available as properties on instances of the class. ```javascript class Dog {} // Implementing `Ducklike` for `Dog`s Ducklike.impl(Dog, [], { walk () { return '*pads on all fours*' } talk () { return 'woof woof. I mean "quack" >_>' } peck (victim) { return 'Can I just bite ' + victim + ' instead?...' } }) ``` -------------------------------- ### Define and Implement Multimethods Source: https://github.com/zkat/protoduck/blob/latest/README.md Multimethods allow dispatching based on multiple arguments. Define matching strings in the protocol definition and provide the specific types during implementation. ```javascript const Playful = protoduck.define(['friend'], {// <---\ playWith: ['friend'] // <------------ these correspond to each other }) class Cat {} class Human {} class Dog {} // The first protocol is for Cat/Human combination Playful.impl(Cat, [Human], { playWith (human) { return '*headbutt* *purr* *cuddle* omg ilu, ' + human.name } }) // And we define it *again* for a different combination Playful.impl(Cat, [Dog], { playWith (dog) { return '*scratches* *hisses* omg i h8 u, ' + dog.name } }) // depending on what you call it with, it runs different methods: const cat = new Cat() const human = new Human() const dog = new Dog() cat.playWith(human) // *headbutt* *purr* *cuddle* omg ilu, Sam cat.playWith(dog) // *scratches* *hisses* omg i h8 u, Pupper ``` -------------------------------- ### Define a Protocol Source: https://github.com/zkat/protoduck/blob/latest/README.md Use protoduck.define to create a protocol definition that specifies the required methods for an object. ```javascript // import the library first! const protoduck = require('protoduck') // `Ducklike` is the name of our protocol. It defines what it means for // something to be "like a duck", as far as our code is concerned. const Ducklike = protoduck.define([], { walk: [], // This says that the protocol requires a "walk" method. talk: [] // and ducks also need to talk peck: [] // and they can even be pretty scary }) ``` -------------------------------- ### Define a protocol with protoduck.define Source: https://github.com/zkat/protoduck/blob/latest/README.md Defines a new protocol named Eq that expects an implementation for the eq function. ```javascript const Eq = protoduck.define(['a'], { eq: ['a'] }) ``` -------------------------------- ### Call Implemented Protocol Methods Source: https://github.com/zkat/protoduck/blob/latest/README.md Once a protocol is implemented for a class, instances can call the defined methods directly. ```javascript const pupper = new Dog() pupper.walk() // *pads on all fours* pupper.talk() // woof woof. I mean "quack" >_> pupper.peck('this string') // Can I just bite this string instead?... ``` -------------------------------- ### proto.impl(target, types, implementations) Source: https://github.com/zkat/protoduck/blob/latest/README.md Adds a new implementation to a defined protocol for specific types. ```APIDOC ## proto.impl(target, types, implementations) ### Description Adds a new implementation to the given protocol across `types`. If the protocol is derivable, the `implementations` object can be omitted. ### Parameters - **target** (Object) - Required - The target class or object to implement the protocol for. - **types** (Array) - Optional - The types to map to method arguments. - **implementations** (Object) - Optional - Functions matching the protocol's API. ### Example ```javascript Show.impl(Foo, { show () { return `[object Foo(${this.name})]` } }) ``` ``` -------------------------------- ### define(types, spec, opts) Source: https://github.com/zkat/protoduck/blob/latest/README.md Defines a new protocol based on specified types and function requirements. ```APIDOC ## define(types, spec, opts) ### Description Defines a new protocol across arguments of types defined by `types`, which will expect implementations for the functions specified in `spec`. ### Parameters - **types** (Array) - Optional - The types to be used in the protocol. - **spec** (Object) - Required - The functions and their associated types that the protocol requires. - **opts** (Object) - Optional - Configuration options including `name`, `where` (constraints), and `metaobject`. ### Example ```javascript const Eq = protoduck.define(['a'], { eq: ['a'] }) ``` ``` -------------------------------- ### Define Protocol Constraints Source: https://github.com/zkat/protoduck/blob/latest/README.md Constraints ensure that any type implementing a protocol also implements required parent protocols. This prevents errors by enforcing dependencies. ```javascript const Show = proto.define({ // This syntax allows default impls without using arrays. toString () { return Object.prototype.toString.call(this) }, toJSON () { return JSON.stringify(this) } }) const Log = proto.define({ log () { console.log(this.toString()) } }, { where: Show() // Also valid: // [Show('this'), Show('a')] // [Show('this', ['a', 'b'])] }) // This fails with an error: must implement Show: Log.impl(MyThing) // So derive Show first... Show.impl(MyThing) // And now it's ok! Log.impl(MyThing) ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.