Putting the fun in functional since 2012
16
3
0

akira

Functional language that transpiles to JavaScript.

Installing

with nodejs and npm

npm install akira

git

git clone git://github.com/goatslacker/akira.git
sudo npm link

Usage

ast [file]               - output the Mozilla Parse API for that file
compile [file] [target]  - compile to JavaScript
help                     - dis
output [file]            - compile to JS and output
repl                     - start the repl
run [file]               - compile and interpret said file
tokens [file]            - output the lexer tokens for that file
version                  - akira version

Overview

Literals

String

'i am a string'

Numbers

42
2.0
9,000
-3

Boolean

true
false

Maps

cat = {
  :name 'Luna'
  :age 2
}

Vectors

[1 2 3 4]
[true false]

Regular Expressions

/[A-Z]+/g

Operators

Math

1 + 2
4 - 1
3 * 1
9 / 3

Exponents

akira javascript
3 ** 3 Math.pow(3, 3)

Equality

true == true
false != true
3 > 2
2 < 3
3 >= 3
3 <= 3

Logical

false || true
true && true

Concat and Cons

akira javascript
[1] ++ [2] [1].concat(2)
'hello' ++ 'world' 'hello'.concat('world')
1 +: [2 3] [1].concat(2, 3)

Property Access

akira javascript
{ :key 'value' } !! 'key' { key: 'value' }['key']
{ :key 'value' }.key { key: 'value' }.key
[1 2 3 4] !! 2 [1, 2, 3, 4][2]
[1 2 3].1 [1, 2, 3][0]

Functions

Defining functions

sum = fn [a b]
  a + b

sub = fn [a b]
  a - b

Invoking

sum 1 2

Invoking with no arguments

| 'hello-world'.to-string

IIFE/Beta-redex

| ->
  number-of-balloons = 99

Anonymous functions

fn [x] x * x

Pipes

Functions can also be invoked or chained with pipes

sum 1 2 | print        -- print(sum(1, 2))

Multiple expressions can be piped together

1 | id | print           -- print(id(1))

Previous arguments are carried over into the next function call...

1 | sum 2 | (== 3)   -- sum(2, 1) === 3

...and you can use _ (underscore) to place your argument

2 | sub _ 1 | (== 1)    -- sub(2, 1) === 1

Scope

In akira you may not redeclare a variable, so in reality variables are not really variables, they are symbols; you can also think of them as constants.

a = 1
b = true
c = [1 2 3]
b = false    -- throws a ReferenceError at compile time

So this prevents you from shadowing symbols and misusing scope. You also don't need to include the 'var' as there are no globals.

a = 1        -- outter `a`
b = 2
c = fn []
  a = 2      -- creates a local `a`
  b          -- `b` can be accessed in here

Conditionals

If statements

n = 4
is-n-four = if n == 4
  then true
  else false

Multiple conditions

cond
  n == 4 ? n
  n == 2 ? n + 2
  else ? 0

Pattern Matching

Factorial implemented using pattern matching

fact = match
  [1] 1
  [n] n * (fact n - 1)

This splits up the list into x = head(list) and xs = tail(list)

sort-even-odd = fn [[x, & xs]]
  cond
    not x ? []
    odd x ? (sort-even-odd xs) ++ [x]
    else ? x +: (sort-even-odd xs)

[1 2 3 4 5 6] | sort-even-odd | assert-deep [2 4 6 5 3 1]

Exceptions

try
  | some-function-that-may-crash
catch err
  raise err

Async/Await

For handling async functions there are a few tools you can use

get-file = async [filepath] file = path.join process.env.PWD filepath data = await fs.read-file-async file new File filepath (show data)

do get-file 'README.md' then fn [x] print x catch fn [err] print err

Text Editor Support

ViM: https://github.com/goatslacker/akira.vim

License

MIT

Contributors

goatslacker