facets 2.8.1 → 2.8.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/HISTORY.rdoc +121 -91
- data/NOTES +13 -1
- data/demo/scenario_require.rdoc +0 -5
- data/lib/core/facets.rb +6 -382
- data/lib/core/facets/array.rb +4 -3
- data/lib/core/facets/array/product.rb +0 -9
- data/lib/core/facets/array/uniq_by.rb +18 -0
- data/lib/core/facets/binding/caller.rb +14 -18
- data/lib/core/facets/boolean.rb +75 -78
- data/lib/core/facets/denumerable.rb +3 -3
- data/lib/core/facets/dir/ascend.rb +2 -1
- data/lib/core/facets/enumerable/collapse.rb +12 -0
- data/lib/core/facets/enumerable/compact_map.rb +8 -4
- data/lib/core/facets/enumerable/defer.rb +3 -2
- data/lib/core/facets/enumerable/each_with_object.rb +38 -0
- data/lib/core/facets/enumerable/every.rb +4 -4
- data/lib/core/facets/enumerable/ewise.rb +22 -16
- data/lib/core/facets/enumerable/exclude.rb +13 -0
- data/lib/core/facets/enumerable/filter.rb +18 -8
- data/lib/core/facets/enumerable/find_yield.rb +37 -0
- data/lib/core/facets/enumerable/map_detect.rb +1 -28
- data/lib/core/facets/enumerable/map_with_index.rb +2 -2
- data/lib/core/facets/enumerable/per.rb +2 -2
- data/lib/core/facets/enumerable/purge.rb +43 -0
- data/lib/core/facets/enumerator.rb +70 -0
- data/lib/core/facets/enumerator/fx.rb +20 -0
- data/lib/core/facets/integer/multiple.rb +6 -2
- data/lib/core/facets/kernel/false.rb +2 -0
- data/lib/core/facets/kernel/true.rb +26 -0
- data/lib/core/facets/numeric/length.rb +2 -2
- data/lib/core/facets/numeric/spacing.rb +20 -0
- data/lib/core/facets/proc/bind_to.rb +9 -0
- data/lib/core/facets/string/exclude.rb +10 -0
- data/lib/core/facets/string/expand_tab.rb +6 -6
- data/lib/core/facets/time/future.rb +14 -0
- data/lib/core/facets/time/past.rb +1 -0
- data/lib/core/facets/unboundmethod/name.rb +22 -18
- data/lib/more/facets/date.rb +38 -3
- data/lib/more/facets/fileutils/cp_rx.rb +42 -0
- data/lib/more/facets/pathname.rb +1 -1
- data/meta/homepage +1 -1
- data/meta/released +1 -1
- data/meta/version +1 -1
- data/test/core/array/test_product.rb +0 -5
- data/test/core/enumerable/test_find_yield.rb +75 -0
- data/test/core/numeric/test_spacing.rb +12 -0
- data/test/core/unboundmethod/test_name.rb +3 -3
- metadata +36 -23
- data/MANIFEST +0 -756
- data/lib/core/facets/enumerable/collect.rb +0 -4
- data/lib/core/facets/enumerable/inject.rb +0 -30
- data/lib/core/facets/numeric/size.rb +0 -10
- data/lib/more/facets/enumerator.rb +0 -62
- data/lib/more/facets/tracepoint.rb +0 -209
- data/test/core/enumerable/test_map_detect.rb +0 -75
@@ -2,20 +2,20 @@ require 'facets/functor'
|
|
2
2
|
|
3
3
|
module Enumerable
|
4
4
|
|
5
|
+
EWISE = {}
|
6
|
+
|
5
7
|
# Returns an elementwise Functor designed to make R-like
|
6
|
-
# elementwise operations possible.
|
8
|
+
# elementwise operations possible. This is very much like
|
9
|
+
# the #every method, but it treats array argument specially.
|
7
10
|
#
|
8
|
-
# [1,2].
|
9
|
-
# [1,2].
|
10
|
-
# [1,2].
|
11
|
+
# [1,2].ewise + 3 #=> [4,5]
|
12
|
+
# [1,2].ewise + [4,5] #=> [5,7]
|
13
|
+
# [1,2].ewise + [[4,5],3] #=> [[5,7],[4,5]
|
11
14
|
#
|
12
|
-
#--
|
13
15
|
# Special thanks to Martin DeMello for helping to develop this.
|
14
|
-
#++
|
15
16
|
|
16
|
-
def
|
17
|
-
|
18
|
-
@_elementwise_functor[count] ||= Functor.new do |op,*args|
|
17
|
+
def ewise(count=1)
|
18
|
+
EWISE[[self,count]] ||= Functor.new do |op,*args|
|
19
19
|
if args.empty?
|
20
20
|
r = self
|
21
21
|
count.times do
|
@@ -46,16 +46,22 @@ module Enumerable
|
|
46
46
|
end
|
47
47
|
end
|
48
48
|
|
49
|
-
#
|
49
|
+
# Long-term for #ewise.
|
50
50
|
#
|
51
51
|
# a = [1,2]
|
52
|
-
# a.
|
53
|
-
# a.
|
54
|
-
# a.
|
52
|
+
# a.elementwise + 3 #=> [4,5]
|
53
|
+
# a.elementwise + [4,5] #=> [5,7]
|
54
|
+
# a.elementwise + [[4,5],3] #=> [[5,7],[4,5]
|
55
55
|
#
|
56
|
-
|
57
|
-
# Both of whihc are deprecated.
|
56
|
+
alias_method :elementwise, :ewise
|
58
57
|
|
59
|
-
|
58
|
+
# Operator equivalent of #elementwise.
|
59
|
+
#
|
60
|
+
# This was deprecated along with it's file "op_tilde.rb".
|
61
|
+
#
|
62
|
+
#def ~@
|
63
|
+
# ewise
|
64
|
+
#end
|
60
65
|
|
61
66
|
end
|
67
|
+
|
@@ -1,16 +1,20 @@
|
|
1
1
|
module Enumerable
|
2
2
|
|
3
|
-
# The block acts as an arbitrary filter on the data. Unlike
|
4
|
-
#
|
5
|
-
# additional
|
6
|
-
# of the output.
|
3
|
+
# The block acts as an arbitrary filter on the data. Unlike map,
|
4
|
+
# it can choose to drop elements from the result and/or add
|
5
|
+
# additional elements. The first object passed to the block is
|
6
|
+
# the receiver of the output.
|
7
7
|
#
|
8
8
|
# (1..1_000_000_000).
|
9
|
-
# filter
|
10
|
-
# filter
|
11
|
-
# take(10).each
|
9
|
+
# filter{ |out,i| out << i if i % 2 == 0 }. # like select
|
10
|
+
# filter{ |out,i| out << i + 100 }. # like map
|
11
|
+
# take(10).each{ |i| puts i }
|
12
12
|
#
|
13
|
-
|
13
|
+
# This is very similar to #each_with_object, but #filter handles
|
14
|
+
# argument better by reversing their order and using the splat
|
15
|
+
# operator.
|
16
|
+
|
17
|
+
def filter(output=[]) #:yeild:
|
14
18
|
if block_given?
|
15
19
|
each do |*input|
|
16
20
|
yield(output, *input)
|
@@ -21,5 +25,11 @@ module Enumerable
|
|
21
25
|
end
|
22
26
|
end
|
23
27
|
|
28
|
+
# OLD NAME
|
29
|
+
# CREDIT: David Black, Louis J Scoras
|
30
|
+
#def injecting(k)
|
31
|
+
# each{ |i| yield(k, i) }; k
|
32
|
+
#end
|
33
|
+
|
24
34
|
end
|
25
35
|
|
@@ -0,0 +1,37 @@
|
|
1
|
+
module Enumerable
|
2
|
+
|
3
|
+
# Yield each element to the block and return the result
|
4
|
+
# of the block when that result evaluates as true,
|
5
|
+
# terminating early like #detect and #find.
|
6
|
+
#
|
7
|
+
# obj1.foo? #=> false
|
8
|
+
# obj2.foo? #=> true
|
9
|
+
# obj2.foo #=> "value"
|
10
|
+
#
|
11
|
+
# [obj1, obj2].find_yield{ |obj| obj.foo if obj.foo? } #=> "value"
|
12
|
+
#
|
13
|
+
# Another example:
|
14
|
+
#
|
15
|
+
# [1,2,3,4,5].find_yield{ |i| j = i+1; j if j % 4 == 0 } #=> "5"
|
16
|
+
#
|
17
|
+
# If the block is never true, return the object given in the first parameter,
|
18
|
+
# or nil if none specified.
|
19
|
+
#
|
20
|
+
# [1,2,3].find_yield{ |_| false } #=> nil
|
21
|
+
# [false].find_yield(1){ |_| false } #=> 1
|
22
|
+
#
|
23
|
+
def find_yield(fallback=nil) #:yield:
|
24
|
+
each do |member|
|
25
|
+
result = yield(member)
|
26
|
+
return result if result
|
27
|
+
end
|
28
|
+
fallback
|
29
|
+
end
|
30
|
+
|
31
|
+
# DEPRECATE: This has been renamed to #find_yield.
|
32
|
+
def map_detect(fallback=nil)
|
33
|
+
find_yield(fallback)
|
34
|
+
end
|
35
|
+
|
36
|
+
end
|
37
|
+
|
@@ -1,28 +1 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
# Yield each element to the block. Returns the result of
|
4
|
-
# the block when the block is true, terminating early as detect does.
|
5
|
-
#
|
6
|
-
# obj1.foo? #=> false
|
7
|
-
# obj2.foo? #=> true
|
8
|
-
#
|
9
|
-
# obj2.foo #=> "a value"
|
10
|
-
#
|
11
|
-
# [obj1, obj2].map_detect { |obj| obj.foo if obj.foo? } #=> "a value"
|
12
|
-
#
|
13
|
-
# If the block is never true, return the object given in the first parameter,
|
14
|
-
# or nil if none specified.
|
15
|
-
#
|
16
|
-
# [1,2,3].map_detect { |_| false } #=> nil
|
17
|
-
# [false].map_detect(1) { |_| false } #=> 1
|
18
|
-
#
|
19
|
-
def map_detect(value_for_none_matching = nil)
|
20
|
-
each do |member|
|
21
|
-
if result = yield(member)
|
22
|
-
return result
|
23
|
-
end
|
24
|
-
end
|
25
|
-
|
26
|
-
value_for_none_matching
|
27
|
-
end
|
28
|
-
end
|
1
|
+
require 'facets/enumerable/find_yield'
|
@@ -1,7 +1,7 @@
|
|
1
1
|
require 'facets/functor'
|
2
2
|
|
3
3
|
#--
|
4
|
-
# TODO: Consider Enumerator methods
|
4
|
+
# TODO: Consider Enumerator methods.
|
5
5
|
#++
|
6
6
|
|
7
7
|
module Enumerable
|
@@ -22,7 +22,7 @@ module Enumerable
|
|
22
22
|
# __send__(enum_method, *enum_args){ |x| x.__send__(op, *args) } #, &blk) }
|
23
23
|
#end
|
24
24
|
else
|
25
|
-
|
25
|
+
Functor.new do |enum_method, *enum_args|
|
26
26
|
Permeator.new(self, enum_method, *enum_args)
|
27
27
|
#Functor.new do |op, *args|
|
28
28
|
# __send__(enum_method, *enum_args){ |x| x.__send__(op, *args) } #, &blk) }
|
@@ -0,0 +1,43 @@
|
|
1
|
+
module Enumerable
|
2
|
+
|
3
|
+
# A versitle compaction method. Like #map but used
|
4
|
+
# to filter out multiple items in a single step.
|
5
|
+
#
|
6
|
+
# Without +trash+ arguments +nil+ is assumed.
|
7
|
+
#
|
8
|
+
# [1, nil, 2].purge #=> [1,2]
|
9
|
+
#
|
10
|
+
# If +trash+ arguments are given, each argument is
|
11
|
+
# compared for a match using #==.
|
12
|
+
#
|
13
|
+
# (1..6).purge(3,4) #=> [1,2,5,6]
|
14
|
+
#
|
15
|
+
# If a block is given, the yield is used in the
|
16
|
+
# matching condition instead of the element itsef.
|
17
|
+
#
|
18
|
+
# (1..6).purge(0){ |n| n % 2 } #=> [1,3,5]
|
19
|
+
#
|
20
|
+
# NOTE: This could just as well be an override of the
|
21
|
+
# core #compact method, but to avoid potential issues
|
22
|
+
# associated with overriding core methods we use the
|
23
|
+
# alternate name #purge.
|
24
|
+
#
|
25
|
+
# CREDIT: Trans
|
26
|
+
|
27
|
+
def purge(*trash, &block)
|
28
|
+
trash = [nil] if trash.empty?
|
29
|
+
r = []
|
30
|
+
if block_given?
|
31
|
+
each do |e|
|
32
|
+
y = yield(e)
|
33
|
+
r << e unless trash.any?{|t| t == y}
|
34
|
+
end
|
35
|
+
else
|
36
|
+
each do |e|
|
37
|
+
r << e unless trash.any?{|t| t == e}
|
38
|
+
end
|
39
|
+
end
|
40
|
+
r
|
41
|
+
end
|
42
|
+
|
43
|
+
end
|
@@ -0,0 +1,70 @@
|
|
1
|
+
begin
|
2
|
+
require 'enumerator' #if RUBY_VERSION < 1.9
|
3
|
+
# for Ruby 1.8 -> 1.9 transition
|
4
|
+
Enumerator = Enumerable::Enumerator unless defined? ::Enumerator
|
5
|
+
|
6
|
+
class Enumerator
|
7
|
+
|
8
|
+
alias :old_initialize :initialize
|
9
|
+
|
10
|
+
# Provides the ruby-1.9 block form of Enumerator, where you can write:
|
11
|
+
#
|
12
|
+
# obj = Enumerator.new do |yielder|
|
13
|
+
# .. do stuff
|
14
|
+
# yielder.yield data # or: yielder << data
|
15
|
+
# .. etc
|
16
|
+
# end
|
17
|
+
#
|
18
|
+
# When obj.each is called, the block is run once. It should call
|
19
|
+
# yielder.yield with each item it wishes to generate.
|
20
|
+
#
|
21
|
+
# Example:
|
22
|
+
#
|
23
|
+
# fib = Enumerator.new { |y|
|
24
|
+
# a = b = 1
|
25
|
+
# loop {
|
26
|
+
# y << a
|
27
|
+
# a, b = b, a + b
|
28
|
+
# }
|
29
|
+
# }
|
30
|
+
#
|
31
|
+
# assert_equal [1, 1, 2, 3, 5, 8, 13, 21, 34, 55], fib.take(10)
|
32
|
+
|
33
|
+
def initialize(*args, &block)
|
34
|
+
if block_given?
|
35
|
+
@body = block
|
36
|
+
old_initialize(self, :_start)
|
37
|
+
else
|
38
|
+
old_initialize(*args)
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
def _start(*args,&receiver) #:nodoc:
|
43
|
+
@body.call(Yielder.new(receiver), *args)
|
44
|
+
end
|
45
|
+
|
46
|
+
# Wrapper to allow yielder.yield(output) or yielder << output
|
47
|
+
# in the same way as ruby-1.9
|
48
|
+
|
49
|
+
class Yielder #:nodoc:
|
50
|
+
def initialize(proc)
|
51
|
+
@proc = proc
|
52
|
+
end
|
53
|
+
def yield(*args)
|
54
|
+
@proc[*args]
|
55
|
+
end
|
56
|
+
alias :<< :yield
|
57
|
+
end
|
58
|
+
|
59
|
+
end
|
60
|
+
|
61
|
+
rescue LoadError # Ruby 1.9 already has it built-in.
|
62
|
+
end
|
63
|
+
|
64
|
+
path = __FILE__.chomp('.rb')
|
65
|
+
base = File.basename(path)
|
66
|
+
Dir[File.join(path, '*.rb')].each do |lib|
|
67
|
+
#require lib # why is this so much slower?
|
68
|
+
require "facets/#{base}/#{File.basename(lib)}"
|
69
|
+
end
|
70
|
+
|
@@ -0,0 +1,20 @@
|
|
1
|
+
begin
|
2
|
+
require 'enumerator' #if RUBY_VERSION < 1.9
|
3
|
+
# for Ruby 1.8 -> 1.9 transition
|
4
|
+
Enumerator = Enumerable::Enumerator unless defined? ::Enumerator
|
5
|
+
rescue LoadError # Ruby 1.9 already has it built-in.
|
6
|
+
end
|
7
|
+
|
8
|
+
require 'facets/functor'
|
9
|
+
|
10
|
+
class Enumerator
|
11
|
+
|
12
|
+
#
|
13
|
+
def fx
|
14
|
+
Functor.new do |op, *a|
|
15
|
+
each{ |e| e.send(op, *a) }
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
end
|
20
|
+
|
@@ -1,6 +1,6 @@
|
|
1
1
|
class Integer
|
2
2
|
|
3
|
-
# Is
|
3
|
+
# Is +self+ a multiple of a given number?
|
4
4
|
#
|
5
5
|
# 7.multiple?(2) #=> false
|
6
6
|
# 8.multiple?(2) #=> true
|
@@ -8,7 +8,11 @@ class Integer
|
|
8
8
|
# CREDIT: Trans
|
9
9
|
|
10
10
|
def multiple?(number)
|
11
|
-
|
11
|
+
if number.zero?
|
12
|
+
zero? ? true : false
|
13
|
+
else
|
14
|
+
self % number == 0
|
15
|
+
end
|
12
16
|
end
|
13
17
|
|
14
18
|
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
module Kernel
|
2
|
+
|
3
|
+
# Returns true is an object is class TrueClass,
|
4
|
+
# otherwise false.
|
5
|
+
#
|
6
|
+
# true.true? #=> true
|
7
|
+
# false.true? #=> false
|
8
|
+
# nil.true? #=> false
|
9
|
+
#
|
10
|
+
def true?
|
11
|
+
(true == self)
|
12
|
+
end
|
13
|
+
|
14
|
+
# Returns true is an object is class FalseClass,
|
15
|
+
# otherwise false.
|
16
|
+
#
|
17
|
+
# true.false? #=> false
|
18
|
+
# false.false? #=> true
|
19
|
+
# nil.false? #=> false
|
20
|
+
#
|
21
|
+
def false?
|
22
|
+
(false == self)
|
23
|
+
end
|
24
|
+
|
25
|
+
end
|
26
|
+
|
@@ -0,0 +1,20 @@
|
|
1
|
+
class Numeric
|
2
|
+
|
3
|
+
# Returns the size of the string representation of
|
4
|
+
# a numerical value.
|
5
|
+
#
|
6
|
+
# 1.spacing #=> 1
|
7
|
+
# 10.spacing #=> 2
|
8
|
+
# 100.spacing #=> 3
|
9
|
+
# -100.spacing #=> 4
|
10
|
+
# 1.2.spacing #=> 3
|
11
|
+
#
|
12
|
+
# CREDIT: Victor H. Goff III
|
13
|
+
|
14
|
+
def spacing
|
15
|
+
to_s.length
|
16
|
+
end
|
17
|
+
|
18
|
+
end
|
19
|
+
|
20
|
+
|