Coder Social home page Coder Social logo

effectfuljs's Introduction

JavaScript embedded effects compiler

This is a JavaScript to JavaScript transpiler. It offers extending JavaScript language with various effects by means of runtime libraries, without even using compiler plugins.

There are such libraries for (not yet supporting the new interface):

Not yet implemented:

  • probabilistic programming
  • parallel and distributed programming
  • persistent continuations
  • adaptive computations

Theare are typically small, some of them are just tiny wrappers of well known interfaces, such as Promises and Rx Observables.

The compiler converts ES8 to ES8 and doesn't need any syntax extensions. So it may be applied to results of other compilers targeting JS such as CoffeeScript, TypeScript, Babel etc.

It stratifies input JavaScript code into two levels, namely object and meta level. Their separation may be either explicit or implicit.

Generators syntax can be used for explicit level separation. This way following code:

function* () {
  console.log("x:",yield getX());
}

will be translated into:

function() {
  return getX().mapply(function (b) { console.log("x:", b); });
}

Or with implicit mode input code may be even more succinct:

function() {
  console.log("x:",getX());
}

The output will be the same.

There are more examples of input/output in the test folder.

The mapply function there is abstract. For example its concrete implementation for promises is their then function. There is a dozen of such functions required to be implemented in concrete effects implementation library. There is a library with default implementations of most of them using small basis. The interface builds on Monads interfaces hierarchy from Haskell (Functor, Applicative, Alternative, Monad).

It is arguable if explicit or implicit levels separation is better. This likely depend on what kind effect is used. The succinct and more readable code is good, but if effects are heavy making them explicit may be better. So effectfuljs compiler supports both options.

I will abuse term pure for some JS code or values. This doesn't mean the code is really pure of course. This is original JavaScript and it is absolutely not a problem to use the side effects already embedded in JavaScript. Including IO, references, exceptions, etc.

Besides two primary explicit and implicit modes, there are means to treat some parts of the code selectively to be either effectful or pure.

Usage

There are a few babel presets for different options, for example @effectful/es for abstract two layer syntax

First install it:

$ npm install --save-dev @effectful/es

Next compile your sources with babel using presets from:

{
  "passPerPreset": true,
  "presets": ["@effectful/es","env"]
}

Here passPerPreset is required because Effectful.js compiler doesn't use babel transformation framework. It is based on @effectful/transducers. You won't typically use it directly unless you develop own effects library.

Known major limitations

  • ES6 supper just replaced with Object.getPrototypeOf(...) and call, this is enough for most applications. If it is not, transpile classes with babel before effectful pass. No plans to fix this for now. No plans to implement.
  • In parameter's threading mode closure captured variables are always handled by reference. Compiler tries to handle only variables by value. All mutating operation like Array::push or object's field setting are still visible in other control threads. Closure capturing variables semantically are nothing but object's field. So they are references now too. But there are short term plans to track even mutating updates soon.
  • setters/getters and constructors cannot be effectful now, may be changed in near future after effectful's object referrences are implemented
  • eval/Function construction from string doesn't work, no plans to implement it.
  • configurations with state handling don't support arguments object aliasing (chainging its element - changes parameter value). This may be implemented in future.

Background

There are quite a few JavaScript transpilers adding some concrete new effects into JavaScript language. This tool embeds abstract side effects into language. Any concrete effect is a runtime library implementing that abstract interface.

One of the examples is recent ES standard updates with generators and async/await. It is a new concrete side effect embedded into language. Adding same coroutines effects with effectful-js doesn't require standard, syntax change and new compilers.

Human readability for generated code aim is shared with kneden transpiler, and turning async/await into promises expressions. The same may be achieved using effectful-js with a tiny adapter from promises interface into effectfuljs. There is one implemented in @effectful/es-inline-rt, so effectfuljs approach does require runtime library loading, while kneden team highlights no runtime library dependency as an advantage. Though from it is easy to remove not used features from Effectful.js runtime. And it may be even inlined into target modules. Also, effectfuljs is more complete than kneden(at the time of writing this). It at least can handle breaks/return/continue from try/catch/finally.

There are other less known JS extensions may be implemented as library using effectfuljs compiler. These are webppl for probabilistic programming, flapjax language for reactive programming.

A few other JS libraries abstract generators interface to any monad, for example burrido. It works pretty well if effects don't require re-executing of some control paths several times. Which is the case for reactive, logical programming and continuations. Here is a problem description for rx monad with burrido and this is the same with effectfuljs.

There are a few other things not possible to implement with libraries such as burrido, for example ApplicativeDo, single layer syntax, persistent control flow.

In other languages the most famous examples of similar tools are Haskell do-notation and C# LINQ. They implement explicit separation of meta and object levels. They have different syntaxes. In JS burrido does the same. The effectful level expressions are generators expressions, with interface adapted to arbitrary monad, while pure code parts use plain JS syntax.

In single level syntax the layers separation is implicit, and both use the same language. The first mention of this I know is embedding monads using delimited control by Andrzej Filinski in Representing monad paper from 1994. There is a more recent implementation of the same idea for Java in quasar framework described in this post. Continuations based implementation doesn't allow detecting and automatically generating Applicative combinators instead of Monadic ones, for more efficient code (more details in Applicative vs Monad interface).

There are also concrete side effects compilers with single level syntax, for example flapjax and webppl.

LICENSE

Copyright © 2016-2017 Vitaliy Akimov

Distributed under the terms of The MIT License (MIT).

effectfuljs's People

Contributors

awto avatar

Watchers

Tom Byrer avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.