Slide 1

Slide 1 text

RWTH Aachen, Computer Science Student triAGENS GmbH, Developer moon lum moonbeamlabs by Lucas Dohmen Functional Pro rammin for Rubyists λ

Slide 2

Slide 2 text

Ruby Smalltalk Perl Lisp (Matz)

Slide 3

Slide 3 text

“ Ruby is like Smalltalk and LISP ot to ether and ot a love child and then went o to work and hired Perl to be the nanny. Josh Susser in Thinkin in Objects (RubyConf 2012)

Slide 4

Slide 4 text

Imperative Declarative Procedural OOP Lo ical Functional

Slide 5

Slide 5 text

Models of Computation Turin M achine Church‘s λ-Calculus First order lo ic Functional Pro ram m in Lo ical Pro rammin Im perative Lan ua es

Slide 6

Slide 6 text

Church-Turin thesis • All al orithmically computable functions can be pro rammed on a Turin Machine (Turin ) • All al orithmically computable functions can be pro rammed with the λ-calculus (Church) • Corollary: Turin Machines and λ-calculus can do all the same stu (Dohmen)

Slide 7

Slide 7 text

Functional Lan ua es • Lisp Family • Scheme, Common Lisp, Clojure (& Dylan) • ML Family • Haskell • Erlan • Scala

Slide 8

Slide 8 text

LISP vs. Haskell • Invented by McCarthy (1958) • Used since the dawn of time • You can use it in any paradi m (see CLOS) • Uncountable number of dialects • Desi n by committee (First draft 1990) • Developed in the Ivory Tower • Purity and Laziness as hi hest principles • One clearly defined lan ua e

Slide 9

Slide 9 text

LISP vs. Haskell • Invented by McCarthy (1958) • Used since the dawn of time • You can use it in any paradi m (see CLOS) • Uncountable number of dialects • Desi n by committee (First draft 1990) • Developed in the Ivory Tower • Purity and Laziness as hi hest principles • One clearly defined lan ua e C was introduced in 1972

Slide 10

Slide 10 text

λ-Calculus LISP is a pimped Lambda Calculus The smallest pro rammin lan ua e that exists

Slide 11

Slide 11 text

A short example (( x. plus x 1) 4)

Slide 12

Slide 12 text

A short example (( x. plus x 1) 4) (plus 4 1) β-reduction

Slide 13

Slide 13 text

A short example (( x. plus x 1) 4) With iven δ: = {plus( x, y ) ! x + y } (plus 4 1) β-reduction

Slide 14

Slide 14 text

A short example (( x. plus x 1) 4) With iven δ: = {plus( x, y ) ! x + y } (plus 4 1) β-reduction δ-reduction 4

Slide 15

Slide 15 text

Why you can‘t use Ruby as a functional lan ua e

Slide 16

Slide 16 text

Quiz Time (yep, the theory stu is over) a = puts "b" Where is the side e ect?

Slide 17

Slide 17 text

• One of the hard parts of testin • Haskell only allows side e ects with Monads • Ruby or LISP do not mark them in any way • In Haskell unit testin is really simple Side E ects

Slide 18

Slide 18 text

No Proper Tail Calls • The bi di erence between iterative and recursive pro rammin • Without tail call optimization, every recursive call will add another frame to the call stack • Rule of Thumb: If your lan ua e doesn‘t have PTCs, you should hold your horses with recursive functions

Slide 19

Slide 19 text

Where you can use Ruby‘s functional herita e

Slide 20

Slide 20 text

• In Ruby they all take blocks, not methods (doesn‘t make them less hi her order) • You all know each • …but there are also map, reduce, inject… • Look into the documentation of Enumerable :) Hi her Order Functions

Slide 21

Slide 21 text

How is it implemented? def collect if block_given? ary = [] each do |*o| ary << yield(*o) end ary else to_enum :collect end end alias_method :map, :collect (Implementation in Rubinius)

Slide 22

Slide 22 text

How is it implemented? (Implementation in Rubinius) def each return to_enum(:each) unless block_given? i = @start total = i + @total tuple = @tuple while i < total yield tuple.at(i) i += 1 end self end

Slide 23

Slide 23 text

Lazy Evaluation • Only evaluate a statement if there is no way around that • Ruby is quite lazy • But Haskell is really, really lazy • I‘m talkin Dude-level lazy 1 or this_variable_does_not_exist # => 1

Slide 24

Slide 24 text

Show me somethin • Task: Find the sum of the first x numbers that are dividable by 3 or 5 • First lets write it in idiomatic Haskell • Then lets emulate it with Ruby (2.0)

Slide 25

Slide 25 text

No content

Slide 26

Slide 26 text

-- Step 1: -- An infinite list of all positive integers [1..]

Slide 27

Slide 27 text

-- Step 1: -- An infinite list of all positive integers [1..] -- Step 2: -- Now only those that are dividable by 3 and 5 [n | n <- [1..], n `mod` 3 == 0 || n `mod` 5 == 0]

Slide 28

Slide 28 text

-- Step 1: -- An infinite list of all positive integers [1..] -- Step 2: -- Now only those that are dividable by 3 and 5 [n | n <- [1..], n `mod` 3 == 0 || n `mod` 5 == 0] This is a so called uard [ n | n 2 N, n mod 3 = 0 , n mod 5 = 0] It is inspired by… math!

Slide 29

Slide 29 text

-- Step 1: -- An infinite list of all positive integers [1..] -- Step 2: -- Now only those that are dividable by 3 and 5 [n | n <- [1..], n `mod` 3 == 0 || n `mod` 5 == 0] -- Step 3: -- Only the first x take x [...]

Slide 30

Slide 30 text

-- Step 1: -- An infinite list of all positive integers [1..] -- Step 2: -- Now only those that are dividable by 3 and 5 [n | n <- [1..], n `mod` 3 == 0 || n `mod` 5 == 0] -- Step 3: -- Only the first x take x [...] -- Step 4 -- Add them foldl (+) 0 (take x [...])

Slide 31

Slide 31 text

foldl (+) 0 (take x [n | n <- [1..], n `mod` 5 == 0 || n `mod` 3 == 0])

Slide 32

Slide 32 text

foldl (+) 0 (take x [n | n <- [1..], n `mod` 5 == 0 || n `mod` 3 == 0]) (1..Float::INFINITY)

Slide 33

Slide 33 text

foldl (+) 0 (take x [n | n <- [1..], n `mod` 5 == 0 || n `mod` 3 == 0]) (1..Float::INFINITY).lazy

Slide 34

Slide 34 text

. .select { |n| n % 3 == 0 || n % 5 == 0 } foldl (+) 0 (take x [n | n <- [1..], n `mod` 5 == 0 || n `mod` 3 == 0]) (1..Float::INFINITY).lazy

Slide 35

Slide 35 text

. .select { |n| n % 3 == 0 || n % 5 == 0 } foldl (+) 0 (take x [n | n <- [1..], n `mod` 5 == 0 || n `mod` 3 == 0]) (1..Float::INFINITY).lazy .take(x)

Slide 36

Slide 36 text

. .select { |n| n % 3 == 0 || n % 5 == 0 } foldl (+) 0 (take x [n | n <- [1..], n `mod` 5 == 0 || n `mod` 3 == 0]) (1..Float::INFINITY).lazy .take(x).inject(0, :+)

Slide 37

Slide 37 text

Fun Fact • Fold is also known as foldl, reduce, accumulate, compress or inject • This is of course not confusin at all • LISP is to blame

Slide 38

Slide 38 text

Immutability • In Haskell, everythin is immutable • In Ruby, almost everythin is mutable • hamster em: E cient, Immutable, Thread- Safe Collection classes for Ruby • adamantium em: Immutable extensions to objects

Slide 39

Slide 39 text

require "adamantium" class Wolverine include Adamantium attr_accessor :health def initialize @health = 100 end end wolverine = Wolverine.new p wolverine.health #=> 100 wolverine.health = 211 #=> can't modify frozen Wolverine (RuntimeError)

Slide 40

Slide 40 text

require "adamantium" class Wolverine include Adamantium attr_accessor :health def initialize @health = 100 end end wolverine = Wolverine.new p wolverine.health #=> 100 wolverine.health = 211 #=> can't modify frozen Wolverine (RuntimeError) Warnin ! This lib is confusin

Slide 41

Slide 41 text

Wrappin up…

Slide 42

Slide 42 text

Why doesn‘t it succeed? • Not a ood model for the world • Lar e systems tend to separate into communicatin sub systems… • … and that is pretty much Alan Kay‘s idea

Slide 43

Slide 43 text

Still… • It‘s a lot of fun to play around with • It‘s a ood fit for certain problem types • It‘s a nice exercise for the brain to try a di erent paradi m • … and immutability and no side e ects are the key to parallel pro rammin ;)

Slide 44

Slide 44 text

Further Readin /Listenin • Book: Land Of Lisp • Talk: Jim Weirich‘s Y Not – Adventures in Functional Pro rammin • Blo Article: Pro rammin with Nothin