Skip to content
/ mu-ffsm Public

Very tiny helper function to construct fluent JS interfaces

Notifications You must be signed in to change notification settings

wires/mu-ffsm

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

7 Commits
 
 
 
 
 
 

Repository files navigation

µ-ffsm: Micro fluent API helper

Tiny helper function to create fluent interfaces/APIs in a somewhat consistent way.

> npm i mu-ffsm

Quickstart

Use it

var mkChained = require('mu-ffsm');

The idea is that you construct a fluent builder with some initial state of type S by calling an entry function. Then each chained call transitions the state to a new state.

The value you get from chaining a bunch of calls can be executed as a function, which calls exit to construct a value from that state and any options you pass in.

  • entry : * ⟶ S
  • transition : (S ⟶ *) ⟶ S
  • exit : S ⟶ (* ⟶ *)

For example

var API = mkChained({
  0:    function(opt)    {return ;/* create initial state */},
  then: function(s, opt) {return s; /* new state */},
  whut: function(s, opt) {return s; /* new state */},
  1:    function(s, opt) {return ;/* compute final value */}
});

So 0, 1 are entry, exit functions. All other functions transition an internal state. All functions can take arguments, eg. opt

We create an instance of our newly crafted API,

var call = API() // entry
   .whut()       // transition
   .then()       // transition
   .whut();      // transition

And call it

var result0 = call() // exit
  , result1 = call() // exit

Concrete example

Import

var FFSM = require('mu-ffsm');

Create language/machine.

// internal state is an Array
var Talker = FFSM({
	0:    function() { return []; }, // TODO allow const
	talk: function(say, what) { say.push(what); return say; },
	1:    function(say, sep) { return say.join(sep || ' '); }
});

Construct sentences/instances:

var cowboyGreeting = Talker()
	.talk('howdy')
	.talk('cowboy');

// make dramatic
console.log(cowboyGreeting(', ...'));

How the chaining works

What you define

	var M = FFSM({
		0: function(i)    { return /* initial state */; } // entry function
		a: function(s, t) { return /* new state     */; } // transition 'a'
		b: function(s, t) { return /* new state     */; } // transition 'b'
		1: function(s, x) { return /* final value   */; } // exit function
	});

What gets called with which arguments

	var i = M(entry)    // x : S ← M.0(entry)
		.a(trigger_0)   // y : S ← M.a(x, trigger_0)
		.b(trigger_1)   // z : S ← M.b(y, trigger_1)
		.a(trigger_2);  // i : S ← M.a(z, trigger_2)

Finally

	var y = i(x);		// y ← M.1(i, x)

So we have

  • First M(entry) creates a new machine instance of type M. It's initial state derived computed as 0(entry).

  • Then .a(trigger_0) transitions the machine with transition a to a new state, using the previous state and the data from trigger_0 to compute the new state.

  • Similarly .b(t_1), .a(t_2).

  • Finally, the i(x) call constructs an element out of the internal state and the argument using the exit function 1(i,x).

About

Very tiny helper function to construct fluent JS interfaces

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published