@straits/utils

Utility library for straits

Usage no npm install needed!

<script type="module">
  import straitsUtils from 'https://cdn.skypack.dev/@straits/utils';
</script>

README

@straits/utils npm (scoped) NpmLicense David Travis (.com) Coveralls github

Utilities to declare and use traits and trait sets.

Installation

npm install --save @straits/utils

Quickstart

const {TraitSet} = require('@straits/utils');

const traits = TraitSet.fromKeys({
    a: {},
    b: {}
});

const sym = traits.a;

{
    // implementing `sym` for all objects
    use traits * from TraitSet;
    sym.*impl( Object.prototype, 42 );
}

{
    // using `sym`
    use traits * from traits;
    console.log( ({}).*a ); // 42
}

API

TraitSet.fromKeys( obj ) => TraitSet

Create and return a new TraitSet, with a new symbol for each property of obj.

TraitSet.fromStrings( names ) => TraitSet

Create and return a new TraitSet, witha symbol for each string in names.

new TraitSet( traitSet={} ) => TraitSet

Create a new TraitSet, borrowing symbols from TraitSet.

traitSet.asFreeFunctions() => { str:fn(), ... }

Return an object with a free function wrapping each symbol in traitSet.

symbol.*impl( target, value ) => symbol

Set target[symbol] to value. Such property symbol is not enumerable nor writable.

const obj = {};
Symbol.iterator.*impl( obj, ()=>{/*...*/} );

symbol.*implDefault( value ) => symbol

Set value as the default value for symbol. Free functions wrapping traits will call value(obj, ...args) if they're called on an obj that doesn't have a symbol property.

symbol.*asFreeFunction() => fn()

Return a free function wrapping symbol.

const fn = Symbol.iterator.*asFreeFunction();

const arr = [];
// the following two statements will be equivalent
fn( arr, 1, 2, 3 );
arr[ Symbol.iterator ]( 1, 2, 3 );

obj.*addSymbol( name, sym ) => sym

Add sym to this with key name: obj[name] = symbol. Throw if sym is not a symbol or if obj already has a property name.

obj.*defineTrait( name ) => symbol

Add a new symbol called name to obj: obj[name] = Symbol(). Throw it obj already has a property called name.

obj.*borrowTraits( traitSet, names=undefined ) => obj

Add to obj all the symbols from traitSet whose property is listed in names. If names is not set, all the symbols from traitSet are imported into obj.

obj.*traitsToFreeFunctions() => obj

Return an object with a free function wrapping each symbol in traitSet.

obj.*implTraits( target, implementationObj ) => obj

implementationObj should be an object whose keys are names of symbols in obj. For each key, value entry of implementationObj, set target[ this[key] ] to value.

obj.*defineAndImplTraits( target, implementationObj ) => obj

Like obj.*implTraits( target, implementationObj ), but it defines the symbols (obj.*defineTrait) before using them.

obj.*defineAndImplMethodsAsTraits( target, source, methodList ) => obj

methodList should be a list of properties in source whose value is a method. Create a new symbol sym in obj for each key m of methodList, and set target[sym] to a function wrapping source.m().

obj.*defineAndImplMemberFreeFunctionsAsTraits( target, functionObj ) => obj

functionObj should be an object whose values are free functions. For each key, fn entry in methodList, create a new symbol sym in obj, and set target[sym] to a function wrapping fn().