Matty's Ultimate Gem
alias
Module
alias_singleton_method(new_name, old_name) => self
Makes new_name a new copy of the instance method old_name. This can be used to retain access to instance methods that are overridden.
Examples
require 'mug/alias'
module Mod
def self.foo
1
end
alias_singleton_method :bar, :foo
def self.foo
2
end
end
Mod.foo #=> 2
Mod.bar #=> 1
and-or
Object
obj.and default
obj.and default {|o| block }
Returns either obj or default, depending on the falsiness of obj.
If a block is given, obj is yielded to it; if it returns truthy, default is returned, otherwise obj is returned.
obj.or default
obj.or default {|o| block }
Returns either obj or default, depending on the truthiness of obj.
If a block is given, obj is yielded to it; if it returns truthy, obj is returned, otherwise default is returned.
obj.and_then {|o| block }
Calls block if obj is truthy.
Returns obj.
obj.or_then {|o| block }
Calls block if obj is falsey.
Returns obj.
Examples
require 'mug/and-or'
data_store.get_env_hash.or(default_hash).do_something
get_a_list.and(default_list, &:empty?).do_something
try_thing.and_then {|result| log "got #{result.inspect}" }
try_thing.or_then { log "failed" }
apply
Proc
proc.apply *args
Curries this Proc and partially applies parameters. If a sufficient number of arguments are supplied, it passes the supplied arguments to the original proc and returns the result. Otherwise, returns another curried proc that takes the rest of arguments.
Method
meth.curry
meth.curry n
Returns a curried proc. If the optional arity argument is given, it determines the number of arguments. A curried proc receives some arguments. If a sufficient number of arguments are supplied, it passes the supplied arguments to the original proc and returns the result. Otherwise, returns another curried proc that takes the rest of arguments.
meth.apply *args
Curries this Method and partially applies parameters. If a sufficient number of arguments are supplied, it passes the supplied arguments to the original proc and returns the result. Otherwise, returns another curried proc that takes the rest of arguments.
array/delete_all
Array
array.delete_all {|item| block } => array
array.delete_all => Enumerator
Deletes every element of self
for which block evaluates to true
.
Returns an array of the deleted elements.
If no block is given, an Enumerator is returned instead.
See #delete_if, #reject!
array/extend
Array
array.extend!(size=0, obj=nil)
array.extend!(array)
array.extend!(size) {|index| block }
Extend this Array.
In the first form, when a size and an optional obj are sent, the array is extended with size copies of obj. Take notice that all elements will reference the same object obj.
The second form appends a copy of the array passed as a parameter
(the array is generated by calling #to_ary
on the parameter).
See also: #concat
, #+
In the last form, the array is extended by the given size. Each new element in the array is created by passing the element's index to the given block and storing the return value.
array.extend(size=0, obj=nil)
array.extend(array)
array.extend(size) {|index| block }
See #extend!
array/minus
Array
array.minus(ary, remainder: false)
Subtract elements from this array.
This is similar to Array#-
except that elements from this array are
removed only once per instance in ary.
If remainder is given and true, returns a second array which is all elements in ary that were not present in this array.
array ^ other
Get the elements unique to one of two arrays.
Duplicates in either array are included only once.
array/samples
Array
array.samples(min: int, max: int, random: rng) => new_ary
Choose a random subset of elements from the array.
The elements are chosen by using random and unique indices into the array in order to ensure that an element doesn't repeat itself unless the array already contained duplicate elements.
The optional min and max arguments restrict the size of the returned array. min must be >= 0, and max must be >= min. (Both values are clamped to the size of the array.)
If the array is empty, always returns an empty array.
The optional random argument will be used as the random number generator.
array/to_proc
Array
array.to_proc => proc {|args..| ...}
Returns a Proc that accepts one or two arguments.
The Proc's parameter is used as an index into this array.
See: #slice
bittest
Integer
int.and?(other, test: :any)
Tests common bits in this AND other.
test:
-
:any
=> true if any bits are set -
:all
=> true if all bits are set
int.and_any?(other)
True if this AND other is non-zero.
i.e. if any set bits in other are set in this.
int.and_all?(other)
True if this AND other is other.
i.e. if all set bits in other are set in this.
int.or?(other)
True if this OR other is non-zero.
int.xor?(other)
True if this XOR other is non-zero.
bool
Kernel
Bool(obj)
Returns the truthiness of obj, as either True or False.
This is functionally equivalent to calling !!obj
Object
obj.to_b
Converts obj to a boolean using "typical" C-like conversion rules.
The following values all become false:
-
0
,0.0
, etc. (any numeric zero) Float::NAN
""
-
[]
,{}
, etc. (any Enumerable or Enumerator with no elements) - any Exception
All others values become true.
obj.to_bool
Returns the truthiness of obj, as either True or False.
This is functionally equivalent to calling !!obj
Examples
require 'mug/bool'
Bool(obj) #=> !!obj
obj.to_bool #=> !!obj
obj.to_b #=> C-like truthiness
clamp
Clamps a number to a range.
Numeric
num.clamp lower, higher => new_num
Clamps num so that lower <= new_num <= higher.
Returns lower when num < lower, higher when num > higher, otherwise num itself.
Raises an exception if lower > higher
num.clamp range => new_num
Effectively calls range#bound
Range
rng.bound val => new_val
Bounds val so that first <= new_val <= last.
Returns first when val < first, last when val > last, otherwise val itself.
Raises an exception if val >= end and the range is exclusive.
diggable
Implements #dig for any object that implements #[]
Diggable
Extend any class or object that implements a #[]
method, to
also have #dig
diggy.dig *idx
Extracts the nested value specified by the sequence of idx
objects by
calling dig
at each step, returning nil
if any intermediate step is
nil
.
enumerable/any-and-all
Enumerable
enum.any_and_all? {|obj| block }
Passes each element of the collection to the given block. The method returns true
if the
block contains elements that never return false
or nil
. If the block is not given, Ruby
adds an implicit block of { |obj| obj }
which will cause any_and_all?
to return true
when none of the collection members are false
or nil
.
enumerable/chain
Enumerable
Enumerable.chain(*enums)
Enumerable.chain(*enums) {|...| block }
Invokes a block once for every element in a sequence of Enumerables.
WARNING: Enumerable\#chain
defined since Ruby 2.6 is incompatible with this gem when used with args and a block
enum.chain(*enums)
enum.chain(*enums) {|...| block }
Creates a chain of Enumerables following this one, and invokes a block once for each element of each Enumerable.
enumerable/counts
Returns counts of objects in enumerables.
Enumerable
enum.counts
Returns a hash of item=>count
showing how many
of each item are in this Enumerable.
enum.counts_by {|item| block }
Passes each element in turn to the block, and returns a
hash of result=>count
.
If no block is given, an enumerator is returned.
Examples
require 'mug/enumerable/counts'
%w(a b b).counts #=> {'a'=>1, 'b'=>2}
%w(a b b).counts_by{|o| o.upcase } #=> {'A'=>1, 'B'=>2}
enumerable/hash-like
Makes Enumerables quack a bit more like a hash. A lot of these will not work on indeterminate or infinite sequences.
Enumerable
each_pair {| key, value | block } => hsh
each_pair => an_enumerator
Calls block
once for each key in the enum, passing the key-value pair as parameters.
If no block is given, an enumerator is returned instead.
each_key {| key | block } => hsh
each_key => an_enumerator
Calls block
once for each key in the enum, passing the key as a parameter.
If no block is given, an enumerator is returned instead.
fetch(key [, default] ) => obj
fetch(key) { |key| block } => obj
Returns a value from the enum for the given key. If the key can't be
found, there are several options: With no other arguments, it will
raise a KeyError
exception; if default
is given, then that will
be returned; if the optional code block is specified, then that will
be run and its result returned.
fetch_values(key, ...) => array
fetch_values(key, ...) { |key| block } => array
Returns an array containing the values associated with the given keys
but also raises KeyError
when one of keys can't be found.
Also see #values_at
and #fetch
.
key?(key) => true or false
Returns true
if the given key is present in this enum.
keys => array
Returns a new array populated with the keys from this enum.
length => integer
Returns the number of key-value pairs in the hash.
member?(key) => true or false
Returns true if the given key is present in this enum.
slice(*keys) => a_hash
Returns a hash containing only the given keys and their values.
transform_keys {|key| block } => new_hash
transform_keys => an_enumerator
Returns a new hash with the results of running the block once for every key. If no block is given, an enumerator is returned instead.
transform_values {|value| block } => new_hash
transform_values => an_enumerator
Returns a new hash with the results of running the block once for every value. If no block is given, an enumerator is returned instead.
value?(value) => true or false
Returns true
if the given value is present for some key.
values => array
Returns a new array populated with the values from this enum.
values_at(key, ...) => array
Return an array containing the values associated with the given keys.
fragile-method-chain
Defines a fragile method chain. If any method call in the chain returns a falsy value, the chain aborts.
require 'mug/fragile-method-chain'
# Similar to: a.b && a.b.c
# except that a.b is not called twice
a._?.b.c._!
# Also works with #[] method
nested_hash._?[:a][:b][:c]._!
hash/fetch-assign
Hash
hsh.fetch_assign(key, default) => obj
hsh.fetch_assign(key) {|key| block } => obj
Returns a value from the hash for the given key. If the key can't be found, there are several options: if default is given, then that will be stored and returned; if the optional code block is specified, then that will be run and its result stored and returned.
(#compute_if_absent
is an alias of this method)
require 'mug/hash/fetch-assign'
hsh = {}
hsh.fetch_assign(:a, 1) # => 1
# hsh => {:a => 1}
hsh.fetch_assign(:a, 42) # => 1
# hsh => {:a => 1}
hsh.fetch_assign(:b) {|key| key.to_s } #=> "b"
# hsh => {:a => 1, :b => "b"}
hash/map
Hash
hsh.map_values {|v| block }
Returns a new hash which is a copy of hsh but each value is replaced by the result of running it through block.
As of Ruby 2.4 this is equivalent to #transform_values
require 'mug/hash/map'
{'a'=>1, 'b'=>2}.map_values { |v| v*2 } #=> {'a'=>2, 'b'=>4}
{'a'=>1, 'b'=>2}.map_values { "cat" } #=> {'a'=>"cat", 'b'=>"cat"}
hsh.map_values! {|v| block }
Replaces the values in hsh by running them each through block.
As of Ruby 2.4 this is equivalent to #transform_values!
See: #map_values
hsh.map_keys {|k| block }
Returns a new hash which is a copy of hsh but each key is replaced by the result of running it through block.
If block returns duplicate keys, they will be overwritten in the resulting hash.
As of Ruby 2.5 this is equivalent to #transform_keys
require 'mug/hash/map'
{'a'=>1, 'b'=>2}.map_keys { |k| k*2 } #=> {'aa'=>1, 'bb'=>2}
{'a'=>1, 'b'=>2}.map_keys { "cat" } #=> {'cat'=>2}
hsh.map_keys! {|k| block }
Replaces the keys in hsh by running them each through block.
If block returns duplicate keys, they will be overwritten in turn.
As of Ruby 2.5 this is equivalent to #transform_keys!
See: #map_keys
hsh.map_pairs {|k, v| block }
Returns a new hash which is a copy of hsh but each key-value pair is replaced by the result of running it through block.
If block returns duplicate keys, they will be overwritten in the resulting hash.
require 'mug/hash/map'
{'a'=>1, 'b'=>2}.map_pairs { |k,v| [k*2, v+1] } #=> {'aa'=>2, 'bb'=>3}
{'a'=>1, 'b'=>2}.map_pairs { ["cat","dog"] } #=> {'cat'=>'dog'}
hsh.map_pairs! {|k, v| block }
Replaces the keys and values in hsh by running them each through block.
If block returns duplicate keys, they will be overwritten.
See: #map_pairs
hash/merge
Hash
hsh.merge_left other_hash => new_hash
Returns a new hash containing the contents of other_hash and the contents of hsh. The value for each duplicate key is the value in hsh when it exists.
hsh.merge_right other_hash => new_hash
Returns a new hash containing the contents of other_hash and the contents of hsh. The value for each duplicate key is the value in other_hash when it exists.
hsh.merge_left! other_hash => hsh
Adds the contents of other_hash to hsh. Entries with duplicate keys are overwritten with the values from other_hash if the values in hsh are nil.
hsh.merge_right! other_hash => hsh
Adds the contents of other_hash to hsh. Entries with duplicate keys are overwritten with the values from other_hash unless the values in other_hash are nil.
hash/operations
Hash
hsh | other_hsh
Returns a new Hash, whose value is the same as this one, with any extras in other_hash added in.
Useful for default options.
require 'mug/hash/operations'
def foo options={}
options | {b: 2, c: 2}
end
foo a: 1, b: 1 # => {:a=>1, :b=>1, :c=>2}
hsh + other_hsh
Adds the contents of other_hash to hsh. Entries with duplicate keys are overwritten with the values from other_hash
require 'mug/hash/operations'
a = {a: 1, b: 1}
b = {b: 2, c: 2}
a + b # => {:a=>1, :b=>2, :c=>2}
b + a # => {:a=>1, :b=>1, :c=>2}
hsh << o
Appends stuff to the hash.
- If o is a Hash, this is identical to calling #merge!
- If o is an Array with two elements, it is interpreted as [key,value]
- If o can be converted to a hash with #to_h, this is identical to calling #merge!
- Otherwise an ArgumentError is raised.
require 'mug/hash/operations'
h = {}
h << {:a=>0} # h = {:a=>0}
h << {:b=>2,:c=>3} # h = {:a=>0,:b=>2,:c=>3}
h << [:a,1] # h = {:a=>1,:b=>2,:c=>3}
hash/when
Use a Hash like a case statement.
case key
when /foo/ then "FOO"
when /bar/ then "BAR"
else "DEFAULT"
end
becomes:
h = {
/foo/ => "FOO",
/bar/ => "BAR",
}
h.default = "DEFAULT"
h.when key
iff
Object
obj.iff? condition
obj.iff? { condition }
Test for logical equivalence.
Returns true if condition
and obj
are either
both truthy, or both falsey.
iterator
Iterator
A special class of Enumerator that repeatedly yields values to a block.
The initial yielded value is given in the constructor, but in subsequent iterations the result of the previous iteration is yielded.
new(initial, *args) { |obj, *args| ... }
new(initial, method=:each, *args)
Creates a new Iterator object, which can be used as an Enumerable.
In the first form, iteration is defined by the given block, to which the current object and any other args are yielded.
In the second, deprecated, form, a generated Iterator sends the given method with any +args+ to the iterand.
Use of this form is discouraged. Use Object#iter_for or Method#to_iter instead.
iterator/for
Object
obj.iter_for(meth, *args)
Creates an Iterator object, which is a subclass of Enumerator that recursively invokes a method on an object.
Initially the receiving object is obj. After each iteration, the receiving object is replaced with the result of the previous iteration.
require 'mug/iterator/for'
0.iter_for(:next).take(5) #=> [1,2,3,4,5]
0.iter_for(:+,2).take(5) #=> [2,4,6,8,10]
iterator/method
Method
meth.to_iter(*args)
Creates an Iterator object, which is a subclass of Enumerator that recursively invokes meth on an object.
Initially the receiving object is the object on which meth is defined. After each iteration, the receiving object is replaced with the result of the previous iteration.
require 'mug/iterator/method'
0.method(:next).to_iter.take(5) #=> [1,2,3,4,5]
0.method(:+).to_iter(2).take(5) #=> [2,4,6,8,10]
loop-with
Kernel
loop_with_index(offset=0) {|i| block }
Repeatedly executes the block, yielding the current iteration count, which starts from offset. If no block is given, returns an Enumerator.
loop_with_object(obj) {|o| block }
Repeatedly executes the block, yielding an arbitrary object, obj.
Examples
require 'mug/loop-with'
loop_with_index do |i|
p i
break
end
arr = loop_with_object([]) do |a|
s = gets.chomp
throw StopIteration if s.empty?
a << s
end
main
Kernel
__main__
__main__ { block }
Compares the calling source filename with $PROGRAM_NAME
($0
).
Returns a falsey value if the calling context is not in the 'main' file.
If called without a block, and the calling context is in the 'main' file,
returns true
.
If called with a block, and the calling context is in the 'main' file, the block is executed and the result is returned.
Examples
require 'mug/main'
if __main__
puts "the main file"
end
__main__ do
puts "also the main file"
end
# More advanced example:
if __main__ { ARGV[0] == 'foo' }
do_foo
end
matchdata/each
MatchData
md.each
md.each { |str| block }
Iterates over each capture group in the MatchData object,
including $&
(the entire matched string), yielding the
captured string.
md.each_capture
md.each_capture {|key, str| block }
Iterates over each capture group in the MatchData object, yielding the capture position and captured string.
The capture positions are either all Strings or all Integers, depending on whether the original Regexp had named capture groups or not.
md.each_named_capture
md.each_named_capture {|name, str| block }
Iterates over each named capture group in the MatchData object, yielding the capture name and string.
md.each_positional_capture(include_names: false)
md.each_positional_capture(include_names: false) {|name, str| block }
Iterates over each positional capture group in the MatchData object, yielding the capture position and string.
If include_names
is given and true, treats named captures
as positional captures.
WARNING: if mixing named and positional captures, no positional captures will be available using this method!
matchdata/hash
MatchData
md.to_h
Returns a Hash object of capture position => captured string.
The capture positions are either all Strings or all Integers, depending on whether the original Regexp had named capture groups or not.
md.named_captures
Returns a Hash object of capture name => captured string.
md.positional_captures(include_names: false)
Returns a Hash object of capture position => captured string.
If include_names
is given and true, treats named captures
as positional captures.
WARNING: if mixing named and positional captures, no positional captures will be available using this method!
maybe
Object
obj.maybe
obj.maybe { block }
Invokes a method on obj iff obj is truthy, otherwise returns obj.
When a block is given, the block is invoked in the scope of obj (i.e. self
in the block refers to obj).
When no block is given, maybe returns an object that conditionally delegates methods to obj.
require 'mug/maybe'
# Equivalent to: a && a.b && a.b.c
# except that a and b are only invoked once
# (block form)
a.maybe{ b.maybe{ c } }
# (delegator form)
a.maybe.b.maybe.c
negativity
Numeric
num.negative?
If num is negative (i.e. < 0), returns itself, otherwise returns nil.
num.positive?
If num is positive (i.e. > 0), returns itself, otherwise returns nil.
num.nonnegative?
If num is nonnegative (i.e. >= 0), returns itself, otherwise returns nil.
num.nonpositive?
If num is nonpositive (i.e. <= 0), returns itself, otherwise returns nil.
Examples
require 'mug/negativity'
if i.negative?
puts "#{i} = 0 - #{-i}"
end
n.positive? or raise('not enough items')
x.nonnegative? || -x
arr.map{|i| i.nonpositive? }.compact
not
Kernel
obj.not
obj.not {|o| block }
obj.not(*a)
obj.not(*a) {|o| block }
Negate a predicate.
Examples
require 'mug/not'
false.not #=> true
true.not #=> false
[].not &:empty? #=> false
[1].not :empty? #=> true
[1,-2,3].not(:all?) {|e| e > 0 } #=> true
rexproc
Regexp
rex.to_proc
Returns a proc that accepts one argument, that matches against this regexp object.
require 'mug/rexproc'
%w[foo bar baz].select &/\Ab/ #=> ["bar", "baz"]
%w[foo bar baz].reject &/\Ab/ #=> ["foo"]
%w[foo bar baz].find &/\Ab/ #=> "bar"
self
Object
obj.self
obj.self {|o| block }
obj.itself
obj.itself {|o| block }
When a block is given, yields obj to the block and returns the resulting value.
When no block is given, simply returns obj.
Note: this is different from
#tap
becauseobj.tap{nil}
returns obj, butobj.self{nil}
returns nil.
require 'mug/self'
1.self #=> 1
obj.self #=> obj
2.self{|i| i*3 } #=> 6
[1,1,2,2,3].group_by(&:self) #=> {1=>[1,1], 2=>[2,2], 3=>[3]}
1.itself #=> 1
obj.itself #=> obj
2.itself{|i| i*3 } #=> 6
[1,1,2,2,3].group_by(&:itself) #=> {1=>[1,1], 2=>[2,2], 3=>[3]}
obj.revapply(*args) {|*list| block }
obj.cede(*args) {|*list| block }
obj.revapply(*args)
obj.cede(*args)
When a block is given, yields obj and any args to the block and returns the resulting value.
When no block is given, returns an Enumerator.
tau
Defines the true circle constant.
Math::TAU #= 6.283185307179586..
Additionally it expands the BigDecimal/BigMath module:
require 'bigdecimal'
require 'bigdecimal/math'
include BigMath
puts TAU(15)
See http://tauday.com to find out what it's all about.
time
Time
t.to_now
Returns the number of seconds since the time represented by this Time object.
start = Time.now
#...
duration = start.to_now
t.from_now
Returns the number of seconds until the time represented by this Time object.
target = Time.new 2117, 1, 1, 0, 0, 0
sleep target.from_now
Time.until t
Returns the number of seconds until t
.
Time.since t
Returns the number of seconds since t
.
to_h
Removed
Note: for Ruy 2.1,
Enumerable#to_h
is already defined.
Note: for Ruby <2.0, it is advisable to instead use the to_h gem.
top
Enumerable
enum.top(n=1)
enum.top(n=1) {|a,b| block }
Get the top n items, in order from top to bottom.
Returns an Array even when n is 1.
See: Enumerable#sort
enum.top_by(n=1) {|item| block }
Get the top n items, in order from top to bottom, ordered by mapping the values through the given block.
Returns an Array even when n is 1. Values that are tied after mapping are returned in the initial order.
If no block is given, an enumerator is returned instead.
See: Enumerable#sort_by
enum.bottom(n=1)
enum.bottom(n=1) {|a,b| block }
Get the bottom n items, in order from bottom to top.
Returns an Array even when n is 1.
See: Enumerable#sort
enum.bottom_by(n=1) {|item| item }
Get the bottom n items, in order from bottom to top, ordered by mapping the values through the given block.
Returns an Array even when n is 1. Values that are tied after mapping are returned in the initial order.
If no block is given, an enumerator is returned instead.
See: Enumerable#sort_by
with
Kernel
with(*args) {|*foo| block }
Yields the arguments to a block.
with(1, 2, 3) {|x, y, z| x + y + z }
#=> 6