On Github bjoska / functional_programming_in_an_object_oriented_world
f(x)
fn(x) = x * 25 / 100
function fn(x) { return x * 25 / 100; }(Javascript)
def add_to_shopping_cart(item) self.items << item self.total += item.value self.total end
(Ruby)
def add_to_shopping_cart(item) self.items << item end def total sum = 0 for item in items do sum += item.value end sum end
(Ruby)
def add_to_shopping_cart(item) self.items << item log("Item added to cart: #{item.sku}") end
(Ruby)
class Invoice < ActiveRecord::Base # ORM class belongs_to :customer def issue customer.add_amount(self.amount) self.status = 'Issued' customer.total end end
(Ruby)
class Customer < ActiveRecord::Base has_many :invoices def total_amount invoices.where(status: 'Issued').reduce(0) do |total, invoice| total += invoice.amount total end end end class Invoice < ActiveRecord::Base belongs_to :customer def issue self.status = 'Issued' end end
(Ruby)
So we fixed the side effects, but at what cost?
"We can handle latency as we do in life." - Aslam Khan
def add_to_shopping_cart(item) self.items << item self.items end
(Ruby)
def add_item_to_shopping_cart(shopping_cart, item) shopping_cart.add item shopping_cart end
(Ruby)
def add_item_to_shopping_cart(shopping_cart, item) # Dirty hack to deep copy an object in Ruby shopping_cart = Marshal.load(Marshal.dump(shopping_cart)) shopping_cart.add item shopping_cart end
(Ruby)
next_value() { this.n += 1; return this.n; }
(Javascript)
next_value(current_int) { return current_int + 1; }
(Javascript)
Blowing the stack
Tail Call Optimisation
function sum(numbers) { if(numbers.length == 0) { return 0; } return numbers[0] + sum(numbers.slice(1)); }
(Javascript)
function sum(acc, numbers) { if(numbers.length == 0) { return acc; } return sum(acc + numbers[0], numbers.slice(1)); }
(Javascript)
Functions that take functions
function sum(acc, numbers) { if(numbers.length == 0) { return acc; } return sum(acc + numbers[0], numbers.slice(1)); }
(Javascript)
function reduce(acc, collection, fn) { if(collection.length == 0) { return acc; } return reduce(fn(acc, collection[0]), collection.slice(1), fn); } function sum(numbers) { return reduce(0, numbers, function(a, b) { return a + b; }); } function count(numbers) { return reduce(0, numbers, function(a, _) { return a + 1; }); }
(Javascript)