functional ruby

29
FUNCTIONAL RUBY NOT THE RUBY YOU'RE USED TO... OR IS IT? Dave Hackett / @tallguy_hackett

Upload: tallguyhackett

Post on 22-Nov-2014

279 views

Category:

Software


3 download

DESCRIPTION

A presentation I gave at the Utah Ruby Users Group meeting on applying functional programming to the Ruby programming language. The topics covered are immutability, persistence, and expressions as applied to Ruby. The exercises at the end are inspired by www.4clojure.com exercises for the Clojure programming language. The challenge is use a functional mindset and write some methods in Ruby that are the analogous Clojure solution to some exercises. There is a gist with sample code for this endeavor at https://gist.github.com/tallguy-hackett/ddfef3b3e963838dfb0b

TRANSCRIPT

Page 1: Functional Ruby

FUNCTIONAL RUBYNOT THE RUBY YOU'RE USED TO... OR IS IT?

Dave Hackett / @tallguy_hackett

Page 2: Functional Ruby

WHAT IS FUNCTIONAL PROGRAMMING?Funtional Programming (FP) is a style of building the structure

and elements of computer programs, that treats computation asthe evaluation of mathematical functions and avoids state andmutable data. It is a declarative programming paradigm, which

means programming is done with expressions. In functional code,the output value of a function depends only on the arguments

that are input to the function, so calling a function f twice with thesame value for an argument x will produce the same result f(x)

both times. —Wikipedia

Page 3: Functional Ruby

TL;DRFuntional Programming is like math equations.

Page 5: Functional Ruby

IT'S NOT THAT BADThere's just a few things to remember.

Page 6: Functional Ruby

IMMUTABILITYValues are values are values. They don't change.

Page 7: Functional Ruby

PERSISTENCEValues aren't forgotten, overwritten, or removed over time.

Page 8: Functional Ruby

EXPRESSIONSFP is declarative not imperative.

Page 9: Functional Ruby

EXAMPLES IN CLOJURE(doseq [e [1 2 3]] (println e))

; => 1; => 2; => 3

(def orig [1 2 3])

(def added (map inc orig))

; => orig == [1 2 3]; => added == [2 3 4]

(reduce + [1 2 3])

; => 6

Page 10: Functional Ruby

DOES RUBY HAVE SOME OF THIS ALREADY?Yes... kind of... sometimes.

Page 11: Functional Ruby

CHANCES ARE YOU'RE ALREADY APPLYINGSOME FP-ISH TECHNIQUES

ENUMERABLE MODULE

Page 12: Functional Ruby

FP IN RUBY![1, 2, 3].each do |e| puts eend

# => 1# => 2# => 3

orig = [1, 2, 3]added = orig.map do |e| e + 1end

# => orig == [1, 2, 3]# => added == [2, 3, 4]

[1, 2, 3].reduce(:+)

# => 6

Page 13: Functional Ruby

OOPS!orig = [1, 2, 3]added = orig.map! do |e| e + 1end

# => orig == [2, 3, 4]# => added == [2, 3, 4]

greeting = "hello world"

def end_with_a_bang(phrase) phrase << "!"end

puts end_with_a_bang(greeting)# => hello world!puts greeting# => hello world!puts end_with_a_bang(greeting)# => hello world!!puts greeting# => hello world!!

Page 14: Functional Ruby

DOES RUBY HAVE IMMUTABLE VALUES?

Page 15: Functional Ruby

WHY DOESN'T RUBY SUPPORT ++ OR --?

Page 16: Functional Ruby

NUMBERS ARE IMMUTABLEEVERYTHING IS MESSAGE PASSING IN RUBY

explanation

Page 17: Functional Ruby

SYMBOLS ARE IMMUTABLE

Page 18: Functional Ruby

RANGES ARE IMMUTABLE

Page 19: Functional Ruby

DATE AND TIME ARE IMMUTABLE

Page 20: Functional Ruby

VALUES GEMrequire 'values'

Point = Values.new(:x, :y)p = Point.new(1, 2)p.x = 2# => NoMethodError

Values

Page 21: Functional Ruby

WHAT ABOUT DATA STRUCTURES?

Page 22: Functional Ruby

BUILT IN... EPIC FAIL!

Page 23: Functional Ruby

HAMSTER GEMrequire 'hamster'

v = Hamster.vector(1, 2, 3)v1 = v.add(4)# => v == [1, 2, 3]# => v1 == [1, 2, 3, 4]

v2 = v << 5# => v == [1, 2, 3]# => v2 == [1, 2, 3, 5]

v3 = v.set 0, 5# => v == [1, 2, 3]# => v3 == [5, 2, 3]

hamster

Page 24: Functional Ruby

EXPRESSION COMPOSITION

Page 25: Functional Ruby

LIKE IN MATH...FP is composed of a bunch of functions. Complex functions are

functions composed of other functions.

Page 26: Functional Ruby

MATHSo for instance is an example of function

composition. Another way to write the same thing is

f(g(h(x)))

(f ∘ g ∘ h)(x)The story is that the result of is fed as input to whose

result is then fed into for the final result

h(x) g(x)f(x)

Page 27: Functional Ruby

CODESo in code this [[...],[...],...][3].drop(2).first

There are 3 method calls (functions)

[3] occurs first

.drop(2) occurs next

.first occurs last

It makes sense to us that results are passed down the messagechain

Page 28: Functional Ruby

EXERCISES4clojure

Page 29: Functional Ruby

THE ENDBY DAVE HACKETT