Skip to content

Instantly share code, notes, and snippets.

@localshred
Last active August 29, 2015 14:21
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save localshred/35db417a6d4ba1fe19fe to your computer and use it in GitHub Desktop.
Save localshred/35db417a6d4ba1fe19fe to your computer and use it in GitHub Desktop.
Handling lists with higher-order functions
require "awesome_print"
##
# The term "higher-order" is meant to describe a function that
# takes other functions as arguments, produces a function as a return value,
# or both.
#
# ----> tl;dr use higher-order functions for working with lists as opposed to general "for loop" iteration.
#
# See also:
# + Ruby Enumerable: http://ruby-doc.org/core-2.2.2/Enumerable.html
# + JS Array: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array (note “experimental” icon next to es6 methods)
# + C# Linq Enumerable: https://msdn.microsoft.com/en-us/library/system.linq.enumerable(v=vs.111).aspx
A_HASH = {
:a => 1,
:b => 2,
:c => 3
}
PRIMES = [ 2, 3, 5, 7, 11, 13, 17, 19, 23, 29 ]
################################
##
## EACH :
## Input: An Enumerable
## Ouput: return value of last block invocation (don't use)
##
## Iterate through a list or hash, yielding each element
## to the block.
##
## Generally useful for side-effect operations (e.g. logging)
##
## Replaces general for loops.
##
################################
# "Old" way
#
# for (var i = 0; i < PRIMES.length; i++) do
# puts "I'm a prime!: #{PRIMES[i]}"
# end
# "New" way
PRIMES.each do |prime|
puts "I'm a prime!: #{prime}"
end
A_HASH.each_pair do |key, value|
puts "#{key} => #{value}"
end
################################
##
## MAP :
## Turn an a list of apples into oranges
##
## Input: An Enumerable
## Ouput: A different Enumerable of same size
##
## Iterates over a list, yielding each element to the block,
## and builds a new list out of the returned elements from the block
##
## Replaces initializing a new list, iterating some other list and pushing
## to the new list.
##
################################
# Old Way
squared_primes = []
PRIMES.each do |v|
squared_primes.push(v ** 2)
end
# New way
puts "Squared Primes"
squared_primes = PRIMES.map do |v|
v ** 2
end
ap(squared_primes)
fizzbuzz = (1..20).map do |i|
case
when i % 3 == 0 then "Fizz"
when i % 5 == 0 then "Buzz"
else i.to_s
end
end
puts "FizzBuzz"
ap(fizzbuzz)
################################
##
## SELECT :
## Find elements in a list that match some condition
##
## Input: An Enumerable
## Ouput: A sub-selection of items from the input, possibly an empty array.
##
## Iterates over a list, yielding each element to the block,
## and returns the elements for which the block returned a truthy value
##
## Replaces general loops with if/else/case statements in them.
##
################################
# Old way
evens = []
odds = []
(1..10).each do |v|
if v.odd?
odds.push(v)
else
evens.push(v)
end
end
# New way
range = (1..10)
evens = range.select { |v| v.even? }
odds = range.select { |v| v.odd? }
# or use Symbol#to_proc
evens = range.select(&:even?)
odds = range.select(&:odd?)
# Variant "any?" or "all"?
has_any_evens = false
range.each do |v|
if v.even?
has_any_evens = true
break
end
end
# or using Symbol#to_proc
has_any_evens = range.any?(&:even?)
are_all_even = range.all?(&:even?)
################################
##
## DETECT :
## Find ONE element in a list that matches some condition
##
## Input: An Enumerable
## Ouput: A single item from the input, or nil.
##
## Iterates over a list, yielding each element to the block,
## and returns the first element where the block returns truthy.
##
## Replaces general loops with if/else/case statements in them that
## intend to "Find" a single value in the array by some check.
##
################################
# Old way
value = nil
(1..10).each do |v|
if v * 10 == 100
value = v
break
end
end
# New way
value = (1..10).detect do |v|
(v * 10) == 100
end
################################
##
## REDUCE :
## Turn a list into any other kind of data type.
##
## Input: An Enumerable and an optional start value.
## Ouput: An object that was accumulated through all iterations.
##
## Iterates over a list with a start value of some kind (list, hash, number, etc),
## yielding the accumulated value _and_ each element to the block.
## The return value of the block becomes the accumulator for the first argument
## to the block in the next invocation.
## The final return value of the block determines the reduce function's return value.
##
## Replaces general loops that attempt to build an object from some list of values.
##
################################
# Old way
sum = 0
PRIMES.each do |prime|
sum += prime
end
ap(sum)
# New way
sum = PRIMES.reduce({}) do |accumulator, prime|
accumulator[prime] = prime ** 2
accumulator
end
ap(sum)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment