Given at Dominion Enterprises software developers users group in Dec, 2011. Purpose -- introduce Ruby and Rails to the group. Original presentation consisted of two parts: slides and live Rails application building. Slides are included here.
2. Programs must be written for people to read, and onlyPrograms must be written for people to read, and only
incidentally for machines to execute.incidentally for machines to execute.
Abelson and SussmanAbelson and Sussman
... We are the masters. They are the slaves.... We are the masters. They are the slaves.
Yukihiro Matsumoto, creator of RubyYukihiro Matsumoto, creator of Ruby
on people and machineson people and machines
5. module Fooinizer
def fooinize()
self.split(" ").map{|t| t + "foo"}.join(" ")
end
end
# String.send(:include, Fooinizer)
class String
include Fooinizer
end
puts "my nifty string".fooinize
# => myfoo niftyfoo stringfoo
6. If you quack like a duck, you must be a duckIf you quack like a duck, you must be a duck
def print_size(item)
puts "This item size is #{item.size}"
end
# String
item = "This is string"
print_size(item) # => This item size is 14
# Array
item = %w(This item is array)
print_size(item) # => This item size is 4
#File
item = File::Stat.new("efficiency.rb")
print_size(item) # => This item size is 229
# Integer
item = 5
print_size(item) # => This item size is 8
7. No mutable data (== no side effects)
No state (== no hidden state)
Once assigned, “variable” doesn‘t change its
value
Pure mathematical functions, i.e. f(x) == f(x)
always, no matter how many times you run it
8. x = x + 1x = x + 1
x - x = 1x - x = 1
0 = 10 = 1
9. Programmer has a choice between imperative and functionalProgrammer has a choice between imperative and functional
# Imperative
days = %w(Mon Tue Wed)
days << "Thu"
days += ["Fri", "Sat", "Sun"]
days # ["Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"]
# Functional
days = %w(Mon Tue Wed)
all_days = days + ["Thu"] + ["Fri", "Sat", "Sun"]
all_days # ["Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"]
10. Functions are first-class citizens (can be passed andFunctions are first-class citizens (can be passed and
returned as other values)returned as other values)
# Passing a function
hello_proc = proc { puts "hello world!"}
def some_method(&some_proc)
some_proc.call
end
some_method &hello_proc # => hello world!
# Returning a function
def greeting_builder(*args)
proc { puts "Hello #{args.join(" ")}!" }
end
new_greeting = greeting_builder("Nifty", "Functional", "Ruby")
new_greeting.call # => Hello Nifty Functional Ruby!
11. Recall FoonizerRecall Foonizer
module Fooinizer
def fooinize()
self.split(" ").map{|t| t + "foo"}.join(" ")
end
end
# String.send(:include, Fooinizer)
class String
include Fooinizer
end
puts "my nifty string".fooinize
# => myfoo niftyfoo stringfoo
Higher order functions: mapHigher order functions: map
12. Code that writes codeCode that writes code
# Classic
class Car
def make
@make
end
def make=(value)
@make=value
end
end
# Metaprogramming - method defines method
class Car
attr_accessor :make # defines getter and setter
end
# Add methods to Car at runtime
Car.class_eval %{ attr_accessor :year }
c = Car.new()
puts c.respond_to? :year # => true
13. Define a Class with methods from within another ClassDefine a Class with methods from within another Class
class Definer
def self.build_custom_class(class_name, *methods)
methods.each do |m|
class_eval %{ class ::#{class_name}
attr_accessor :#{m}
end }
end
end
end
Definer.build_custom_class("Foo", "bar", "baz")
f = Foo.new
puts f.methods # => bar bar= baz baz=...
Functional programming is a programming paradigm that treats computation as the evaluation of mathematical functions and avoids state and mutable data. It emphasizes the application of functions, in contrast to the imperative programming style, which emphasizes changes in state.