Fractalide
"Go with the flow", or should one say "Oxidize in the flow"?
Canonical source
The canonical source of this project is hosted on GitLab, and is the preferred place for contributions, however if you do not wish to use GitLab, feel free to make issues, on the mirror. However pull requests will only be accepted on GitLab, to make it easy to maintain.
Quick start
Fractalide is a programming platform which removes three classes of errors associated with:
Memory Safety
Fractalide components are implemented in Rust, a language which gives the programmer fearless control over speed, concurrency and memory safety.
Dependency Hell
Fractalide uses Nix as a replacement for make. Indeed, it seems Fractalide is the first programming language to exclusively use nix as a package manager. Each component is able to setup it's own OS environment, which might include database drivers written in C, specific versions of an executable or pull in a programming language like python. The package manager is lazily evaluated, thus only those dependencies needed will be compiled. This allows us to have an extremely large repository filled with possibly millions of components.
Code reuse
The use of Flow-based programming gives us the ability to combine and concatenate programs in ways never anticipated. Much like the BASH shell coordinates the execution of GNU utils and other executables in neat, sneaky ways. This is a sign of a high reusability factor. Code is like mud, easy to mold when wet, harder when dry, impossible when baked. FBP gives one the ability to keep one's codebase nicely lubricated.
"Flow-based Programming defines applications as networks of "black box" processes, which exchange data across predefined connections by message passing, where the connections are specified externally to the processes. These black box processes can be reconnected endlessly to form different applications without having to be changed internally. FBP is thus naturally component-oriented." - J Paul Morrison.
flow-based programming reduces complexity of your data-processing logic by promoting control flow to first-class citizen of the flow design
— Arnau Orriols (@Arnau_Orriols) February 2, 2016
Slight mindset shift
The goal is to create reusable components that are efficient, solve real world problems and plug into each other, creating flow. As flow is now a first class citizen, it becomes much easier to manipulate. One should not place too much emphasis on component internals when designing for a flow. One should care about the shape of the data, the capnproto contracts, and how data flows through your system. Of equal importance; one should keep in mind when designing components that your code exists within a community. Pick up your litter, keep the paths clean, Be polite when interacting with other components. Once we as a community have reached this point we will be near our goal.
A contrived example of displaying the output of an XOR gate to the terminal:
'maths_boolean:(boolean=false)' -> a xor(maths_boolean_xor) output -> input disp(maths_boolean_print)
'maths_boolean:(boolean=false)' -> b xor()
Explanation:
-
'maths_boolean:(boolean=false)'
is anIIP (Initial Information Packet)
which tells the virtual machine to use themaths_boolean
capnproto contract which can be found in the contracts/maths/boolean folder. The:(boolean=false)
bit puts the valuefalse
into theboolean
field ofmaths_boolean
-
->
means message pass theIIP
to the inputa
ofxor()
.xor()
is an initialized variable of the typemaths_boolean_xor
which can be found in components/maths/boolean/xor folder. Thereafter you may simply refer toxor()
without themaths_boolean_xor
. -
output
is the output ofxor
which feeds intoinput
ofdisp()
, which is of typemaths_boolean_print
located in components/maths/boolean/print -
IN =>
means you have an input port interface namedIN
. - What's inbetween
IN =>
and=> OUT
is the implementation of the subnet. -
=> OUT
means you have an output port interface namedOUT
. - Do note, you will see ${component_name} this particular syntax is the nix programming language. It will lazily evaluate to the correct path just before compile time.
- For more details, follow the setup steps below which will show you how to compile the docs component. This component will teach you how to build a NOT logic gate.
maths_boolean_xor
{ stdenv, buildFractalideSubnet, upkeepers, maths_boolean_not, ip_clone, maths_boolean_and, maths_boolean_or,...}:
buildFractalideSubnet rec {
src = ./.;
subnet = ''
a => input clone1(${ip_clone})
b => input clone2(${ip_clone})
clone1() clone[2] -> input not1(${maths_boolean_not}) output -> a and2(${maths_boolean_and})
clone2() clone[1] -> input not2(${maths_boolean_not}) output -> b and1(${maths_boolean_and})
clone1() clone[1] -> a and1() output -> a or(${maths_boolean_or})
clone2() clone[2] -> b and2() output -> b or() output => output
'';
meta = with stdenv.lib; {
description = "Subnet: XOR logic gate";
homepage = https://gitlab.com/fractalide/fractalide/tree/master/components/maths/boolean/xor;
license = with licenses; [ mpl20 ];
maintainers = with upkeepers; [ dmichiels sjmackenzie];
};
}
maths_boolean_print
extern crate capnp;
#[macro_use]
extern crate rustfbp;
mod contract_capnp {
include!("maths_boolean.rs");
}
use self::contract_capnp::maths_boolean;
use std::thread;
component! {
Print,
inputs(input: maths_boolean),
inputs_array(),
outputs(output: maths_boolean),
outputs_array(),
option(),
acc(),
fn run(&mut self) -> Result<()> {
let mut ip_a = try!(self.ports.recv("input"));
let a_reader = try!(ip_a.get_reader());
let a_reader: maths_boolean::Reader = try!(a_reader.get_root());
let a = a_reader.get_boolean();
println!("boolean : {:?}", a);
let _ = self.ports.send("output", ip_a);
Ok(())
}
}
From here, you go native.
Setup
Fractalide supports whatever platform Nix runs on, with the exception of Mac OS as Rust on Nix on Darwin doesn't work.
Please read Don't pipe to your shell, then read the script before you execute it. After you are comfortable with it, let's agree that the below one-liner is convenient. If you insist, there is documentation to type this stuff manually.
Run this command as a user other than root (you will need sudo
). To uninstall simply rm -fr /nix
. See this blog post for more detailed information.
$ curl https://nixos.org/nix/install | sh
(ignore if on nixos)
$ source ~/.nix-profile/etc/profile.d/nix.sh
(ignore if on nixos)
Quite possibly your Linux package manager has a Nix package already.
$ git clone https://gitlab.com/fractalide/fractalide.git
$ cd fractalide
$ nix-build --argstr debug true --argstr subnet docs
Congratulations, you just built your first Fractalide executable, now let's run it:
$ ./result/bin/docs
This serves up the Quick Start manual section on http://localhost:8083/docs/manual.html.
This is what the code you just ran looks like.
Happy Hacking!
Collective Code Construction Contract
We use the C4 on this project.