noders 0.0.2

NodeJS-like event loop environment for Rust
Documentation
# node.rs

A nodejs-like framework for Rust.

The biggest thing that makes nodejs pleasent to program in is the API. Even the most ardent Javascript
fan will agree that Js has a certain amount of [wat](https://www.destroyallsoftware.com/talks/wat)
inducing design decisions, but what's important about javascript, and especially nodejs, is that
the code written in it usually Just Works. There isn't a complex type system (or any type system) to
impede quick development and the APIs strike a good balance between making it *easy* to do what people
typically want to do, and avoiding "magic" commands, which are difficult to understand and reason
about, or worse, which the API designed expects the consumer to invoke blindly.


## Why API matters

Here's an example of why API matters so much. This is a little program which reads out a file and
replaces all instances of the word "cloud" (case insensitive) with the word "butt". Our first example
showcases all the terrible API of the Java standard library:

```java
import java.util.regex.Pattern;
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;

public class ApiMatters
{
    static final Pattern REGEX = Pattern.compile("cloud", Pattern.CASE_INSENSITIVE);
    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new FileReader("file.txt"));
        try {
            String line = br.readLine();
            while (line != null) {
                System.out.println(REGEX.matcher(line).replaceAll("butt"));
                line = br.readLine();
            }
        } finally {
            br.close();
        }
    }
}
```

Java really wants you to know *how* things are happening, every little detail is necessary, you need
to know that you're reading a File, with a FileReader, and in case you might not want to cause a syscall
every time you read, well you need a BufferedReader. And doing regex replacement requires that you create
a Pattern object, which you should put as a static field in the class of your Object, you are making an
Object, right ?

At the other extreme you have magic, the best example I can think of is in the old Bitcoin codebase, when
the data structures are to be read or written to/from the disk or network, they need to be converted into
a serialized form. Satoshi's lovely solution for this is one magic macro:
[IMPLEMENT_SERIALIZE](https://github.com/bitcoin/bitcoin/blob/v0.8.6/src/protocol.h#L42) which expands to
about [1000 lines of nested C++ macro code](https://github.com/bitcoin/bitcoin/blob/v0.8.6/src/serialize.h).
Satoshi to his credit only used this monstrosity for his own code. The real offense is exporting these
[magical constructs as API](https://blogs.msdn.microsoft.com/oldnewthing/20050106-00/?p=36783/).

Magic APIs writers don't try to explain what's happening, instead they write documentation which amounts
to "just call it, don't ask too many questions, it will work". But if ever it doesn't work, you're gonna
be in a world of pain trying to understand what that thousand lines of meta-meta-meta-polymorphic
programming actually does. The fundimental problem with magical APIs is they lack a solid metaphore, you
really don't know if switching on the lights might cause the toilet to flush, and if it does, whether that
is a bug, or some Rube Goldberg "feature" to save the mad scientist API author.

Nodejs is pleasent to work with because the API creators  took the middle road. Javascript doesn't
(as of 2018) have powerful macros so creating magical APIs is not easy, and the creators of nodejs made
a solid effort to avoid
[global flags](https://softwareengineering.stackexchange.com/questions/173086/are-flag-variables-an-absolute-evil)
and
[side effects](http://codebetter.com/matthewpodwysocki/2008/04/30/side-effecting-functions-are-code-smells/)
in their API design, while still hiding most of the things which the typical programmer is not likely to
care about.

Take this snippet as example:

```js
const Fs = require('fs');
Fs.readFile('./file.txt', 'utf8', (err, data) => {
    if (err) { throw err; }
    data.split('\n').forEach((l) => {
        console.log(l.replace(/cloud/i, 'butt'));
    })
});
```

Like the big Java example, it also reads the file, replaces cloud with butt and writes out the result.
Unlike the big Java example, it doesn't require the programmer to know about buffer, regular expression
compiling or any of the many types of errors which can occur throughout the process. A fair criticism of
nodejs is that it is not easy to verify that all exceptional cases have been handled, but when you're
trying to get a project off the ground, handling all exceptional cases is the least of your concerns.

## What is Rust

Rust is a compiled language, so
like C/C++ it can make small fast standalone binaries. Rust is also a memory safe language, so like
Javascript, it cannot segfault[*](https://doc.rust-lang.org/nomicon/meet-safe-and-unsafe.html). Rust's
type system is a state of the art system,
[comparable to that of a function language like haskell](https://sdleffler.github.io/RustTypeSystemTuringComplete/)
but Rust itself is procedural, often resembling C++. In some ways, you could imagine Rust as two
languages, the procedural language which you use to write the code and the functional language which
you use to convince the type system that your code is safe.

## Introducing node.rs

Node.rs is an attempt at bringing the good stuff from Nodejs to Rust. It is built on top of
[MIO](https://github.com/carllerche/mio) and contains an embedded event loop and callback functionality.

### Simple example

The most simple example is a `setTimeout()`, unlike nodejs, you need to launch the event loop explicitly,
you do that with the module builder. After building the module, you are called with a [Scope](#scope).
The Scope provides you access to the underlying event loop and is the first argument which is passed to
every callback that is called. We'll get to the module builder later on, but for now you can just wrap
your program with `module().run((), |s| {` ..... `});`.

```rust
extern crate noders;
fn main() {
    noders::module().run((), |s| {
        noders::time::set_timeout(s, |s, _| {
            println!("Hello1");
        }, 100);
    });
}
```

### The Scope

In Javascript and other Scheme-like languages, nested scopes can access and modify variables of
parent scopes like this:

```js
let sum = 0;
[1,2,3,4,5].forEach((i) => {
    sum += i
});
console.log(sum);
```

This example is rather simple because everything happens synchronously. The number `sum` is gone
by the time the code snippet completes.

However, in this example:
```js
let x = 0;
setTimeout(() => { x++; }, 100);
setTimeout(() => { console.log(x); }, 200);
```

The number, `x` needs to continue to exist after the function where it was declared returns.
Javascript achieves this by means of single-threaded execution and garbage collection, because two
closures have been registered to the `setTimeout` function and those two closures hold a reference
to `x`, Javascript will keep the memory location for `x` in memory until they are complete.

Because Rust has no garbage collector, every object in memory must have a unique *owner*,
furthermore, in order to avoid [pointer aliasing](https://en.wikipedia.org/wiki/Pointer_aliasing)
issues, the Rust language rules specify that if there is a mutable pointer to an object, there
cannot be any other pointer to the same object at the same time.

So in Rust, the first example works:

```rust
fn main() {
    let mut sum = 0;
    vec![1,2,3,4,5].iter().for_each(|i|{
        sum += i
    });
    println!("{}", sum);
}
```

But the second example fails, because `i` is *owned* by the main function, and so it is de-allocated
when the main function completes.

```rust
// error[E0597]: `i` does not live long enough
fn main() {
    let fake_event_loop = || {
        let mut i = 0;
        return (
            || { i += 1; },
            || { println!("{}", i); }
        );
    };
    let mut callbacks = fake_event_loop();
    (callbacks.0)();
    (callbacks.1)();
}
```
[Try it out in the Rust Playground](https://play.rust-lang.org/?gist=f49f4eadcf16b568c53f5b1ce12f7fd9&version=stable&mode=debug&edition=2015)

#### How the Scope works

When you created a module with `module().run((), |s| {` ..... `});`, you might have noticed that
the first argument to `run()` is `()`, the [unit](https://doc.rust-lang.org/std/primitive.unit.html)
(similar to `null` in other programming languages). When you invoke `run()`, you can pass in any
object and this object will be *wrapped* to create a scope, so with the following pattern, you can
get a working scope:

```rust
extern crate noders;

struct Context {
    integer: i32,
    hi: &'static str,
    number: f32
}

fn main() {
    let ctx = Context {
        integer: 1,
        hi: &"Hello world",
        number: 3.5
    };

    noders::module().run(ctx, |s| {
        noders::time::set_timeout(s, |s,_| {
            println!("{} {}", s.hi, s.number);
            s.integer += 1;
        }, 100);
        noders::time::set_timeout(s, |s,_| {
            println!("{}", s.integer);
        }, 200);
    });
}
```

However, note that the scope wrapper adds the following functions `cb()`, `as_rc()`, and `core()`.
So if you pass in an object with a `core()` method (for example), calling the `core()` method will
not do what you expect.

### The rec!{} macro

Since using noders can lead to creating lots of temporary scope objects, the `rec!{}` macro exists
to help you create quick anonymous objects. Because Rust has strong type inferrence, you can often
just pass the value and Rust will detect the type. So this:

```rust
extern crate noders;
struct Context {
    integer: i32,
    hi: &'static str,
    number: f32
}
fn main() {
    noders::module().run(Context {
        integer: 1,
        hi: &"Hello world",
        number: 3.5
    }, |s| {
        noders::time::set_timeout(s, |s,_| {
            println!("{} {}", s.hi, s.number);
            s.integer += 1;
        }, 100);
        noders::time::set_timeout(s, |s,_| {
            println!("{}", s.integer);
        }, 200);
    });
}
```

Can be simplified to this:

```rust
#[macro_use(rec)] extern crate noders;
fn main() {
    noders::module().run(rec!{
        integer: 1,
        hi: &"Hello world",
        number: 3.5
    }, |s| {
        noders::time::set_timeout(s, |s,_| {
            println!("{} {}", s.hi, s.number);
            s.integer += 1;
        }, 100);
        noders::time::set_timeout(s, |s,_| {
            println!("{}", s.integer);
        }, 200);
    });
}
```

Internally, what `rec!{}` does is examine entries which you create and craft some code like
the following:

```rust
{
    struct Rec<A,B,C> { integer: A hi: B, number: C }
    Rec { integer: 1, hi: &"Hello world", number: 3.5 }
}
```

And Rust's strong type inferrence system is able to determine what the types of the objects
are. **CAUTION**: If you create a `rec!{}` with ambiguous values (for example None), Rust may
not be able to detect the type and you may have to use an explicit structure.

Throughout this document, we will use the `rec!{}` macro to simplify examples.

### The time module

The heart of any event based system is the means to *schedule* a callback to trigger at some point
in the future. The `set_timeout()`, `set_interval()`, `clear_timeout()` and `clear_interval()`
functions are part of the time module. Like their Javascript cousins, the `set_timeout()` and
`set_interval()` functions return a Token which can be used with `clear_timeout()` or
`clear_interval()` to cancel the timeout or interval.

```rust
extern crate noders;
use noders::time;
fn main() {
    let x = 3;
    noders::module().run(rec!{
        to: noders::Token(0)
    }, |s| {
        s.to = time::set_timeout(s, |_,_| {
            println!("This should never happen");
        }, 100);
        time::set_timeout(s, |_,_| {
            time::clear_timeout(s, s.to);
        }, 50);
    });
}
```


### The rec!{} macro




### Making SubScopes