Occamsrazor.js

A javascript swiss knife

Not a silver bullet

More like a magic bullet

Chapter 1: validators

const duck = {
  swim: true,
  fly: true,
  speak: 'quack!'
};

function isDuck(animal) {
  return animal.swim && animal.fly && animal.speak === 'quack!';
}

isDuck(duck); // true !!!

Duck typing: "If it looks like a duck, swims like a duck, and quacks like a duck, then it probably is a duck."

https://en.wikipedia.org/wiki/Duck_typing

Chapter 1: validators

const validator = require('occamsrazor-validator');

const duck = {
  swim: true,
  fly: true,
  speak: 'quack!'
};

const isDuck = validator()
  .match({ swim: true })
  .match({ fly: true })
  .match({ speak: 'quack!' })

isDuck(duck) !== null; // true !!!

Chapter 1: validators

const validator = require('occamsrazor-validator');

// http://www.answers.com/Q/Do_geese_quack_or_is_it_just_the_ducks?#slide=2

const goose = {
  swim: true,
  fly: true,
  speak: 'honk!' 
};

const isDuck = validator()
  .match({ swim: true })
  .match({ fly: true })
  .match({ speak: 'quack!' })

isDuck(goose) === null; // it is a goose

Chapter 1: validators

const validator = require('occamsrazor-validator');

const isAny = validator();
const doesFly = isAny.match({ fly: true });
const doesFlyAndSwim = doesFly.match({ swim: true });
const isDuck = doesFlyAndSwim.match({ speak: 'quack!' });

doesFlyAndSwim(goose).value(); // 2


doesFly(duck).value(); // 2
isDuck(duck).value();  // 3

isDuck(duck).value() > doesFly(duck).value()

Specificity

Chapter 2: plugins

Open closed principle

https://en.wikipedia.org/wiki/Open/closed_principle

"software entities should be open for extension, but closed for modification"

Chapter 2: plugins

function getMaleNoun(animal) {
  if (isDuck(animal)) {
    obj.maleName = 'drake';
  } else if isGoose(animal) {
    obj.maleName = 'gander';
  } else if {
    ... // you have to keep changing here
  }
}

Chapter 2: plugins

const occamsrazor = require('occamsrazor');

const getMaleNoun = occamsrazor();

getMaleNoun.add(isDuck, (animal) => { animal.maleName = 'drake' });
getMaleNoun.add(isGoose, (animal) => { animal.maleName = 'gander' });

getMaleNoun(duck);

Chapter 3: adapters

https://en.wikipedia.org/wiki/Adapter_pattern

"...allows the interface of an existing class to be used as another interface"

Chapter 3: adapters

const or = require('occamsrazor');

const egg = or();

egg.add(isDuck, (animal) => ({
  owner: animal,
  eat: 'yum a duck egg'
}));

egg.add(isGoose, (animal) => ({
  owner: animal,
  eat: 'yuck a goose egg'
}));

get a "duck/goose" object and return an "egg" object

Chapter 3: adapters

const or = require('occamsrazor');

const nursing = or();

nursing.add(isDuck, isEgg, (animal, egg) => ({  
  // use your imagination here
}));

nursing.add(isGoose, isEgg, (animal, egg) => ({
  // use your imagination here
}));

multiadapter: adapting more than one object

const or = require('occamsrazor');

const registry = or();

registry.add(isDuck, (animal) => {
  return 'I see a duck';
});

registry.add(doesFly, (animal) => {
  return 'Look! It flies';
});

registry(duck);
// it is returning "I see a duck" (the most specific)

registry.all(duck);
// it is returning ["I see a duck", "Look! It flies"]
// sorted by specificity

Chapter 3: adapters

Returning multiple matches

Chapter 4: observer

const or = require('occamsrazor');

const observable = or();

observable.add(isDuck, (obj) => {
  console.log('it is a duck');
});

observable.add(isDuck, (obj) => {
  console.log('Look! it flies');
});

observable.all(obj); // it is executing all matching functions

https://en.wikipedia.org/wiki/Observer_pattern

Just like the previous example but functions don't return

Chapter 4: observer

const or = require('occamsrazor');

const observable = or();

observable.on(isDuck, (obj) => {
  console.log('it is a duck');
});

observable.on(isDuck, (obj) => {
  console.log('it is a goose');
});

observable.trigger(obj);

add and on are equivalent

all is synchronous while trigger defers to the next tick

Chapter 4: observer

const or = require('occamsrazor');

const observable = or();

observable.on(isDuck, (obj) => {
  console.log('it is a duck');
});

observable.trigger(duck);

// this is attached too late
observable.on(isDuck, (obj) => {
  console.log('it is another duck');
});

stick

Chapter 4: observer

const or = require('occamsrazor');

const observable = or();

observable.on(isDuck, (obj) => {
  console.log('it is a duck');
});

observable.stick(duck);

// this is executed anyway
observable.on(isDuck, (obj) => {
  console.log('it is another duck');
});

stick

Many other features!

read the doc!

Thanks

Occamsrazor.js

By Maurizio Lupo

Occamsrazor.js

A javascript swiss knife

  • 485