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:
$ bundle
Or 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) # => 8
Calculates the sum of two arguments.
Daitai.add.(3, 4) # => 7
Checks 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]) # => false
Creates 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) # => false
Checks 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]) # => false
Creates 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) # => 144
Returns 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) # => 6
Calculates the quotient of two arguments.
Daitai.divide.(18, 6) # => 3
Returns 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]) # => true
Returns a function that ignores all arguments and always returns false
.
Daitai.false.() # => false
Daitai.false.(1, 2, 3) # => false
Returns 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) # => false
Checks 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) # => false
Returns 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) # => 8
Returns 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, {}) # => false
Checks if an argument is a nil
.
Daitai.is_nil.(nil) # => true
Daitai.is_nil.(false) # => false
Daitai.is_nil.(0) # => false
Returns 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") # => 4
Checks 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) # => false
Checks 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) # => false
Applies 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.([]) # => NaN
Returns the median of a list.
Daitai.median.([3.14, 4.5, 7.77]) # => 4.5
Daitai.median.([6, 7]) # => 6.5
Daitai.median.([]) # => NaN
Returns the larger of two arguments.
Daitai.max.(6, 7) # => 7
non_negative = Daitai.max.(0)
non_negative.(-7) # => 0
non_negative.(11) # => 11
Returns the smaller of two arguments.
Daitai.min.(6, 7) # => 6
non_positive = Daitai.min.(0)
non_positive.(-7) # => -7
non_positive.(11) # => 0
Calculates the remainder after division of two arguments.
Daitai.modulo.(18, 7) # => 4
Calculates the product of two arguments.
Daitai.multiply.(4, 3) # => 12
Unary negation - returns a negated value of the argument.
Daitai.negate.(11) # => -11
Daitai.negate.(-8) # => 8
Boolean not
- returns a contradiction of the argument.
Daitai.not.(true) # => false
Daitai.not.(false) # => true
Daitai.not.('λ') # => false
Daitai.not.(nil) # => true
Returns 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)) # => 7
Boolean 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) # => false
Returns 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) # => 102
Calculates the product of all elements of a list.
Daitai.sum.([1, 2, 3, 4]) # => 24
Reduces 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) # => -1
Returns 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) # => 5
Calculates the sum of all elements of a list.
Daitai.sum.([1, 2, 3, 4]) # => 10
Returns 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
# => 7
Returns a function that ignores all arguments and always returns true
.
Daitai.true.() # => true
Daitai.true.(1, 2, 3) # => true
Boolean 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) # => false
After 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.