
a context based Javascript eDSL
- [Fluorine](#fluorine)
- [Main Concepts](#main-concepts)
- [Pure and Impure](#pure-impure-concepts)
- [Contexts](#contexts-concepts)
- [Features](#features)
- [Isolating Impure Parts in Javascript Applications](#isolating-impure-parts-in-javascript-applications)
- [Break the Glass in Emergency](#break-the-glass-in-emergency)
- [Flow-Control](#flow-control)
- [Laziness ( well, sort of )](#laziness)
- [Installation](#installation)
- [Dependencies](#dependencies)
- [Recommends](#recommends)
- [How to Use It](#how-to-use-it)
- [Initialize](#initialize)
- [Build a Runnable Program](#build-a-runnable-program)
- [Guides and Common Mistakes](#guides-N-common-mistakes)
- [0. Wrap all computation with side-effects](#wrap-all-computation-with-side-effects)
- [1. Every context chain should be enclosed](#every-context-chain-should-be-enclosed)
- [2. Don't forget the period](#dont-forget-the-period)
- [3. Turn on the debug option](#turn-on-the-debug-option)
- [4. Execute only when it's necessary](#execute-only-when-its-necessary)
- [APIs](#apis)
- [Use with Other DSLs](#use-with-other-dsls)
- [License](#license)
- [Contacts](#contacts)
# Fluorine
[Fluorine](https://github.com/snowmantw/Fluorine) is a Javascript eDSL and library, want to help developers constructing their
application with more functional features, and build large programs from small functions.
It currently has these features:
* [Isolating impure parts in the program.](#isolate-impure-parts-in-javascript-applications)
* [Allow to mix pure/impure when necessary.](#break-the-glass-in-emergency)
* [Flow-Control](#flow-control), to avoid callback hell.
* [Laziness](#laziness) (well, sort of) .
It's first inspired by the [Arrowlets](http://www.cs.umd.edu/projects/PL/arrowlets/api-arrowlets.xhtml) library,
which brought the functional structure, Arrowlet, into Javascript world. Of course, the great [jQuery](http://jquery.com/)
and [Underscore.js](http://underscorejs.org/) also shown how amazing Javascript could be.
Futhurmore, this library also want to experiment the possibility of constructing reasonable Javascript programs
**without (too much) class, object and other OOP things**. Because Javascript, at least according to Douglas Crockford,
["has more in common with functional languages like Lisp or Scheme than with C or Java".](http://www.crockford.com/javascript/javascript.html)
This is a good point in this OOP-overflowed age, especailly most of libraries are all eager to provide class, inheritance and other OOP stuffs.
---
## Main Concepts
### Pure and Impure
Considering we have two string values, they have only one difference:

_Fig.1: Impure values differ from pure values._
String "Foo" comes from some DOM in the document, and the "Bar" is a Javascript string variable spawed from some literal.
The ways to generate them shows the difference between pure and impure value in Fluorine:
**Impure value** means it come from IO, UI and other computations may be failed,
like extract string from a removed DOM, or fetch data from a no longer existing URL.
**Pure value**, on the other hand, should be never failed in it's scope.
The most important concept of Fluorine is that these two kinds of values and computations **should never be mixed arbitrarily**.
This doesn't mean we can live without any impure things, but just want to apply them reasonably.
### Contexts
Fluorine use a structure named **context** to wrap those computations with side-effects.
The name "context" means it's different from other purer and stronger structures like
[Arrowlet](http://www.haskell.org/haskellwiki/Typeclassopedia#Arrow),
[Monad](http://www.haskell.org/haskellwiki/Typeclassopedia#Monad) and
[MonadTransformer](http://www.haskell.org/haskellwiki/Typeclassopedia#Monad_transformers).
These structures are delicate enough but also hard to implement well in this little eDSL (at least, in current stage) .

_Fig.2: All computation with side-effects should be wrapped by contexts._
The _Fig.2_ shows that all computation, include fetching data from server, rendering DOMs in document, and any other comes with side-effects,
should be wrapped by contexts. It also shows the result generated by those computations is wrapped, too. In such a way that we can distinguish
pure values and computations, like applying math functions or creating but not appending DOMs, from those impure parts mentioned earlier.
Contexts in Fluorine are just predefined functions like the "jQuery" function, and the main difference is
that the later don't provide mechanisms to execute lazily, so we can't combine all jQuery chains togeter to build a large program.
Other differences between jQuery and Fluorine's contexts are that jQuery didn't care about side-effects,
and it's combinators mainly provide UI manipulations. These differences don't mean it isn't a great Javascript library,
but only show there're some holes need to be filled. So Fluorine actually depends on `jQuery` and `underscore.js`,
which can easily build important UI and other computations. This library just provide some contexts to orgranize them in proper ways.
Currently, Fluorine has these important contexts:
* **Context**: the basic context, others are inherited from it; extend more new context is possible
* **IO**: fetching data from server, or from local storage (not implement yet)
* **UI**: wrapped jQuery, to seduce it become lazy and greedy (never leaks any impure value)
* **Event**: providing a basically usable event mechanism
* **Socket**: wrapped WebSocket, experimental
See the [APIs](#apis) section to get more information.
---
## Features
### Isolating Impure Parts in Javascript Applications
Fluorine's contexts can help Javascript programmers isolate impure parts in their applications,
so that errors resulted from side-effects can be reduced as much as possible:
// Infect whole context to omit prefix namespaces.
// You can restore this by call `fluorine.heal()`.
fluorine.infect()
// Impure function: manipulate DOMs in the document.
// All impure computing should be wrapped with contexts.
//
// :: String -> UI $DOM
drawMyName = function(name)
{
// $() means apply jquery: `a -> UI $DOM`
return UI('#name-user').$().text(name).done()
}
// Extract string from DOM in document is impure.
//
// :: UI String
getName = function()
{
return UI('#name-user').text().done()
}
// Pure function: return a plain old string.
//
// :: String
giveName = function()
{
return "foobar"
}
The result of `getName` means **"a String under the UI context"**.
On the contrary, function `giveName` will generate **a pure String**.
Because they have different types, users can't arbitrarily mix them like normal strings in Javascript:
ui_name = getName()
name = giveName()
error = ui_name + name
In fact, programmers can only mix them in some proper ways, like in a generator function
returing yet another larger context:
// Generator means this function will return another context wrapped value, rather than a pure value.
//
// :: UI $DOM
drawApp = function()
{
return UI().
let(giveName).as('name'). // Allow to define some local variables in the scope of chain.
tie( function() // Allow to tie with other chains to build a large chain.
{
// Use local variables just like "let" in other languages.
var slc_ex1 = '#ex1'
// Subchain's result will become next step's input.
// In this case, it will return `UI $DOM`, and the next `tie` will receive that.
return UI("").$().appendTo(slc_ex1).done()
}).
tie( function($dom)
{
// Apply the value pre-defined by `let` and `as`.
return drawMyName(this.name)
}).
done() // Don't forget to close this chain.
}
### Break the Glass in Emergency
Basically, pure functions and values can't arbitrarily mix with impure values:
// :: String
pureString = function()
{
return "pure"
}
// :: UI String
impureString = function()
{
return UI("impure").done()
}
illegal_string = pureString() + impureString() // Error.
But in some special cases, we still can do that if we jump into the underlay implementation:
illegal_string = pureString() + impureString()().extract() // extract:: Process String -> String
// The "Process" is a underlay component used to control contexts' flow.
// Every pure value in contexts are actually double-wrapped, by the context and the Process.
//
// impureString() :: UI (Process String)
// impureString()() :: Process String
// extract :: Process String -> String
Also, we can do some dirty works in the theoretically pure combinator, like the `let` or `_`:
UI('#name-user').$().
_(function(e) // Call it "lambda" if you like.
{
// Should keep it pure, not violenting like this:
$(e).text("Name on the document was changed !")
}).
done()
This is useful because sometimes we may want to embed 3rd libraries in our contexts.
Nevertheless, these tricks should be exceptions, not normalities.
### Flow-Control
Fluorine use a hidden and stack based process to manage each step in context chains. The most classical example is the `IO` context:
IO().
get('/ajax/hello').as('hello'). // Delegate to `jQuery.get` .
get('/ajax/world').as('world').
_(function(){ return this.hello + ' ' + this.world }).
tie(function(msg)
{
return UI('').$().text(msg).appendTo('body').done()
})
done()
Here, we get a serialized execution of multiple Ajax requests. The second `get` will not execute unless the first one got successfully executed.
In this way, we can "flatten" nested Ajax callbacks such like:
function requests()
{
var responses = {}
$.get('/one', function(one)
{
responses["one"] = one
$.get('/two', function(two){
responses["two"] = two
$.get('/three', function(three){
responses["three"] = three
$('#io-msg').text(responses["one"]+responses["two"]+responses["three"])
})
})
})
}
Into this:
function requests()
{
return IO().
get('/one').as('one').
get('/two').as('two').
get('/three').as('three').
tie(function()
{
return UI('#io-msg').$().text(this["one"]+this["two"]+this["three"]).done()
}).
done()
}
Of course there're many flow-control libraries promising this, but Fluorine hope this feature can naturally become a part of context-based computing,
not a standalone feature.
Concurrent IOs like initialize multiple requests in the same time is not implemented yet. It will be a important feature in the near future.
### Laziness ( well, sort of )
Context chains in Fluorine will not execute immediately, unless it's required.
// Normal jQuery chain will execute immediately:
act = $('#io-msg').hide().css('background-color', 'cyan').text('New message').fadeIn()
// Fluorine chain: nothing happened.
act = UI('#io-msg').$().hide().css('background-color', 'cyan').text("New message").fadeIn().done()
So we can storage the chain to embed and apply it in anywhere we want
// Can return entire chain because it will not execute in this function.
// :: UI ()
function newMessage()
{
return UI('#io-msg').$().hide().css('background-color', 'cyan').text("New message").fadeIn().done()
}
// When the program initialize, execute it:
newMessage()()
The first application of `newMessage` function is for generating the `UI ()` value:
// :: UI ()
newMessage()
And the next is for extract (execute) pure value from it:
// :: UI () -> ()
newMessage()()
Because the `UI () -> ()` will return nothing, `newMessage()()` will return nothing.
The second `()` is like runner functions in Haskell.
For instance, the `runST:: (forall s. ST s a) -> a` can "execute" a ST Monad.
If anonymous functions annoys you, we also provide `idGen` function.
Using it to put a chain in another chain directly can avoid the annoying anonymous function syntax:
// No need to use anonymous functions anymore.
Event('initialize').
tie(idGen( UI('#io-msg').$().hide().css('background-color', 'cyan').text("New message").fadeIn().done() )).
done()
The "lazyness" and the way we controlling processes are exactly why users should never expect to extract values from IOs:
we can't guarrantee the IO chain will execute and return the value as users wish. In fact, if someone do this:
// Try to extract the result of IO context:
var hello = IO().
get('/ajax/hello').
done()().extract()
// And use it in another context:
UI('#io-msg').$().text(hello).done()()
The `hello` shall be null because the asynchronous `get` still waiting the response.
If values from IO is needed by other contexts, embedding them in the chain is the standard way to satisfy the request:
IO().
get('/ajax/hello').
tie( function( msg )
{
// Instead of try to get the IO handled value outside,
// it's better to embed the receiver context in.
return UI('#io-msg').$().text(msg).done()
}).
done()()
---
## Installation
Clone it from Github, then locate the merged source file in `build/fluorine/fluorine.js`.
git clone https://github.com/snowmantw/Fluorine.git
Or, you can install it via [bower](https://github.com/twitter/bower) :
bower install Fluorine
Lasted tagged version in GitHub:
https://github.com/snowmantw/Fluorine/archive/v0.2.2.zip
### Dependencies
* [jQuery](http://jquery.com) : UI context.
* [Underscore.js](http://underscorejs.org) : use it for your good !
### Recommends
* [bacon.js](https://github.com/raimohanska/bacon.js) : FRP programming.
---
## How to Use It
### Initialize
Normally, use `fluorine.infect()` first, to omit prefix namespace and do some initialization works:
fluorine.infect()
The notifier, designed as a individual part, need initialization too.
fluorine.Notifier.init()
The `infect()` will embed Fluorine utils functions and contexts in `window` object, so you can call them without prefixes:
fluorine.infect()
IO().
get('/ajax/hello').
tie(function(hello)
{
return UI('#io-msg').text(hello).done()
}).
done()()
You can use `fluorine.heal()` to remove the infection.
### Build a Runnable Program
It will generate a Todo list in HTML. This example is also runnable in this page (see below).
In the repo, the example is also in `/demo/todo`.
Run `npm install` in the server directory, and `node ./server.js` to run it.
First we need to prepare our library:
fluorine.infect()
fluorine.debug(true)
fluorine.Notifier.init()
We should define our main function, even though it's not complete yet:
// Parse settings in JSON format.
//
// :: String -> Object
function parseSettings(str)
{
return JSON.parse(str)
}
// Standard main function.
//
// :: IO ()
function main()
{
return IO().
get('/static/todo-settings.json').
let(parseSettings).as('settings').
tie(/*TODO*/). // Do other actions under the settings.
done()
}
Then we need to define some movable parts of our program:
// Generate a frame of this Todo example.
//
// :: UI $DOM
function frame_todo()
{
// Define pure DOM don't violent rules of purity.
var tpl = [ ''].join("")
var frame = $(tpl).get(0)
// This is how event works: forward to global scope then handle it.
// Fluorine's event mechanism hasn't been comprehensively implemented,
// so user can use other libraries like `bacon.js` to get more close to real FRP.
return UI().
tie(idGen(UI(frame).$().appendTo('body').done())).
tie(idGen(UI('#todo-frame').
select('#todo-new').
forward('keypress', function(e)
{
if( 13 == e.which )
{
return 'todo-item-new'
}
else
{ return "_" }
}).
done())
).
done()
}
// When a new todo created, append it.
//
// :: String -> UI $DOM
function new_todo(str_todo)
{
// Generate the new item and append to the list.
var item = $(_.template("