Lab: Higher-order Functions
In today's lab, you'll explore both sides of higher-order functions in Ruby. First you'll create your own higher-order function for processing a subset of elements in an array. Second you'll craft some calls to the map, filter, and fold functions in Ruby. Since Ruby doesn't technically have first-class functions, you'll use blocks to pass around code.
Take Through
Define in takethrough.rb
a higher-order function in Ruby named take_through
that collects up elements from an array until it encounters an element that meets some arbitrary criteria. It accepts an explicit array parameter and an implicit block parameter that returns true for the stopping element. It returns the subset of elements in a new array. Consider these example calls that demonstrate its behavior:
# Take numbers until we hit 8.
p take_through([10, 9, 8, 7, 5]) { |x| x == 8 }
# [10, 9, 8]
# Take letters from the alphabet until we hit one in "dog".
p take_through(('a'..'z').to_a) { |c| "dog".include?(c) }
# ['a', 'b', 'c', 'd']
# Take numbers until we exceed 10.
sum = 0
p take_through((1..50).to_a) { |x|
sum += x
sum > 10
}
# [1, 2, 3, 4, 5]
Ensure these three calls produce the expected results, and add a call of your own.
Map, Filter, and Fold
In calls.rb
, write short Ruby expressions that achieve the following tasks. Solve each with exactly one call to map
, filter
, or inject
. In some cases, Ruby might provide convenience functions that solve the problem more succinctly than these three. Don't use them. Also don't use each
, since its purpose is to achieve side-effects, not produce values.
teams
holding an array of arrays of player names, like [["Fern", "Wilbur", "Templeton"], ["Milo", "Addie", "Doc"]]
. Produce an array of just the first players of these teams, like ["Fern", "Milo"]
.files
. Produce true if all the files exist, and false otherwise. Using all?
is cheating.tokens
. Produce an array of just those strings whose first characters are the same as their last.message
. Produce an array of its characters' decimal ASCII values.entries
. Produce true if at least one of the strings is nil
, and false otherwise. Using any?
is cheating.[49, 5, 13]
represents 49 millions, 5 thousands, and 13 ones. Produce the full number. For example: 49005013.xs
. Produce a parallel array of strings representing the signs of these numbers. Positive numbers are represented as '+'
, negative as '-'
, and zeroes as '0'
.names
and bunglers
. Produce an array of those names who are not bunglers
.Each solution should be an expression that evaluates to the described value. Verify that your solutions work by adding code that prints the produced values. For example, here's how we would test a map operation that produces an array of successors:
xs = [1, 2, 3]
ys = xs.map { |x| x + 1 }
p ys
Do not print inside the blocks you pass to the higher-order functions.
Submit
To receive credit for this lab, you must submit your two Ruby scripts on Canvas by Monday noon. Late labs or forgot-to-submits are not accepted because Monday at noon is when your instructor has time to grade.