Daitai (代替, Japanese for "alternative") is a functional library for Ruby language.
- Encourages Haskell's style of writing functions - the object you work on is the last parameter, so you can compose a sequence of operations on this object.
- Provides curried functions.
- Favors immutability.
- Eliminates side effects.
Add this line to your application's Gemfile:
gem 'daitai'And then execute:
$ bundleOr install it yourself as:
$ gem install daitai- abs
- add
- all
- always
- and
- any
- comparator
- compose
- concat
- cond
- dec
- divide
- equals
- false
- filter
- flip
- gt
- gte
- head
- identity
- inc
- init
- is
- is_nil
- last
- length
- lt
- lte
- map
- max
- mean
- median
- min
- modulo
- multiply
- negate
- not
- once
- or
- partition
- pipe
- product
- reduce
- reverse
- signum
- sort
- sort_by
- sort_with
- subtract
- sum
- tail
- tap
- true
- xor
Returns the absolute value of an argument.
Daitai.abs.(11) # => 11
Daitai.abs.(-8) # => 8Calculates the sum of two arguments.
Daitai.add.(3, 4) # => 7Checks if all elements of the list satisfy the predicate.
even = ->(x) { x % 2 == 0 }
Daitai.all.(even, [2, 4, 6, 8]) # => true
Daitai.all.(even, [2, 4, 7, 8]) # => falseCreates a function that always returns the provided value.
always_zero = Daitai.always.(0)
always_zero.(:one) # => 0
always_zero.(7, 8) # => 0
Daitai.map.(always_zero, [1, 2, 3, 4]) # => [0, 0, 0, 0]Boolean and - returns true if both arguments are true. Otherwise returns false.
Daitai.and.(true, true) # => true
Daitai.and.(true, false) # => false
Daitai.and.(false, true) # => false
Daitai.and.(false, false) # => falseChecks if at least one element of the list satisfies the predicate.
even = ->(x) { x % 2 == 0 }
Daitai.any.(even, [1, 2, 3, 5]) # => true
Daitai.any.(even, [1, 3, 5, 7]) # => falseCreates a comparator function based on a function which checks if the first argument is greater than the second one.
apple = { colour: 'red', weight: 136 }
banana = { colour: 'yellow', weight: 118 }
pear = { colour: 'green', weight: 178 }
weight_comparator = Daitai.comparator.(->(a, b) { a[:weight] > b[:weight]})
by_weight_decreasingly = Daitai.sort_with.(weight_comparator)
by_weight_decreasingly.([apple, banana, pear]) # => [pear, apple, banana]Applies one function to the result of another to produce a new function.
add_two = ->(x) { x + 2 }
square = ->(x) { x * x }
f = Daitai.compose.(square, add_two)
f.(10) # => 144Returns the result of concatenating provided lists or strings.
Daitai.concat.([1, 2], [3, 4]) # => [1, 2, 3, 4]
Daitai.concat.("Szcz", "ecin") # => "Szczecin"Takes a list of pairs consisted of a predicate and a transformer and returns a function which finds the first passing predicate and evaluates the corresponding transformer. Returns a nil if there is no matching predicate.
function = Daitai.cond.(
[Daitai.is.(String), Daitai.always.("It's a String!")],
[Daitai.is.(Symbol), Daitai.always.("It's a Symbol!")],
[Daitai.true, ->(unknown) { "I don't know what #{unknown} is."}]
)
function.("いただきます") # => "It's a String!"
function.(:env) # => "It's a Symbol!"
function.(3.14) # => "I don't know what 3.14 is."Returns the decremented value of a provided number.
Daitai.dec.(7) # => 6Calculates the quotient of two arguments.
Daitai.divide.(18, 6) # => 3Returns true if both arguments are equal. Otherwise returns false.
Daitai.equals.(7, 7) # => true
Daitai.equals.('7', 7) # => false
Daitai.equals.(%w[a b c], %w[a b c]) # => trueReturns a function that ignores all arguments and always returns false.
Daitai.false.() # => false
Daitai.false.(1, 2, 3) # => falseReturns a list of all elements that satisfy the predicate.
greater_than_two = ->(x) { x > 2 }
Daitai.filter.(greater_than_two, [1, 2, 3, 4]) # => [3, 4]
Daitai.filter.(greater_than_two, x: 2, y: 3, z: 5) # => { y: 3, z: 5 }
only_even = Daitai.filter.(->(x) { x % 2 == 0 })
only_even.([1, 2, 3, 4]) # => [2, 4]Returns a copy of a function with reversed order of the first two arguments.
concat = ->(x, y) { x + y }
flipped_concat = Daitai.flip.(concat)
flipped_concat.("flip", "flop") # => "flopflip"Checks if the first argument is greater than the second one.
Daitai.gt.(7, 5) # => true
Daitai.gt.(40, 40) # => false
Daitai.gt.(3.1, 3.14) # => falseChecks if the first argument is greater than or equal to the second one.
Daitai.gte.(7, 5) # => true
Daitai.gte.(40, 40) # => true
Daitai.gte.(3.1, 3.14) # => falseReturns the first element of a list.
Daitai.head.([1, 2, 3, 4]) # => 1
Daitai.head.("Ruby") # => "R"Returns exactly the provided value.
Daitai.identity.(1) # => 1
Daitai.identity.("Ruby") # => "Ruby"Returns the incremented value of a provided number.
Daitai.inc.(7) # => 8Returns all the elements of a list except the last one.
Daitai.init.([1, 2, 3, 4]) # => [1, 2, 3]
Daitai.init.("Ruby") # => "Rub"Checks if an argument is an instance of the provided type.
Daitai.is.(Numeric, 7.77) # => true
Daitai.is.(Float, 7.77) # => true
Daitai.is.(String, "Ruby") # => true
Daitai.is.(Regexp, /hello/) # => true
Daitai.is.(Hash, {}) # => true
Daitai.is.(Enumerable, {}) # => true
Daitai.is.(Object, {}) # => true
Daitai.is.(Numeric, {}) # => falseChecks if an argument is a nil.
Daitai.is_nil.(nil) # => true
Daitai.is_nil.(false) # => false
Daitai.is_nil.(0) # => falseReturns the last element of a list.
Daitai.last.([1, 2, 3, 4]) # => 4
Daitai.last.("Ruby") # => "y"Returns the length of a list.
Daitai.length.([1, 2, 3, 4]) # => 4
Daitai.length.("Ruby") # => 4Checks if the first argument is less than the second one.
Daitai.lt.(5, 7) # => true
Daitai.lt.(40, 40) # => false
Daitai.lt.(3.14, 3.1) # => falseChecks if the first argument is less than or equal to the second one.
Daitai.lte.(5, 7) # => true
Daitai.lte.(40, 40) # => true
Daitai.lte.(3.14, 3.1) # => falseApplies the function to all elements of the list and returns a new list of the results.
triple = ->(x) { x * 3 }
Daitai.map.(triple, [1, 2, 3, 4]) # => [3, 6, 9, 12]
Daitai.map.(triple, a: 10, b: 13) # => { a: 30, b: 39 }
increment = Daitai.map.(->(x) { x + 1 })
increment.([1, 2, 3, 4]) # => [2, 3, 4, 5]Returns the mean of a list.
Daitai.mean.([3, 4.5, 9]) # => 5.5
Daitai.mean.([6, 7]) # => 6.5
Daitai.mean.([]) # => NaNReturns the median of a list.
Daitai.median.([3.14, 4.5, 7.77]) # => 4.5
Daitai.median.([6, 7]) # => 6.5
Daitai.median.([]) # => NaNReturns the larger of two arguments.
Daitai.max.(6, 7) # => 7
non_negative = Daitai.max.(0)
non_negative.(-7) # => 0
non_negative.(11) # => 11Returns the smaller of two arguments.
Daitai.min.(6, 7) # => 6
non_positive = Daitai.min.(0)
non_positive.(-7) # => -7
non_positive.(11) # => 0Calculates the remainder after division of two arguments.
Daitai.modulo.(18, 7) # => 4Calculates the product of two arguments.
Daitai.multiply.(4, 3) # => 12Unary negation - returns a negated value of the argument.
Daitai.negate.(11) # => -11
Daitai.negate.(-8) # => 8Boolean not - returns a contradiction of the argument.
Daitai.not.(true) # => false
Daitai.not.(false) # => true
Daitai.not.('λ') # => false
Daitai.not.(nil) # => trueReturns a wrapped function which can be executed only once - no matter how many times it is called.
decrement = ->(x) { x - 1 }
decrement_once = Daitai.once.(decrement)
decrement_once.(8) # => 7
decrement_once.(40) # => 7
decrement_once.(decrement_once.(40)) # => 7Boolean or - returns true if at least one of the arguments is true. Otherwise returs false.
Daitai.or.(true, true) # => true
Daitai.or.(true, false) # => true
Daitai.or.(false, true) # => true
Daitai.or.(false, false) # => falseReturns a pair of lists of elements that do and do not satisfy the predicate.
greater_than_two = ->(x) { x > 2 }
Daitai.partition.(greater_than_two, [1, 2, 3, 4]) # => [[3, 4], [1, 2]]
Daitai.partition.(greater_than_two, x: 2, y: 3, z: 5) # => [{ y: 3, z: 5 }, { x: 2 }]
partition_numbers = Daitai.partition.(->(x) { x % 2 == 0 })
partition_numbers.([1, 2, 3, 4]) # => [[2, 4], [1, 3]]Performs a function composition from left to right and returns a new function.
add_two = ->(x) { x + 2 }
square = ->(x) { x * x }
f = Daitai.pipe.(square, add_two)
f.(10) # => 102Calculates the product of all elements of a list.
Daitai.sum.([1, 2, 3, 4]) # => 24Reduces the list using the function, from left to right, using the accumulator.
add = ->(x, y) { x + y }
Daitai.reduce.(add, 0, [1, 2, 3, 4]) # => 10
sum = ->(acc, (_, v)) { v + acc }
Daitai.reduce.(sum, 0, x: 2, y: 3, z: 5) # => 10
concat = Daitai.reduce.(add, "")
concat.(%w[l a m b d a]) # => "lambda"Returns the elements of a list in reverse order.
Daitai.reverse.([0, 5, 10, 15]) # => [15, 10, 5, 0]
Daitai.reverse.("raw desserts") # => "stressed war"Extracts the sign of an argument.
Daitai.signum.(11) # => 1
Daitai.signum.(0) # => 0
Daitai.signum.(-8) # => -1Returns a copy of the list sorted in the ascending order.
Daitai.sort.(diff, [2, 1, 4, 3]) # => [1, 2, 3, 4]
Daitai.sort.(%w[haskell ruby elixir]) # => ["elixir", "haskell", "ruby"]Returns a copy of the list sorted by the provided property - either a key of a Hash or a name of an Object's function.
apple = { colour: 'red', weight: 136 }
banana = { colour: 'yellow', weight: 118 }
pear = { colour: 'green', weight: 178 }
Daitai.sort_by.(:weight, [apple, banana, pear]) # => [banana, apple, pear]
sort_by_length = Daitai.sort_by.(:length)
sort_by_length.(%w[haskell ruby elixir] # => ["ruby", "elixir", "haskell"]Returns a sorted copy of the list according to the specified comparator function.
diff = ->(x, y) { x - y }
Daitai.sort.(diff, [2, 1, 4, 3]) # => [1, 2, 3, 4]
sort_by_length = Daitai.sort.(->(x, y) { x.length - y.length })
sort_by_length.(%w[haskell ruby elixir]) # => ["ruby", "elixir", "haskell"]Calculates the differce of two arguments.
Daitai.subtract.(9, 4) # => 5Calculates the sum of all elements of a list.
Daitai.sum.([1, 2, 3, 4]) # => 10Returns all the elements of a list except the first one.
Daitai.tail.([1, 2, 3, 4]) # => [2, 3, 4]
Daitai.tail.("Ruby") # => "uby"Executes the given function with the provided argument, then returns the argument.
logger = ->(x) { puts "the value is #{x}" }
Daitai.tap.(logger, 7)
# the value is 7
# => 7Returns a function that ignores all arguments and always returns true.
Daitai.true.() # => true
Daitai.true.(1, 2, 3) # => trueBoolean xor - returns true if only one of the arguments is true. Otherwise returs false.
Daitai.xor.(true, true) # => false
Daitai.xor.(true, false) # => true
Daitai.xor.(false, true) # => true
Daitai.xor.(false, false) # => falseAfter checking out the repo, run bin/setup to install dependencies. Then, run rake spec to run the tests. You can also run bin/console for an interactive prompt that will allow you to experiment.
To install this gem onto your local machine, run bundle exec rake install. To release a new version, update the version number in version.rb, and then run bundle exec rake release, which will create a git tag for the version, push git commits and tags, and push the .gem file to rubygems.org.
Bug reports and pull requests are welcome on GitHub at walerian777/daitai. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the Contributor Covenant code of conduct.
The gem is available as open source under the terms of the MIT License.
Everyone interacting in the Daitai project’s codebases, issue trackers, chat rooms and mailing lists is expected to follow the code of conduct.