lambda calculus beep boop

recursion: https://beep-boop-bap.glitch.me/

we: @einarwh, @JonasWinje

soundtest

Sounds.playStuff([{ beops: "beep beep boop boop pling bap".split(" ")}])

commands for slides

Exp u ::= x variable
λx.u abstraction
u1 u2 application
this is mostly about syntax really
also it's like stupid I guess

semantics though

replace references to parameter with argument

(λa.λb.λc.c a b) foo bar quux
(λb.λc.c foo b) bar quux
(λc.c foo bar) quux
quux foo bar

this slide is wide :)

(λa.λb.λc.c a b) foo bar quux
(λb.λc.c foo b) bar quux
(λc.c foo bar) quux
quux foo bar

some lambdas

0 is λf.λx.x
1 is λf.λx.f x
2 is λf.λx.f (f x)
3 is λf.λx.f (f (f x))
5 is λf.λx.f (f (f (f (f x))))
and so on

some lambdas

+ is λa.λb.λf.λx.a f (b f x)
(f applied a times to f applied b times to x)

* is λa.λb.λf.λx.a (b f) x
(f applied b times a times to x)

can try

2 ≜ λf.λx.f (f x)
3 ≜ λf.λx.f (f (f x))
+ ≜ λa.λb.λf.λx.a f (b f x)
* ≜ λa.λb.λf.λx.a (b f) x

+ 2 2
+ 2 3

variable capture thing

λy.(λx.λy.x) y

variable capture thing

λy.(λx.λy.x) y

λy.λy.y

oh no

variable capture thing

λy.(λx.λy.x) y

rename inner y before reducing

λy.(λx.λy.x) y

de bruijn index

Exp u ::= n variable
λu abstraction
u1 u2 application

λz.(λy.y (λx. x)) (λx.z x)

some lambdas

0 is λλ1
1 is λλ2 1
2 is λλ2 (2 1)
3 is λλ2 (2 (2 1))
5 is λλ2 (2 (2 (2 (2 1))))
and so on

some lambdas

+ is λλλλ4 2 (3 2 1)
(um)

* is λλλλ4 (3 2) 1
(uh)

some lambdas

+ is λa.λb.λf.λx.a f (b f x)
(f applied a times to f applied b times to x)

* is λa.λb.λf.λx.a (b f) x
(f applied b times a times to x)

λa.λb.λf.λx.a f (b f x)
λa.λb.λf.λx.a f (b f x)

2 + 3

(λλλλ4 2 (3 2 1)) (λλ2 (2 1)) (λλ2 (2 (2 1)))
(λλλ(λλ2 (2 1)) 2 (3 2 1)) (λλ2 (2 (2 1)))
λλ(λλ2 (2 1)) 2 ((λλ2 (2 (2 1))) 2 1)
λλ(λ3 (3 1)) ((λλ2 (2 (2 1))) 2 1)
λλ2 (2 ((λλ2 (2 (2 1))) 2 1))
λλ2 (2 ((λ3 (3 (3 1))) 1))
λλ2 (2 (2 (2 (2 1))))

2 * 3

(λλλλ4 (3 2) 1) (λλ2 (2 1)) (λλ2 (2 (2 1)))
(λλλ(λλ2 (2 1)) (3 2) 1) (λλ2 (2 (2 1)))
λλ(λλ2 (2 1)) ((λλ2 (2 (2 1))) 2) 1
λλ(λ(λλ2 (2 (2 1))) 3 ((λλ2 (2 (2 1))) 3 1)) 1
λλ(λλ2 (2 (2 1))) 2 ((λλ2 (2 (2 1))) 2 1)
λλ(λ3 (3 (3 1))) ((λλ2 (2 (2 1))) 2 1)
λλ2 (2 (2 ((λλ2 (2 (2 1))) 2 1)))
λλ2 (2 (2 ((λ3 (3 (3 1))) 1)))
λλ2 (2 (2 (2 (2 (2 1)))))

variable capture thing

λy.(λx.λy.x) y

λ(λλ2) 1

variable capture thing

λ(λλ2) 1

λλ2

λy.(λx.λy.x) y
λy2.(λx.λy.x) y2
λy2.λy.y2
λy2.(λx.λy.x) y2
λy2.λy.y2
λy2.(λx.λy.x (λy.x)) y2
λy2.λy.y2 (λy.y2)

anyway

beep boop

Exp u ::= boop b variable
beep u abstraction
pling u1 u2 application

Boops b ::= bap bap
boop b boop

so the identity function is beep boop bap

nice

so the identity function is beep boop bap

λx.x
λx.x

some beep boops

0 is beep beep boop bap
1 is beep beep pling boop boop bap boop bap
2 is beep beep pling boop boop bap pling boop boop bap boop bap
3 is beep beep pling boop boop bap pling boop boop bap pling boop boop bap boop bap
5 is beep beep pling boop boop bap pling boop boop bap pling boop boop bap pling boop boop bap pling boop boop bap boop bap
and so on

some beep boops

+ is beep beep beep beep pling pling boop boop boop boop bap boop boop bap pling pling boop boop boop bap boop boop bap boop bap
* is beep beep beep beep pling pling boop boop boop boop bap pling boop boop boop bap boop boop bap boop bap

2 + 3

pling pling beep beep beep beep pling pling boop boop boop boop bap boop boop bap pling pling boop boop boop bap boop boop bap boop bap beep beep pling boop boop bap pling boop boop bap boop bap beep beep pling boop boop bap pling boop boop bap pling boop boop bap boop bap

we can try

for keyboard: a = beep, s = boop d = bap, f = pling, backspace = undo, space = "next"

with tree

lambdatree!

more lambdaer

also actual sounds

cannot syntax error

λf.λx.f (f x
λf.λx f (f x)
x.x

so uh what else?

I mean, there's fish?

Einar always has some fish

Svg.create( 600, 600, Mirror.mirrorShapes( 600, Picture.squareLimitColor( 4, Magic.createPicture(Fish.fancy())) (Lens.create( Box.create( Vector.create(100, 100), Vector.create(400, 0), Vector.create(0, 400)), Hue.create("black")))).map(r => r.shape.toSvgElement(r.style)))

some other picture combinator thing

maybe more legible

can make it sound different

const supersaw = (freq, vol, sawNumber, detune) => { let g = Sounds.audioContext().createGain(); g.gain.setValueAtTime(0, Sounds.audioContext().currentTime); for (let i = 0; i < sawNumber; i++) { let saw = Sounds.audioContext().createOscillator(); saw.type = 'sawtooth'; saw.frequency.setValueAtTime(freq, Sounds.audioContext().currentTime); saw.detune.value = -detune + i * 2 * (detune / (sawNumber - 1)); saw.start(); saw.connect(g); } let dur = 0; for (let i = 0; i < vol.length; i++) { dur = dur + vol[i].time; } dur = dur * 0.5; g.connect(Sounds.audioContext().destination); return Sounds.note(dur, [{ dial: g.gain, vts: vol }]); } const sawVol = [ { val: 0.13, time: 0.1 }, { val: 0.1, time: 0.2 }, { val: 0.1, time: 0.5 }, { val: 0, time: 0.3 }]; const saw = (freq) => supersaw(freq, sawVol, 7, 10); Sounds.setNotes(new Map( [ ["beep", saw(440)], ["boop", saw(493.88)], ["bap", saw(523.25)], ["pling", saw(587.33)], ["undo", saw(800)], ["next", saw(250)] ]));

(supersaw stolen from @mollerse. code.)

forever

omega!

const f = (x) => [{ val: x * 1.2, time: 0.7 }, { val: x, time: 0.3 }]; const vol = [ { val: 0.13, time: 0.1 }, { val: 0.1, time: 0.2 }, { val: 0.1, time: 0.5 }, { val: 0, time: 0.3 } ]; const newNotes = new Map([ ["beep", Sounds.makeNote(f(400), vol)], ["boop", Sounds.makeNote(f(460), vol)], ["bap", Sounds.makeNote(f(515), vol)], ["pling", Sounds.makeNote(f(550), vol)], ["undo", Sounds.makeNote(f(800), vol)], ["next", Sounds.makeNote(f(250), vol)] ]); Sounds.setNotes(newNotes);

conclusion

code

https://glitch.com/edit/#!/beep-boop-bap