Skip to content

Latest commit

 

History

History
115 lines (92 loc) · 2.85 KB

oi.md

File metadata and controls

115 lines (92 loc) · 2.85 KB

OI

OI is a helper for passing multiple values through a promise/event chain.

Quick. How do I use it?

.oi (i, o) ->
    ...
.oi ({a1, a2}, o) ->    # 1. destructure what you need from i
    o.a3 = ...          # 2. assign new promises to o.[name]
.oi ({a1, a3}, o) ->    # 3. use resolved new values and old ones
    ...
  1. i is the input from the previous step which we typically use with destructuring assignment.
  2. o is an empty object to which we can assign new promises/values.
  3. the return can be a promise, however the value is ignored.
  4. the result of the step is mixin i, o. values in o can overwrite same names in i.

Why OI?

When I discovered promises I often found myself saving values in scoped variables.

doSomething = ->
    something = null   # NO!
    another = null     # NOOOO!
    Q().then ->
        someFileOperation()
    .then (_something) ->
        something = _something    # YUCK!
        someDbThing(something.blah)
    .then (_another) ->
        another = _another        # MORE YUCK!
    .then ->
        doStuff(something, another)
    .then ->
        close(something)
    .then ->
        move(another);

Those scope variables really bothers me. And are outright wrong for XQ style event chains where they would overwrite each other.

With XQ I made X.all() work for objects as well as arrays, this opened up for a new style.

Coffeescript destructuring to the rescue!

doSomething = ->
    X().then ->
        someFileOperation()
    .then (something) ->
        another = someDbThing(something.blah)
        {something, another}
    .all ({something, another}) ->            # Sweet!
        doStuff(something, another).then ->
            {something, another}
    .then ({something, another}) ->
     ...

However it's still a bit much to write when every step must explicitly end with what args are passed to the next, which in turn starts by just deconstructing the same args.

    {something, another}
.all ({something, another}) ->

So one morning in yoga practice (ok, bad focus, I know), it came to me.

OI [choir music]

doSomething = ->
    X().oi (o) ->
        o.something = someFileOperation()
    .oi ({something}, o) ->
        o.another = someDbThing(something.blah)
    .oi ({something, another}, o) ->
        doStuff(something, another)
    .oi ({something}, o) ->
        close(something)
    .oi ({another}, o) ->
        move(another)

One can think of .oi as a curried function with the following signature

oi(f)(i) :: ((i, o) -> *) -> i -> o

An implemetation using fnuc is:

oi = curry (i, f) ->    # fnuc does reverse curry
    o = {}
    r = if f.length == 1 then f(o) else f(i, o)
    X(r).then -> X.all(mixin i, o)

This could be used with X.all()

.all oi (o, {a1}) ->

However I made an implementation straight in XQ.