SlideShare a Scribd company logo
THINKING
FUNCTIONALLY
 IN
 RUBY.
      @tomstuart
1: Functional
   programming
   is a pretty
   neat idea.
2: Enumerable
   contains
   some useful
   methods.
I hope
these things
are connected.
1.
(Functional programming is a
      pretty neat idea)
What is
  functional
programming?
A programming
style.
Two broad
families of
languages:
• Scheme
  • Common Lisp
  • Dylan
  • Clojure

1. Lisp-like
  • Dynamically typed
  • Homoiconic (code is data)
  • Lists are fundamental
• Standard ML
  • Haskell
  • OCaml
  • Scala (sort of)

2. ML-like
  • Statically typed (+ reconstruction)
  • Code is not data
  • ADTs and pattern matching
Functions
as values
What is
a function?
Thinking Functionally In Ruby
Thinking Functionally In Ruby
Thinking Functionally In Ruby
1               2
7                                       6
    2
                    3       3
    6                   1       7
                5       4           8
        4
Functions
as values
“First-class functions”
      “closures”, “lambdas”,
     “anonymous functions”



Implies: higher-order
      functions
No side
effects
Values are immutable

 All functions do is
 return their result
        No state
         No I/O
(In reality,
 different languages
   accomplish this
to varying degrees.)
Implies: recursion

Implies: persistent
  data structues
So what?
Unfortunately...
Declarative                  T!
                           W HA
 programming
is counterintuitive when
 youʼre accustomed to

  imperative               HOW
                                 !
 programming
Copying is expensive
But!
Referential
            transparency
“an expression can be replaced with its value”

       •   Good for efficiency
           • caching/memoisation/inlining
           • ultimately more efficient
       •   Good for programmer understanding
           • state is incredibly hard to deal with
           • ultimately more intuitive
       •   Good for code reuse and testing
Highly expressive

Strongly compositional

  Deeply satisfying
Future-proof
• Mooreʼs Law is running out of steam
  • similar transistor density, more cores
• The futureʼs concurrent
• Concurrent access to mutable state is hard...
  • but not if you donʼt have mutable state!
• Parallelising an algorithm is hard...
  • but itʼs easier if your code isnʼt overspecified
OK seriously:
 so what?
Ruby can do
 some of this.
 Not really a functional language, but we
can pretend and get some of the benefits.
Use function values
       blocks, procs


lambda { |x| x + 1 }
Consider treating
  your values
 as immutable
   State is rarely worth it.
  It will kill you in the end.
http://clojure.org/state
Use the
functional-flavoured
    parts of the
  standard library
Think functionally.
     Be declarative.
     What, not how.
2.
(Enumerable contains
 some useful methods)
Enumerable#zip
[1, 2, 3, 4].
  zip([5, 6, 7, 8])
1   2   3   4


5   6   7   8
1   5   2   6   3   7   4   8
[                            ]
[1 , 5],[2 , 6],[3 , 7],[4 , 8]
[1, 2, 3, 4].
  zip([5, 6, 7, 8],
      [9, 10, 11, 12])
Enumerable#select
 (a.k.a. #find_all)
{ |x| x.odd? }
1
?
1
!
?
1
1   2
!
?
1   ?
1   2
!
?
1   "
    ?
    2
[1, 2, 3, 4].
 select { |x| x.odd? }
1   2   3   4
?   ?   ?   ?
1   2   3   4
!
?
1   "
    ?
    2   !
        ?
        3   "
            ?
            4
1       3
!
?
1       !
        ?
        3
    1       3
[ 1, 3 ]
Enumerable#partition
[1, 2, 3, 4].
  partition { |x| x.odd? }
1   2   3   4
?   ?   ?   ?
1   2   3   4
!
?
1   "
    ?
    2   !
        ?
        3   "
            ?
            4
1   3   2   4
!
?   !
    ?   "
        ?   "
            ?
1       3       2       4
!
?       !
        ?       "
                ?       "
                        ?
    1       3       2       4
[[ 1 , 3 ] , [ 2 , 4 ]]
Enumerable#map
(a.k.a. #collect)
{ |x| x * 3 }
2
×3
6
2
×3
2
6
[1, 2, 3, 4].
   map { |x| x * 3 }
1    2    3    4
×3
3    ×3
     6    ×3
          9    ×3
               12
1    2    3    4
×3
1    ×3
     2    ×3
          3    ×3
               4
3    6    9    12
[ , , , ]
 3   6   9 12
Enumerable#inject
  (a.k.a. #reduce)
{ |x, y| x + y }
3       5
        8
    +
3   5
3+5     8
[1, 2, 3, 4].
  inject(0) { |x,y| x+y }
0
        1
        1
    +
                2
                3
            +
                        3
                        6
                    +
                                4
                            +
                            10
0 1
0+1
      1   2
      1+2
              3   3
              3+3
                      6   4
                      6 + 4 10
module Enumerable
  def inject(initial)
    result = initial

   for element in self
     result = yield(result, element)
   end

    result
  end
end
a.k.a. “left fold”
(foldl, fold_left)
0 1 2 3 4
10
(((0 + 1) + 2) + 3) + 4
...versus “right fold”
(foldr, fold_right)
1 2 3 4 0
10
1 + (2 + (3 + (4 + 0)))
The initial argument is
      optional...
[1, 2, 3, 4].
  inject { |x,y| x+y }
[2, 3, 4].4].
[1, 2, 3,
  inject(1)|x,y| x+yx+y }
  inject { { |x,y| }
...but only if the
output is the same
type as the input...
>> ['El', 'rug'].
   inject(0) { |l,s| l + s.length }
=> 5

>> ['El', 'rug'].
   inject { |l,s| l + s.length }
TypeError: can't convert Fixnum into String
  from (irb):1:in `+'
  from (irb):1
  from (irb):1:in `inject'
  from (irb):1:in `each'
  from (irb):1:in `inject'
  from (irb):1
...and itʼs meaningful
 to get nil when the
  collection is empty
>> [].inject { |x,y| x+y }
=> nil

>> [].inject(0) { |x,y| x+y }
=> 0

>> [].inject(1) { |x,y| x*y }
=> 1
P O SE !
C O M
[1, 2, 3, 4].
  map { |x| x * 3 }.
  inject(0) { |x| x+y }
1       2       3       4
    ×3
    3       ×3
            6       ×3
                    9       ×3
                            12

0
        3
    +
                9
            +
                    +
                    18

                            +
                            30
1       2        3       4
 ×3
 1        ×3
          2        ×3
                   3      ×3
                          4

0 3
0+3   3   6
      3+6      9   9
               9 + 9 18 12
                        18+12 30
I am so
 excited.
What now?
Review your
Ruby code.
Func it up.
result = ''
for name in names
  unless result.empty?
    result << ', '
  end
  result << name
end
result
!
result = ''
for name in names
  unless result.empty?
    result << ', '
  end
  result << name
end
result



names.join(', ')
def count_mines_near(x, y)
  count = 0
  for i in x-1..x+1
    for j in y-1..y+1
      count += 1 if mine_at?(i, j)
    end
  end
  count
end
!
def count_mines_near(x, y)
  count = 0
  for i in x-1..x+1
    for j in y-1..y+1
      count += 1 if mine_at?(i, j)
    end
  end
  count
end

def count_mines_near(x, y)
  ((x-1..x+1).entries * 3).sort.
    zip((y-1..y+1).entries * 3).
    select { |x, y| mine_at?(x, y) }.
    length
end
[1, 2, 3, 1, 2, 3, 1, 2, 3].sort =
 [1, 1, 1, 2, 2, 2, 3, 3, 3]




def count_mines_near(x, y) # = (2, 8)
  ((x-1..x+1).entries * 3).sort.
    zip((y-1..y+1).entries * 3).
    select { |x, y| mine_at?(x, y) }.
    length
end
[1, 2, 3, 1, 2, 3, 1, 2, 3].sort =
 [1, 1, 1, 2, 2, 2, 3, 3, 3].zip(
 [7, 8, 9, 7, 8, 9, 7, 8, 9]) =
 [[1, 7], [1, 8], [1, 9],
  [2, 7], [2, 8], [2, 9],
  [3, 7], [3, 8], [3, 9]]


def count_mines_near(x, y) # = (2, 8)
  ((x-1..x+1).entries * 3).sort.
    zip((y-1..y+1).entries * 3).
    select { |x, y| mine_at?(x, y) }.
    length
end
[1, 2, 3, 1, 2, 3, 1, 2, 3].sort =
 [1, 1, 1, 2, 2, 2, 3, 3, 3].zip(
 [7, 8, 9, 7, 8, 9, 7, 8, 9]) =
 [[1, 7], [1, 8], [1, 9],
  [2, 7], [2, 8], [2, 9],
  [3, 7], [3, 8], [3, 9]].select {…} =
 [[1, 8], [3, 7]].length = 2
def count_mines_near(x, y) # = (2, 8)
  ((x-1..x+1).entries * 3).sort.
    zip((y-1..y+1).entries * 3).
    select { |x, y| mine_at?(x, y) }.
    length
end
[      [1, 7],    [1, 8],   …,    [1, 1007],
       [2, 7],    [2, 8],   …,    [2, 1007],
            …,              …,            …,
    [1000, 7], [1000, 8],   …, [1000, 1007],
    [1001, 7], [1000, 8],   …, [1001, 1007]]




def count_mines_near(x, y)
  ((x-500..x+500).entries * 1001).sort.
    zip((y-500..y+500).entries * 1001).
    select { |x, y| mine_at?(x, y) }.
    length
end
[      [1, 7],    [1, 8],   …,    [1, 1007],
       [2, 7],    [2, 8],   …,    [2, 1007],
            …,              …,            …,
    [1000, 7], [1000, 8],   …, [1000, 1007],
    [1001, 7], [1000, 8],   …, [1001, 1007]]




      173      96      121       78    237

                       705
def numbers_near(n, radius)
  ((n - radius)..(n + radius)).entries
end

def squares_near(x, y, radius)
  diameter = (radius * 2) + 1
  (numbers_near(x, radius) * diameter).
    sort.
    zip(numbers_near(y, radius) * diameter)
end

def count_mines_near(x, y, radius = 1)
  squares_near(x, y, radius).
    select { |x, y| mine_at?(x, y) }.
    length
end
Learn a
functional language
• OCaml
• Scheme (Google “SICP”)
• Clojure
• Scala
• Haskell? Erlang?
Thanks!
@tomstuart / tom@experthuman.com
http://www.flickr.com/photos/somemixedstuff/2403249501/




  http://en.wikipedia.org/wiki/File:Modified-pc-case.png

More Related Content

What's hot (20)

PPT
Prashant tiwari ppt.on
Prashant tiwari
 
PPTX
Adding and subtracting polynomials
ewhitener
 
PPT
Add/Subtract polynomials
swartzje
 
PPT
Chapter 2.5
nglaze10
 
PDF
Monads and Monoids by Oleksiy Dyagilev
JavaDayUA
 
PPTX
Operations on Polynomials
Ver Louie Gautani
 
PPTX
Python data structures
kalyanibedekar
 
PDF
A tour of Python
Aleksandar Veselinovic
 
KEY
Notes 12.1 identifying, adding & subtracting polynomials
Lori Rapp
 
PPTX
Addition and subtraction in polynomials
saidyein
 
PDF
Cheat sheet python3
sxw2k
 
PPT
Adding Polynomials
chulitt
 
PPT
Multiplying polynomials
chrystal_brinson
 
PDF
Python3 cheatsheet
Gil Cohen
 
PPT
Adding and subtracting polynomials
holmsted
 
PDF
Python_ 3 CheatSheet
Dr. Volkan OBAN
 
KEY
0304 ch 3 day 4
festivalelmo
 
PPTX
Multiplying Polynomials
Mary Ann Villanueva
 
PDF
Haskell in the Real World
osfameron
 
DOCX
สมการเชิงเส้นตัวแปรเดียว
Destiny Nooppynuchy
 
Prashant tiwari ppt.on
Prashant tiwari
 
Adding and subtracting polynomials
ewhitener
 
Add/Subtract polynomials
swartzje
 
Chapter 2.5
nglaze10
 
Monads and Monoids by Oleksiy Dyagilev
JavaDayUA
 
Operations on Polynomials
Ver Louie Gautani
 
Python data structures
kalyanibedekar
 
A tour of Python
Aleksandar Veselinovic
 
Notes 12.1 identifying, adding & subtracting polynomials
Lori Rapp
 
Addition and subtraction in polynomials
saidyein
 
Cheat sheet python3
sxw2k
 
Adding Polynomials
chulitt
 
Multiplying polynomials
chrystal_brinson
 
Python3 cheatsheet
Gil Cohen
 
Adding and subtracting polynomials
holmsted
 
Python_ 3 CheatSheet
Dr. Volkan OBAN
 
0304 ch 3 day 4
festivalelmo
 
Multiplying Polynomials
Mary Ann Villanueva
 
Haskell in the Real World
osfameron
 
สมการเชิงเส้นตัวแปรเดียว
Destiny Nooppynuchy
 

Similar to Thinking Functionally In Ruby (20)

PDF
Functional programming in ruby
Koen Handekyn
 
PDF
Clojure: The Art of Abstraction
Alex Miller
 
PDF
Dont Drive on the Railroad Tracks
Eugene Wallingford
 
PDF
From Javascript To Haskell
ujihisa
 
PDF
Let’s Talk About Ruby
Ian Bishop
 
PPTX
F# Presentation
mrkurt
 
PPTX
Ruby's Arrays and Hashes with examples
Niranjan Sarade
 
PDF
Peyton jones-2011-type classes
Takayuki Muranushi
 
KEY
Functional ruby
Kerry Buckley
 
PPT
Intro to Functional Programming Workshop (code4lib)
Will Kurt
 
PDF
Clojure for Rubyists
Jean-François Héon
 
PPTX
The Essence of the Iterator Pattern
Eric Torreborre
 
PDF
FSharp Talk
HaiBin Chang
 
PDF
Scala by Luc Duponcheel
Stephan Janssen
 
PDF
The Essence of the Iterator Pattern (pdf)
Eric Torreborre
 
PDF
Introduction to Haskell@Open Source Conference 2007 Hokkaido
ikegami__
 
PDF
Advanced
Logan Campbell
 
PDF
All I Needed for Functional Programming I Learned in High School Algebra
Eric Normand
 
PPT
Python 101 language features and functional programming
Lukasz Dynowski
 
PDF
Be aware of side effects
ryanlemmer
 
Functional programming in ruby
Koen Handekyn
 
Clojure: The Art of Abstraction
Alex Miller
 
Dont Drive on the Railroad Tracks
Eugene Wallingford
 
From Javascript To Haskell
ujihisa
 
Let’s Talk About Ruby
Ian Bishop
 
F# Presentation
mrkurt
 
Ruby's Arrays and Hashes with examples
Niranjan Sarade
 
Peyton jones-2011-type classes
Takayuki Muranushi
 
Functional ruby
Kerry Buckley
 
Intro to Functional Programming Workshop (code4lib)
Will Kurt
 
Clojure for Rubyists
Jean-François Héon
 
The Essence of the Iterator Pattern
Eric Torreborre
 
FSharp Talk
HaiBin Chang
 
Scala by Luc Duponcheel
Stephan Janssen
 
The Essence of the Iterator Pattern (pdf)
Eric Torreborre
 
Introduction to Haskell@Open Source Conference 2007 Hokkaido
ikegami__
 
Advanced
Logan Campbell
 
All I Needed for Functional Programming I Learned in High School Algebra
Eric Normand
 
Python 101 language features and functional programming
Lukasz Dynowski
 
Be aware of side effects
ryanlemmer
 
Ad

More from Ross Lawley (19)

PDF
Kanban For Software Engineering Apr 242
Ross Lawley
 
PDF
Kanban Vs Scrum
Ross Lawley
 
PDF
How To Fail With Agile
Ross Lawley
 
PDF
Evolving From Scrum To Lean
Ross Lawley
 
PDF
Anti Patterns2008
Ross Lawley
 
PDF
Couch Db
Ross Lawley
 
PDF
Metaprogramming in Ruby
Ross Lawley
 
PDF
Designing For Web2
Ross Lawley
 
PDF
Designing Web2
Ross Lawley
 
PDF
GOF patterns in Ruby
Ross Lawley
 
PDF
User Experience Pain Free
Ross Lawley
 
PDF
L R U G - JRuby
Ross Lawley
 
PDF
Juggling
Ross Lawley
 
PDF
Rails Conf Europe 2007 Notes
Ross Lawley
 
PDF
Learning To Love Forms Webvisions 07 21033
Ross Lawley
 
PDF
Wiki Design Luke W
Ross Lawley
 
PDF
B D D Intro
Ross Lawley
 
PDF
Thesis Carohorn
Ross Lawley
 
PDF
When Interface Design Attacks
Ross Lawley
 
Kanban For Software Engineering Apr 242
Ross Lawley
 
Kanban Vs Scrum
Ross Lawley
 
How To Fail With Agile
Ross Lawley
 
Evolving From Scrum To Lean
Ross Lawley
 
Anti Patterns2008
Ross Lawley
 
Couch Db
Ross Lawley
 
Metaprogramming in Ruby
Ross Lawley
 
Designing For Web2
Ross Lawley
 
Designing Web2
Ross Lawley
 
GOF patterns in Ruby
Ross Lawley
 
User Experience Pain Free
Ross Lawley
 
L R U G - JRuby
Ross Lawley
 
Juggling
Ross Lawley
 
Rails Conf Europe 2007 Notes
Ross Lawley
 
Learning To Love Forms Webvisions 07 21033
Ross Lawley
 
Wiki Design Luke W
Ross Lawley
 
B D D Intro
Ross Lawley
 
Thesis Carohorn
Ross Lawley
 
When Interface Design Attacks
Ross Lawley
 
Ad

Recently uploaded (20)

PPTX
AUTOMATION AND ROBOTICS IN PHARMA INDUSTRY.pptx
sameeraaabegumm
 
PDF
How Startups Are Growing Faster with App Developers in Australia.pdf
India App Developer
 
PPTX
Webinar: Introduction to LF Energy EVerest
DanBrown980551
 
PDF
July Patch Tuesday
Ivanti
 
PDF
POV_ Why Enterprises Need to Find Value in ZERO.pdf
darshakparmar
 
PDF
Smart Trailers 2025 Update with History and Overview
Paul Menig
 
PDF
Transforming Utility Networks: Large-scale Data Migrations with FME
Safe Software
 
PDF
Biography of Daniel Podor.pdf
Daniel Podor
 
PDF
What Makes Contify’s News API Stand Out: Key Features at a Glance
Contify
 
PPTX
From Sci-Fi to Reality: Exploring AI Evolution
Svetlana Meissner
 
PPTX
Q2 FY26 Tableau User Group Leader Quarterly Call
lward7
 
PDF
Staying Human in a Machine- Accelerated World
Catalin Jora
 
PDF
Newgen 2022-Forrester Newgen TEI_13 05 2022-The-Total-Economic-Impact-Newgen-...
darshakparmar
 
PDF
Advancing WebDriver BiDi support in WebKit
Igalia
 
PDF
DevBcn - Building 10x Organizations Using Modern Productivity Metrics
Justin Reock
 
PDF
CIFDAQ Token Spotlight for 9th July 2025
CIFDAQ
 
PDF
Go Concurrency Real-World Patterns, Pitfalls, and Playground Battles.pdf
Emily Achieng
 
PDF
Achieving Consistent and Reliable AI Code Generation - Medusa AI
medusaaico
 
PDF
“NPU IP Hardware Shaped Through Software and Use-case Analysis,” a Presentati...
Edge AI and Vision Alliance
 
PDF
Jak MŚP w Europie Środkowo-Wschodniej odnajdują się w świecie AI
dominikamizerska1
 
AUTOMATION AND ROBOTICS IN PHARMA INDUSTRY.pptx
sameeraaabegumm
 
How Startups Are Growing Faster with App Developers in Australia.pdf
India App Developer
 
Webinar: Introduction to LF Energy EVerest
DanBrown980551
 
July Patch Tuesday
Ivanti
 
POV_ Why Enterprises Need to Find Value in ZERO.pdf
darshakparmar
 
Smart Trailers 2025 Update with History and Overview
Paul Menig
 
Transforming Utility Networks: Large-scale Data Migrations with FME
Safe Software
 
Biography of Daniel Podor.pdf
Daniel Podor
 
What Makes Contify’s News API Stand Out: Key Features at a Glance
Contify
 
From Sci-Fi to Reality: Exploring AI Evolution
Svetlana Meissner
 
Q2 FY26 Tableau User Group Leader Quarterly Call
lward7
 
Staying Human in a Machine- Accelerated World
Catalin Jora
 
Newgen 2022-Forrester Newgen TEI_13 05 2022-The-Total-Economic-Impact-Newgen-...
darshakparmar
 
Advancing WebDriver BiDi support in WebKit
Igalia
 
DevBcn - Building 10x Organizations Using Modern Productivity Metrics
Justin Reock
 
CIFDAQ Token Spotlight for 9th July 2025
CIFDAQ
 
Go Concurrency Real-World Patterns, Pitfalls, and Playground Battles.pdf
Emily Achieng
 
Achieving Consistent and Reliable AI Code Generation - Medusa AI
medusaaico
 
“NPU IP Hardware Shaped Through Software and Use-case Analysis,” a Presentati...
Edge AI and Vision Alliance
 
Jak MŚP w Europie Środkowo-Wschodniej odnajdują się w świecie AI
dominikamizerska1
 

Thinking Functionally In Ruby