Skip to content

Instantly share code, notes, and snippets.

@wavebeem
Last active December 3, 2015 03:09
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save wavebeem/dcea6b70f0cee32fcc1b to your computer and use it in GitHub Desktop.
Save wavebeem/dcea6b70f0cee32fcc1b to your computer and use it in GitHub Desktop.
### 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