Home

Awesome

<p align="center"> <img src="logo.png" />

ion language

Ion is a little language that compiles to JavaScript. It doesn't try to be completely different than JavaScript, but it attemps to strip it to the minimal set of functional features of the language, while extending it to have some more. It relies heavily on libraries supporting Fantasy Land, such as Ramda, Santuary and Folktale

One example

The following example is a solution to the "async problem", using the same tools behind the scenes as the task solution.

path = require('path')

read = path.resolve
  | fs.readFile
  | map(toString)
  | map(split('\n'))
  | map(map(fs.readFile))
  | chain(task.waitAll)
  | map(map(toString))
  | map(join(','))
  | map(put)

read('./index.txt').mapRejected(put).run()
Features

Things removed:

Improved type detection

// JS          |   // Ion
typeof null    |   type(null)
// 'object'    |   // 'Null'
typeof []      |   type([])
// 'object'    |   // 'Array'
typeof {}      |   type({})
// 'object'    |   // 'Object'
typeof /a/     |   type(/a/)
// 'object'    |   // 'Regexp'
Improved comparisons
// JS          |   // Ion
1 == "1"       |   1 == "1"
// true        |   // false
NaN == NaN     |   NaN == NaN
// false       |   // true
[] == []       |   [] == []
// false       |   // true
{} == {}       |   {} == {}
// false       |   // true
/a/ == /a/     |   /a/ == /a/
// false       |   // true
All variables are constss
// JS          |   // Ion
const age = 22 | age = 22
let age = 22   | // check "where" below
var age = 22   | // check "where" below
All functions are curried
sayTo = (greet, name) =>
  `${greet}, ${name}!`
sayTo('Hello', 'John') // 'Hello, John!'
sayTo('Hello')('John') // 'Hello, John!'

sayHelloTo = sayTo('Hello')
sayHelloTo('John') // 'Hello, John'
Blocks can have only one expression, and this is returned by default
age = 22
status = if(age >= 18)
  'adult'
else
  'minor'

addFive = (n) => n + 5  
Ramda is treated as the stdlib
map((a) => a + 1, [1, 2, 3]) // => [2, 3, 4]
Operators are seen as functions
map(+(1), [1, 2, 3]) // => [2, 3, 4]
Range type (only for integers so far)
map(+(1), [1..3]) // => [2, 3, 4]
Some new operators:
// `<-` is map

+(1) <- [1..3] // => [2, 3, 4]

// `|` is pipe (sorta like in bash)

add2AndThenMult3 = +(2) | *(3)
add2AndThenMult3(1) // => 9

// `@` gets attribute of object, may be deep

'name' @ {name: 'John'} // => 'John'

['movies', 0, 'name'] @ {movies: [{name: 'Rambo'}, ...]} // => 'Rambo'

dupAllPrices = map(@('price') | *(2))
dupAllPrices([{price: 1}, {price: 2}]) //  => [2, 4]
where construct

Where makes sure variables are local, and they are part of an expression. It's a safe substitute for var/let:

foo = (x) =>
  a + b where
    a = x * 2,
    b = x * 3

Extended types

// Maybe

Maybe.fromNullable(undefined) // Nothing
Maybe.fromNullable('john')    // Just(john)

// Result

Result.Ok(5)
Result.Error('Ooops')

// task (equivalent of Promise)

wait = (secs) =>
  task.task((resolver) =>
    resolver.cleanup(() => clearTimeout(timer)) where
      timer = setTimeout(() => resolver.resolve(secs), secs * 1000))

// gets first task to succeed and automatically cleans up others
task.waitAny([wait(2), wait(1)]).map(put).run()

Usage

ion -h                    // help
ion -c file.ion           // compiles to JS, returns to stdout
ion -c file.ion > file.js // compiles to JS, writes to file.js
ion -e file.ion           // compiles to JS, executes with node (4+ will work)
ion -a file.ion           // returns ion's AST
ion -r 'put("Hello")'     // executes some arbitrary code
ion -t file.ion           // simply tries parsing and return true or error

Credits

ion is inspired by:

Status

Ion is still a toy language and far from 1.0. Beware.