• Stars
    star
    345
  • Rank 122,750 (Top 3 %)
  • Language
    JavaScript
  • Created over 12 years ago
  • Updated about 10 years ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

A small library to enable pattern matching in javascript and coffeescript

Pun

A tiny functional programming library for Javascript/Coffeescript.

Now available on NPM!

Currying

pun.curry allows you to partially apply some values to a function:

f = (a,b,c,d) ->
	[a,b,c,d].join(', ')

fab = pun.curry f, 1, 2

fab(3,4)      # 1, 2, 3, 4
fab("c", "d") # 1, 2, c, d

pun.autocurry allows you to create functions which automatically curry when you apply arguments to them:

# Using f from previous example
autof = pun.autocurry f

autofab = autof(1, 2)

autofab(3,4)      # 1, 2, 3, 4
autofab("c", "d") # 1, 2, c, d

Abstract Data Types

You can use ADTs like so:

List = pun.ADT
	Cons: ['value', 'next']
	Nil:  []

l = List.Cons(1, List.Cons(2, List.Nil()))  # Linked list for [1,2]
l.value                                     # 1
l.next.value                                # 2

And can apply pattern matching!

Pattern Matching

Pun allows for complex pattern matching in javascript/coffeescript. Let's dive in with an example:

Hello, factorial

Coffeescript

$ = pun.$

fac = pun.match(
    0, -> 1
    $, (n) -> n * fac (n-1)
)

Javascript

var $ = pun.$

var fac = pun.match(
    0, function() { return 1 },            // Note required comma at end of line
    $, function(n){ return n * fac(n-1) }
)

This is equivalent to the Haskell:

fac 0 = 1
fac n = n * fac (n-1)

pun.match takes pairs of arguments, the first being the pattern the second being the function applied if the pattern is matched. It will return undefined if there is no match.

Basic Matching

Numbers, strings, bools and undefined/nulls are all matched simply by equality:

f = pun.match(
	110,      -> "one"
	"foobar", -> "two"
	true,     -> "three"
)

f(110)      # "one"
f("foobar") # "two"
f(true)     # "three"

Wildcard

The wild character pun._ can be used to match any value:

_ = pun._

f = pun.match(
    0, -> 0
    1, -> 1
    _, -> "Other"
)

f(0)           # 0
f(1)           # 1
f("foobarbaz") # "Other"

Type Matching

You can pass functions which will be interpreted as type constructors - this allows you to match your own "classes" or the builtin ones:

class Cat

f = pun.match(
	Number,  -> "Number"
	String,  -> "String"
	Boolean, -> "Boolean"
	Cat,      -> "Cat"
)

f(1024)       # "Number"
f("foobar")   # "String"
f(true)       # "Boolean"
cf(new Cat()) # "Cat"

Binding

The $ symbol can be used to 'bind' values so that you can use them in the matching function. You can use it without an argument and the bound value will be passed to match function as an argument, or with an argument of a pattern to match:

$ = pun.$    # alias $ so we can use it more easily

f = pun.match(
    $(Number), (n) -> "Num: #{n}"
    $,         (a) -> "Got: #{a}"
)

f(0)    # "Num: 0"
f(true) # "Got: true"
f({})   # "Got: [object Object]"

Or you can supply it with a string s and it will be avaliable in this.s/@s of the match function:

f = pun.match(
    $('a'), -> "Got: #{@a}"
)

Finally, you can bind to patterns:

f = pun.match(
	$('a',Number), -> "Got: #{@a}"
)

f(1)     # "Got 1"
f(false) # undefined

Arrays

Arrays will be matched item by item and each element of the array is a pattern. The pattern array length and the value array length must be the same.

$ = pun.$

f = pun.match(
	[1,2,3],                             -> "onetwothree"
	[$, $('a'), $('b', Number)], (first) -> "#{first}, #{@a}, #{@b}" 
)

f([0,"lol",2])    # "0, lol, 2"
f([0,"lol",true]) # undefined
f([1,2,3])        # "onetwothree"
f([1,2,3,4])      # undefined

Objects

Objects as a pattern will match each key and value. The value of each key/value pair is a pattern:

$ = pun.$

f = pun.match(
	{a: 0, b: "lol"},          -> "One"
	{a: 0, b: $('n',Number)},  -> "Two #{@n}"
	{a: 0},                    -> "Three"
)

f({a:0})               # "Three"
f({a:0, b:"lol", c:1}) # "One"
f({a:0, b: 4})         # "Two 4"

Abstract Data Types

ADTs can also be matched:

$ = pun.$

from = pun.match(
	List.Nil(),               -> []
	List.Cons($, $),  (x, xs) -> [x].concat from(xs)
)

from(List.Cons 1, List.Cons 2, List.Cons 3, List.Nil())  # [1,2,3]

More Repositories

1

LLVM-Windows-Binaries

A repo of built Windows binaries and instructions on how to compile a shared library on Windows
C#
63
star
2

should-not-typecheck

A HUnit/hspec assertion to verify that an expression does not typecheck
Haskell
42
star
3

omegle

A library to connect with and chat to people on omegle using node
CoffeeScript
20
star
4

stack-ide-atom

Haskell
8
star
5

obc

Oxford Oberon-2 Compiler
OCaml
8
star
6

GbcEmulator

An emulator for the GameBoy Color written in C#
C#
7
star
7

baconsnake

The classic game snake, built in typescript
7
star
8

llvm-strong

Very strongly typed version of llvm-hs
Haskell
6
star
9

AMDOverdriveControlled

Removing "safety" restrictions from popular overclocking tool
C++
5
star
10

Processing.NET

A Processing port to C# that is idiomatic for .NET rather than a converter from Java
C#
3
star
11

Repent

A Haskell port of my original RPN based golfing language, this time without so much unicode D:
Haskell
3
star
12

fay-typescript-def

An automatic typescript IDL to fay FFI compiler
Haskell
3
star
13

SimulaCircuit

A Digital Ciruit Simulator.
C#
3
star
14

coml

COffescript Markup Language. Like haml but written entirely in valid coffeescript.
CoffeeScript
3
star
15

RaskellCompiler

A compiler for something like Haskell, built in Haskell.
Haskell
2
star
16

CarGC

A conservative C garbage collector
C
2
star
17

hcl

A hardware platform for designing processors. (Hardware Control Language)
JavaScript
2
star
18

cloudflare-workers-test

Rust
2
star
19

frp-from-temporal-logic

Playing around with the code/ideas from http://haskellexists.blogspot.co.uk/2016/01/frp-for-free.html
Haskell
2
star
20

reactive-banana-examples

Haskell
2
star
21

jschat

A javascript chat client using websocket, node.js and socket.io (using coffescript, haml and sass)
JavaScript
2
star
22

EmptyDllMain

A library you can link again with if no other object files have a DllMain
C++
2
star
23

BTCstats

An interface for stats from slush's pool and custom sources
C#
1
star
24

omegle-irc-bot

An irc bot which allows many people to chat to one other on omegle, using my omegle library.
JavaScript
1
star
25

hamljs-coffee

Coffeescript plugin for hamljs
JavaScript
1
star
26

old_blog

My musings.
1
star
27

irc-notifier

An irc bot that posts all messages using notify-send
JavaScript
1
star
28

jade

Jade templating in pure Haskell
Haskell
1
star
29

SublimeGHCi

Python
1
star
30

Node.js-Tutorial

Just a small repo to keep my tutorial files synced
JavaScript
1
star
31

bananasnake

The classic game snake, built in Haskell
Haskell
1
star
32

RayTracer

A raytracer in processing
Java
1
star
33

singleton-list-question

Haskell
1
star
34

blog

My musings.
Haskell
1
star
35

SubEdit

A simple SRT time offsetter
C#
1
star
36

scotty-hspec-skeleton

Haskell
1
star
37

miner-control

Haskell
1
star
38

Kinect

Just some messing around with the Kinect.
1
star
39

KinectGroupPractical

C#
1
star
40

dcpu-16-toolkit

JavaScript
1
star
41

crogers.github.com

1
star
42

DrakeCompilerRedux

Haskell
1
star
43

pyopencl-tutorials

Going through http://enja.org/2011/02/22/adventures-in-pyopencl-part-1-getting-started-with-python/
Python
1
star
44

hspec-reactive-banana

Haskell
1
star
45

DrakeCompiler

DrakeCompiler
JavaScript
1
star
46

soop

A Simple Object Orientated Programming Language Compiler
F#
1
star
47

ProjectEuler

Coming back to these problems after a year or so and finishing them off in Scala.
Scala
1
star
48

algebraics

Haskell
1
star
49

binders

Playing around with http://www.cse.chalmers.se/~emax/documents/axelsson2013using.pdf
Haskell
1
star
50

hm-typecheck

Seeing if I can put into use the TDD I've learnt to achieve Hindley-Milner type inference
Haskell
1
star
51

quickbot

A superfast and easy irc bot with a plugin system and remote control.
Shell
1
star
52

FileWatcher

A Ruby/C# tool to run a command every time a file is changed (e.g. for compilation)
Ruby
1
star
53

funell

A compiler for a Haskell like language that is actually fun. Hence funell.
OCaml
1
star