Grain



These work just as you'd expect of any reasonable language.


let someNumber = 5
let someString = "A collection of characters"

Lambdas are king (and by that we mean first-class) in Grain. Here we show the function 'add2' being closed over inside the 'add3' function.


# A simple function that adds two numbers
let add2 = (x, y) => x + y
add2(3, 4) # A function that adds three numbers with intermediate steps
let add3 = (x, y, z) => { let firstSum = add2(x, y) let secondSum = add2(firstSum, z) secondSum
}
add3(5, 6, 7)

No functional language is complete without recursion (or in this case, mutual recursion).


let rec isEven = (n) => if (n <=> if (n <=>

Sometimes it's best to work as a pair.

let tup = (4, 2)
let (first, second) = tup
first + second

If that's your kind of thing. Of course, we'd prefer to do everything functionally if possible, but it should still be easy to work this way if necessary.


let variable = box 5
let mutateSomeThings = () => { if (unbox variable > 2) { variable := (unbox variable) - 2 } else { variable := (unbox variable) + 2 }
}
mutateSomeThings()
unbox variable # 3 resides in this box

DOM nodes are primitives in Grain. Traditional DOM queries and node operations are available.


let div1 = DOM.query("#div1")
let div2 = DOM.query("#div2")
let div3 = DOM.query("#div3")
DOM.setText(div1, "I'm just a div.")
DOM.setText(div2, "Sitting here on wasm hill.")
DOM.dangerouslySetInnerHTML(div3, "<i>[[grain]]</i>")

Native Grain functions can be bound as callbacks to native DOM events. This example updates a counter whenever the button is clicked.

let counter = box 0
let button = DOM.query("#button1")
let view = DOM.query("#div1")
let handleEvent = () => { counter := (unbox counter) + 1 DOM.setText(view, toString(unbox counter))
}
DOM.addEventListener(button, "click", handleEvent)