Last active
December 3, 2015 03:09
-
-
Save wavebeem/dcea6b70f0cee32fcc1b to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
### Imports | |
let {JSON, document, console} = global | |
### Basic data | |
let namedConstants = [true, false, null, undefined] | |
let numbers = [1, 2, 1_000, 3.14, NaN, -Infinity] | |
let strings = ["hello,\n", "\u{20}", "\"world\"\u{2757}"] | |
let arrays = [[], [1, 2], [3, [[4]], [5]]] | |
let objects = [ | |
{}, | |
{a: "b"}, | |
{key: 400, "first name": "Fatima"}, | |
{("a" ++ "b"): "ab"} | |
] | |
### Trivial functions | |
let alwaysFourA = func() | |
4 | |
end | |
let incrementA = func(x) | |
x + 1 | |
end | |
def alwaysFourB() | |
4 | |
end | |
def incrementB(x) | |
x + 1 | |
end | |
def curriedAddThree(a) | |
fn(b) fn(c) a + b + c | |
end | |
### First multi-line example | |
def addStringsAsNumbers(x, y) | |
let x = Number(x) | |
let y = Number(y) | |
x + y | |
end | |
### Named this example | |
def methodShowXLater(@this) | |
setTimeout(fn() console.log(this.x), 300) | |
end | |
### Variadic function | |
def max(...xs) | |
Math.max.apply(null, xs) | |
end | |
### Basic recursive function, obligatory factorial | |
def factorialA(n) | |
if n < 0 then | |
error "cannot factorial of " ++ n.toString() | |
else if n == 0 or n == 1 then | |
1 | |
else | |
n * factorialA(n - 1) | |
end | |
end | |
def factorialB(n) | |
match n | |
case 0 then 1 | |
case n then n * factorialB(n - 1) | |
end | |
end | |
### Working with a custom data type using just functions | |
def makePointA(x, y) | |
{x, y} | |
end | |
def pointAdd(a, b) | |
let {x: ax, y: ay} = a | |
let {x: bx, y: by} = b | |
makePointA(ax + bx, ay + by) | |
end | |
### Working with a custom data type using prototypes and methods | |
let pointProto = { | |
add: fn(@this, that) = | |
makePointB(this.x + that.x, this.y + that.y), | |
scale: fn(@this, n) do | |
console.log("DEBUG: scaling by", n) | |
makePointB(this.x * n, this.y * n) | |
end | |
} | |
def makePointB(x, y) | |
# This will be frozen and have the right prototype thanks to the `~` op | |
Object.create(pointProto) ~ {x, y} | |
end | |
### Working with updating objects | |
def updateNameA(person, name) | |
if not person has "name" then | |
error "person didn't alreay have a name field" | |
else | |
person ~ {name} | |
end | |
end | |
def updateNameB(person, name) | |
match person | |
case {name: _} then | |
person ~ {name} | |
end | |
end | |
### Pattern match heavy algorithms | |
def sort(items) | |
match items | |
case [] then [] | |
case [x, ...xs] then | |
let lt = xs.filter(fn(y, _, _) y < x) | |
let gt = xs.filter(fn(y, _, _) y >= x) | |
sort(lt) ++ [x] ++ sort(gt) | |
end | |
end | |
def map(f, xs) | |
match xs | |
case [] then [] | |
case [x, ...xs] then [f(x)] ++ map(f, xs) | |
end | |
end | |
### Sneaky log stuff | |
def sneakyLogA(x) | |
console.log(x) | |
x | |
end | |
def tap(f, x) | |
f(x) | |
x | |
end | |
def sneakyLogB(x) | |
tap(console::log, x) | |
end | |
### Lots of cases | |
def numberToEnglishA(n) | |
if n == 1 then "one" | |
else if n == 2 then "two" | |
else if n == 3 then "three" | |
else if n == 4 then "four" | |
else "some other number" | |
end | |
end | |
def numberToEnglishB(n) | |
match n | |
case 1 then "one" | |
case 2 then "two" | |
case 3 then "three" | |
case 4 then "four" | |
case _ then "some other number" | |
end | |
end | |
### Try example | |
def safeParse(text) | |
match try JSON.parse(text) | |
case ["ok", obj] then obj | |
case ["fail", _] then {} | |
end | |
end | |
### Await example | |
def saveProfilePic(userId) | |
await profile = httpGet("/user/" ++ userId) | |
await image = httpGet(profile.imageUrl) | |
await _ = writeFile(profile.userName ++ ".jpg", image.data) | |
console.log("Saved image for " ++ profile.userName) | |
end | |
### Node.js HTTP server example | |
let http = require "http" | |
let port = 1337 | |
let host = "127.0.0.1" | |
let url = "http://" ++ host ++ ":" ++ port.toString() ++ "/" | |
def handler(res, res) | |
let headers = {"Content-Type": "text/plain"} | |
res.writeHead(200, headers) | |
res.end("Hello world\n") | |
end | |
def start() | |
http.createServer(handler).listen(port, host) | |
end | |
console.log("Server running at " ++ url) | |
### Example app from http://mithril.js.org/ | |
let Page = { | |
list: func() | |
m.request({method: "GET", url: "pages.json"}) | |
end | |
} | |
let Demo = { | |
controller: func() | |
{ | |
pages: Page.list(), | |
rotate: func() | |
pages().push(pages().shift()) | |
end | |
} | |
end, | |
view: func(ctrl) | |
m("div", [ | |
ctrl.pages().map(fn(page, _, _) | |
m("a", {href: page.url}, page.title) | |
), | |
m("button", {onclick: ctrl.rotate}, "Rotate links") | |
]) | |
end | |
} | |
m.mount(document.getElementById("example"), Demo) | |
### Example Squiggle app using virtual-dom | |
let H = require "virtual-dom/h" | |
let diff = require "virtual-dom/diff" | |
let patch = require "virtual-dom/patch" | |
let createElement = require "virtual-dom/create-element" | |
let {Object, setInterval, document} = global | |
let {assign} = Object | |
def render(state) | |
H("div", {className: "box"}, [state.count.toString()]) | |
end | |
let app = Object() | |
def start() | |
assign(app, { | |
state: {count: 0}, | |
tree: render(app.state), | |
root: createElement(app.tree) | |
}) | |
document.body.appendChild(app.root) | |
setInterval(update, 1000) | |
end | |
def update() | |
let state = app.state ~ {count: app.state.count + 1} | |
let tree = render(state) | |
let patches = diff(app.tree, tree) | |
let root = patch(app.root, patches) | |
assign(app, {state, root, tree}) | |
end | |
start() | |
### CSV parsing example | |
let papa = require "papaparse" | |
let fs = require "fs" | |
let {Object, console} = global | |
let csv = fs.readFileSync("data.tsv", "utf8") | |
let result = papa.parse(csv, {header: true}) | |
let indexToName = [ | |
"day", | |
"time", | |
"length", | |
"type", | |
"novdec" | |
] | |
def explode(x) | |
x.trim().split(SOME_REGEX) | |
end | |
let counts = { | |
day: Object(), | |
time: Object(), | |
length: Object(), | |
type: Object(), | |
novdec: Object() | |
} | |
def inc(obj, key) | |
let n = | |
if obj has key | |
then 1 + obj[key] | |
else 1 | |
end | |
assign(obj, {key: n}) | |
end | |
result.data.forEach(func(obj, _, _) | |
let fields = result.meta.fields | |
let n = fields.length | |
fields.slice(1, n - 1).forEach(func(k, i, _) | |
let name = indexToName[i] | |
let choices = explode(obj[k]) | |
choices.forEach(func(choice) | |
inc(counts[name], choice) | |
end) | |
end) | |
end) | |
console.log(counts) | |
### END ### |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment