mug 0.5.3 → 0.5.4
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/mug/and-or.rb +26 -26
- data/lib/mug/any-and-all.rb +16 -16
- data/lib/mug/apply.rb +37 -37
- data/lib/mug/array/extend.rb +43 -43
- data/lib/mug/array/minus.rb +32 -32
- data/lib/mug/bool.rb +71 -71
- data/lib/mug/clamp.rb +35 -35
- data/lib/mug/counts.rb +27 -27
- data/lib/mug/fragile-method-chain.rb +42 -42
- data/lib/mug/hash/map.rb +75 -75
- data/lib/mug/hash/operations.rb +47 -47
- data/lib/mug/iterator/for.rb +7 -7
- data/lib/mug/iterator/method.rb +7 -7
- data/lib/mug/iterator_c.rb +14 -14
- data/lib/mug/loop-with.rb +30 -29
- data/lib/mug/matchdata/each.rb +40 -40
- data/lib/mug/matchdata/hash.rb +29 -29
- data/lib/mug/maybe.rb +33 -33
- data/lib/mug/negativity.rb +20 -20
- data/lib/mug/not.rb +6 -6
- data/lib/mug/rexproc.rb +6 -6
- data/lib/mug/self.rb +31 -31
- data/lib/mug/to_h.rb +2 -2
- data/lib/mug/top.rb +100 -100
- data/test/test-and-or.rb +32 -32
- data/test/test-any-and-all.rb +19 -19
- data/test/test-apply.rb +47 -47
- data/test/test-array-extend.rb +54 -54
- data/test/test-array-minus.rb +11 -11
- data/test/test-bool.rb +48 -48
- data/test/test-clamp.rb +42 -42
- data/test/test-counts.rb +21 -21
- data/test/test-fragile-method-chain.rb +56 -56
- data/test/test-hashmap.rb +14 -14
- data/test/test-hashop.rb +47 -47
- data/test/test-iterator-for.rb +12 -12
- data/test/test-loop-with.rb +117 -66
- data/test/test-matchdata_each.rb +50 -50
- data/test/test-matchdata_hash.rb +40 -40
- data/test/test-maybe.rb +76 -76
- data/test/test-negativity.rb +40 -40
- data/test/test-not.rb +53 -53
- data/test/test-rexproc.rb +6 -6
- data/test/test-self.rb +21 -21
- data/test/test-tau.rb +12 -12
- data/test/test-top.rb +100 -100
- metadata +4 -4
data/lib/mug/clamp.rb
CHANGED
@@ -1,46 +1,46 @@
|
|
1
1
|
|
2
2
|
class Numeric
|
3
3
|
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
4
|
+
#
|
5
|
+
# Clamps num so that lower <= new_num <= higher.
|
6
|
+
#
|
7
|
+
# Returns lower when num < lower, higher when num > higher, otherwise
|
8
|
+
# num itself.
|
9
|
+
#
|
10
|
+
# Raises an exception if lower > higher
|
11
|
+
#
|
12
|
+
def clamp lower, higher=nil
|
13
|
+
return lower.bound(self) if lower.is_a?(Range) && higher.nil?
|
14
|
+
raise ArgumentError, 'range must not be negative' if lower > higher
|
15
|
+
[[lower, self].max, higher].min
|
16
|
+
end
|
17
17
|
|
18
18
|
end
|
19
19
|
|
20
20
|
class Range
|
21
21
|
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
22
|
+
#
|
23
|
+
# Bounds val so that first <= new_val <= last.
|
24
|
+
#
|
25
|
+
# Returns first when val < first, last when val > last, otherwise
|
26
|
+
# val itself.
|
27
|
+
#
|
28
|
+
# Raises an exception if val >= end and the range is exclusive.
|
29
|
+
#
|
30
|
+
def bound val
|
31
|
+
a = first
|
32
|
+
return a if val < a
|
33
|
+
|
34
|
+
b = last
|
35
|
+
if val >= b
|
36
|
+
if exclude_end?
|
37
|
+
raise ArgumentError, 'more than or equal to the exclusive range'
|
38
|
+
end
|
39
|
+
return b
|
40
|
+
end
|
41
|
+
|
42
|
+
val
|
43
|
+
end
|
44
44
|
|
45
45
|
end
|
46
46
|
|
data/lib/mug/counts.rb
CHANGED
@@ -1,34 +1,34 @@
|
|
1
1
|
|
2
2
|
module Enumerable
|
3
3
|
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
4
|
+
#
|
5
|
+
# Returns a hash of item=>count showing how many
|
6
|
+
# of each +item+ are in this Enumerable.
|
7
|
+
#
|
8
|
+
def counts &block
|
9
|
+
return counts_by(&block) if block_given?
|
10
|
+
hsh = Hash.new{|h,k| h[k] = 0 }
|
11
|
+
each do |k|
|
12
|
+
hsh[k] += 1
|
13
|
+
end
|
14
|
+
hsh
|
15
|
+
end
|
16
16
|
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
17
|
+
#
|
18
|
+
# Passes each element in turn to the block, and returns a
|
19
|
+
# hash of result=>count.
|
20
|
+
#
|
21
|
+
# If no block is given, an enumerator is returned.
|
22
|
+
#
|
23
|
+
def counts_by &block
|
24
|
+
return enum_for(:counts_by) unless block_given?
|
25
|
+
hsh = Hash.new{|h,k| h[k] = 0 }
|
26
|
+
each do |j|
|
27
|
+
k = yield j
|
28
|
+
hsh[k] += 1
|
29
|
+
end
|
30
|
+
hsh
|
31
|
+
end
|
32
32
|
|
33
33
|
end
|
34
34
|
|
@@ -8,55 +8,55 @@
|
|
8
8
|
# nested_hash._?[:a][:b][:c]._!
|
9
9
|
#
|
10
10
|
class FragileMethodChain
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
11
|
+
#
|
12
|
+
# Creates a FragileMethodChain which will send its first method to +o+
|
13
|
+
#
|
14
|
+
def initialize o, falsy: true
|
15
|
+
@o = o
|
16
|
+
@falsy = falsy
|
17
|
+
end
|
18
18
|
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
19
|
+
#
|
20
|
+
# Finalises the FragileMethodChain.
|
21
|
+
#
|
22
|
+
# The final result will be the first +nil+ or +false+ value
|
23
|
+
# returned in the chain, or its end result.
|
24
|
+
#
|
25
|
+
def _!
|
26
|
+
@o
|
27
|
+
end
|
28
28
|
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
29
|
+
# Delegate the method args/block
|
30
|
+
def method_missing *a, &b #:nodoc:
|
31
|
+
if __defer?
|
32
|
+
@o = @o.__send__(*a, &b)
|
33
|
+
end
|
34
|
+
self
|
35
|
+
end
|
36
36
|
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
37
|
+
# Explicitly invoke :_? as a method in the chain.
|
38
|
+
def _? #:nodoc:
|
39
|
+
# Unconditionally invoke it, so the eventual _! doesn't fail
|
40
|
+
#if __defer?
|
41
|
+
@o = @o.__send__(:_?)
|
42
|
+
#end
|
43
|
+
self
|
44
|
+
end
|
45
45
|
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
46
|
+
# Return true iff @o is deferable.
|
47
|
+
def __defer?
|
48
|
+
return @o if @falsy
|
49
|
+
! @o.nil?
|
50
|
+
end
|
51
51
|
end
|
52
52
|
|
53
53
|
class Object
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
54
|
+
#
|
55
|
+
# Begins a FragileMethodChain.
|
56
|
+
#
|
57
|
+
def _?
|
58
|
+
FragileMethodChain.new(self)
|
59
|
+
end
|
60
60
|
end
|
61
61
|
|
62
62
|
=begin
|
data/lib/mug/hash/map.rb
CHANGED
@@ -1,85 +1,85 @@
|
|
1
1
|
|
2
2
|
class Hash
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
3
|
+
#
|
4
|
+
# Returns a new hash which is a copy of the current hash but each
|
5
|
+
# value is replaced by the result of running it through +block+.
|
6
|
+
#
|
7
|
+
# {'a'=>1, 'b'=>2}.map_values { |v| v*2 } #=> {'a'=>2, 'b'=>4}
|
8
|
+
# {'a'=>1, 'b'=>2}.map_values { "cat" } #=> {'a'=>"cat", 'b'=>"cat"}
|
9
|
+
#
|
10
|
+
def map_values &block # :yields: value
|
11
|
+
hsh = {}
|
12
|
+
each do |k, v|
|
13
|
+
hsh[k] = yield v
|
14
|
+
end
|
15
|
+
hsh
|
16
|
+
end
|
17
17
|
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
18
|
+
#
|
19
|
+
# Replaces the values in +hsh+ by running them each through +block+.
|
20
|
+
#
|
21
|
+
# See: #map_values
|
22
|
+
#
|
23
|
+
def map_values! &block # :yields: value
|
24
|
+
replace map_values(&block)
|
25
|
+
end
|
26
26
|
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
27
|
+
#
|
28
|
+
# Returns a new hash which is a copy of the current hash but each
|
29
|
+
# key is replaced by the result of running it through +block+.
|
30
|
+
#
|
31
|
+
# If +block+ returns duplicate keys, they will be overwritten in
|
32
|
+
# the resulting hash.
|
33
|
+
#
|
34
|
+
# {'a'=>1, 'b'=>2}.map_keys { |k| k*2 } #=> {'aa'=>1, 'bb'=>2}
|
35
|
+
# {'a'=>1, 'b'=>2}.map_keys { "cat" } #=> {'cat'=>2}
|
36
|
+
#
|
37
|
+
def map_keys &block # :yields: key
|
38
|
+
hsh = {}
|
39
|
+
each do |k, v|
|
40
|
+
hsh[ yield k ] = v
|
41
|
+
end
|
42
|
+
hsh
|
43
|
+
end
|
44
44
|
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
45
|
+
#
|
46
|
+
# Replaces the keys in +hsh+ by running them each through +block+.
|
47
|
+
#
|
48
|
+
# If +block+ returns duplicate keys, they will be overwritten in turn.
|
49
|
+
#
|
50
|
+
# See: #map_keys
|
51
|
+
#
|
52
|
+
def map_keys! &block # :yields: key
|
53
|
+
replace map_keys(&block)
|
54
|
+
end
|
55
55
|
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
56
|
+
#
|
57
|
+
# Returns a new hash which is a copy of the current hash but each
|
58
|
+
# key-value pair is replaced by the result of running it through +block+.
|
59
|
+
#
|
60
|
+
# If +block+ returns duplicate keys, they will be overwritten in
|
61
|
+
# the resulting hash.
|
62
|
+
#
|
63
|
+
# {'a'=>1, 'b'=>2}.map_pairs { |k,v| [k*2, v+1] } #=> {'aa'=>2, 'bb'=>3}
|
64
|
+
# {'a'=>1, 'b'=>2}.map_pairs { ["cat","dog"] } #=> {'cat'=>'dog'}
|
65
|
+
#
|
66
|
+
def map_pairs &block # :yields: key, value
|
67
|
+
hsh = {}
|
68
|
+
each do |k, v|
|
69
|
+
a, b = yield k, v
|
70
|
+
hsh[a] = b
|
71
|
+
end
|
72
|
+
hsh
|
73
|
+
end
|
74
74
|
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
75
|
+
#
|
76
|
+
# Replaces the values in +hsh+ by running them each through +block+.
|
77
|
+
#
|
78
|
+
# See: #map_values
|
79
|
+
#
|
80
|
+
def map_pairs! &block # :yields: key, value
|
81
|
+
replace map_pairs(&block)
|
82
|
+
end
|
83
83
|
end
|
84
84
|
|
85
85
|
=begin
|
data/lib/mug/hash/operations.rb
CHANGED
@@ -1,54 +1,54 @@
|
|
1
1
|
|
2
2
|
class Hash
|
3
3
|
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
4
|
+
#
|
5
|
+
# Returns a new Hash, whose value is the same as this
|
6
|
+
# one, with any extras in +other_hash+ added in.
|
7
|
+
#
|
8
|
+
# Useful for default options.
|
9
|
+
#
|
10
|
+
# Example:
|
11
|
+
# opts = {:a => 1, :b => 2 }
|
12
|
+
# dflt = {:a => 0, :x => 9 }
|
13
|
+
# opts |= dflt # => opts = {:a=>1, :b=>2, :x=>9}
|
14
|
+
#
|
15
|
+
def | other_hash
|
16
|
+
other_hash.merge self
|
17
|
+
end
|
18
18
|
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
19
|
+
#
|
20
|
+
# Adds the contents of +other_hash+ to +hsh+.
|
21
|
+
# Entries with duplicate keys are overwritten with the
|
22
|
+
# values from +other_hash+
|
23
|
+
#
|
24
|
+
def + other_hash
|
25
|
+
merge other_hash
|
26
|
+
end
|
27
27
|
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
28
|
+
#
|
29
|
+
# Appends stuff to the hash.
|
30
|
+
#
|
31
|
+
# If +o+ is a Hash, this is identical to calling #merge!
|
32
|
+
# If +o+ is an Array with two elements, it is interpreted as [key,value]
|
33
|
+
# If +o+ can be converted to a hash with #to_h, this is identical to calling #merge!
|
34
|
+
# Otherwise an ArgumentError is raised.
|
35
|
+
#
|
36
|
+
# Example:
|
37
|
+
# h = {}
|
38
|
+
# h << {:a=>0} # h = {:a=>0}
|
39
|
+
# h << {:b=>2,:c=>3} # h = {:a=>0,:b=>2,:c=>3}
|
40
|
+
# h << [:a,1] # h = {:a=>1,:b=>2,:c=>3}
|
41
|
+
#
|
42
|
+
def << o
|
43
|
+
if o.respond_to? :to_hash
|
44
|
+
merge! o.to_hash
|
45
|
+
elsif o.respond_to?(:to_a) && (a = o.to_a) && a.length == 2
|
46
|
+
tap { store a[0], a[1] }
|
47
|
+
elsif o.respond_to? :to_h
|
48
|
+
merge! o.to_h
|
49
|
+
else
|
50
|
+
raise ArgumentError, "#{o.class.name} is not a Hash"
|
51
|
+
end
|
52
|
+
end
|
53
53
|
end
|
54
54
|
|