Functo
Composable method objects in ruby.
Usage
class AddsOne
include Functo.call :add, :number
def add
number + 1
end
end
AddsOne[1] # `.call` or `.()` also work
# => 2
class Multiplies
include Functo.call :multiply, :foo, :bar
def multiply
foo * bar
end
end
Multiplies[2, 3]
# => 6
Functo objects can be used in place of a Proc
.
[1, 2, 3].map(&AddsOne)
# => [2, 3, 4]
Use slurp
to splat array inputs.
[[1, 2], [3, 4], [5, 6]].map(&Multiplies.slurp)
# => [2, 12, 30]
Composition
MultipliesAddsOne = Multiplies >> AddsOne
MultipliesAddsOne[2, 3]
# => 7
>>
splats intermediate results. Use >
to compose without splatting intermediate results.
class SplitsDigits
include Functo.call :split, :number
def split
number.to_s.split(//).map(&:to_i)
end
end
class Sums
include Functo.call :sum, :arr
def sum
arr.reduce(:+)
end
end
SumsDigits = SplitsDigits >> Sums
SumsDigits[1066]
# => ArgumentError: wrong number of arguments (4 for 1)
SumsDigits2 = SplitsDigits > Sums
SumsDigits2[1066]
# => 13
Any object that responds to to_proc
can be made composable.
SquareRoots = Functo.wrap ->(n) { Math.sqrt(n) }
SquareRootsAddsOne = SquareRoots >> AddsOne
SquareRootsAddsOne[16]
# => 5.0
AddsOneStringifies = AddsOne >> Functo.wrap(&:to_s)
AddsOneStringifies[3]
# => "4"
Filters
class DividesTwo
include Functo.call :divide, number: ->(n) { Float(n) }
def divide
2 / number
end
end
DividesTwo['4']
# => 0.5
class DividesThree
include Functo.call :divide, number: :to_f
def divide
3 / number
end
end
DividesThree['4']
# => 0.75
A filter can be any object that responds to to_proc
, call
, or []
.
For example using dry-types.
require 'dry-types'
module Types
include Dry::Types.module
end
class Squares
include Functo.call :square, number: Types::Strict::Int
def square
number**2
end
end
Squares[4]
# => 16
Squares['4']
# => Dry::Types::ConstraintError: "4" violates constraints
Acknowledgements
Functo was inspired by:
- concord by mbj
- procto by snusnu
- dry-pipeline
Contributing
Bug reports and pull requests are welcome on GitHub at https://github.com/sbscully/functo.
License
The gem is available as open source under the terms of the MIT License.