enumerable-extra 0.1.0

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/CHANGES ADDED
@@ -0,0 +1,2 @@
1
+ = 0.1.0 - 14-May-2009
2
+ * Initial release
data/MANIFEST ADDED
@@ -0,0 +1,7 @@
1
+ * CHANGES
2
+ * README
3
+ * MANIFEST
4
+ * Rakefile
5
+ * enumerable-extra.gemspec
6
+ * lib/enumerable/extra
7
+ * test/tc_enumerable_extra.rb
data/README ADDED
@@ -0,0 +1,54 @@
1
+ = Description
2
+ This library includes modified versions of the Enumerable methods, designed
3
+ to make list comprehensions a little bit easier and prettier in Ruby.
4
+
5
+ = Installation
6
+ rake test (optional)
7
+ rake install (non-gem) OR rake install_gem (gem)
8
+
9
+ = Synopsis
10
+ require 'enumerable/extra'
11
+
12
+ array = %w/foo bar baz/
13
+
14
+ array.map(:upcase) => ['FOO', 'BAR', 'BAZ']
15
+ array.map(:+, 'A') => ['fooA', 'barA', 'bazA']
16
+
17
+ numbers = [1,2,3]
18
+ numbers.sum => 6
19
+
20
+ = Motivation
21
+ This library was created in reaction to the ugly "&" (or worse, "&its")
22
+ notation started by Ruby on Rails and perpetuated by the Symbol#to_proc
23
+ adherents.
24
+
25
+ The theory behind Symbol#to_proc is that it's a generic metaprogramming
26
+ solution that will solve a certain range of programming problems. The
27
+ reality is that 99% of people use it for list comprehensions*. So, instead
28
+ of introducing crappy notation, I decided that it made better sense to
29
+ modify Enumerable methods to accept arguments.
30
+
31
+ There are two advantages to this. First, superior notation, i.e. no need
32
+ for the ampersand. One of the reasons I chose Ruby as my primary programming
33
+ language in the first place was the beauty of its notation. I don't want
34
+ to see that ruined by Symbol#to_proc. Also, coming from a C background, I
35
+ find the ampersand too reminiscent of C address notation.
36
+
37
+ Second, Symbol#to_proc is very slow.
38
+
39
+ * Based on the questions and solutions that I see on the ruby-talk and rails
40
+ mailing lists. I've monitored the former for almost seven years and the
41
+ latter for close to two now. This is in addition to many blogs I read that
42
+ occasionally touch on the subject.
43
+
44
+ = Future Plans
45
+ Modify several more Enumerable methods.
46
+
47
+ = License
48
+ Ruby's
49
+
50
+ = Warranty
51
+
52
+ = Author
53
+ Daniel J. Berger
54
+ djberg96 at nospam at gmail dot com
@@ -0,0 +1,149 @@
1
+ module Enumerable
2
+ EXTRA_VERSION = '0.1.0'
3
+
4
+ alias old_map map
5
+ alias old_collect collect
6
+
7
+ # Returns the numeric total of the elements of +enum+, using +total+ as
8
+ # an accumulator (0 by default). Raises an error if any of the elements
9
+ # are non-numeric.
10
+ #
11
+ def sum(total = 0)
12
+ each{ |val| total += val }
13
+ total
14
+ end
15
+
16
+ # Returns a new array containing the results of running +method+ once for
17
+ # every element in the enumerable object. If both arguments and a block
18
+ # are provided the arguments are processed first, then passed to
19
+ # the block.
20
+ #
21
+ # If no method is provided, then it behaves as the standard MRI method.
22
+ #
23
+ # Examples:
24
+ #
25
+ # array = ['foo', 'bar']
26
+ #
27
+ # # No arguments
28
+ # array.map(:capitalize) => ['Foo', 'Bar']
29
+ #
30
+ # # With arguments
31
+ # array.map(:+, 'x') => ['foox', 'barx']
32
+ #
33
+ # # With arguments and a block
34
+ # array.map(:capitalize){ |e| e + 'x' } => ['Foox', 'Barx']
35
+ #
36
+ def map(method=nil, *args, &block)
37
+ if method
38
+ array = []
39
+ method = method.to_sym unless method.is_a?(Symbol)
40
+
41
+ each{ |obj|
42
+ temp = obj.send(method, *args)
43
+ if block
44
+ array << block.call(temp)
45
+ else
46
+ array << temp
47
+ end
48
+ }
49
+
50
+ array
51
+ else
52
+ old_map(&block)
53
+ end
54
+ end
55
+
56
+ # Reset the aliases
57
+ alias collect map
58
+ end
59
+
60
+ class Array
61
+ alias old_map map
62
+ alias old_map! map!
63
+ alias old_collect collect
64
+ alias old_collect! collect!
65
+ #alias old_select select
66
+
67
+ # Returns a new array containing the results of running +block+ once for
68
+ # every element in the +array+.
69
+ #
70
+ # Examples:
71
+ #
72
+ # array = ['foo', 'bar']
73
+ #
74
+ # # No arguments
75
+ # array.map(:capitalize) => ['Foo', 'Bar']
76
+ #
77
+ # # With arguments
78
+ # array.map(:+, 'x') => ['foox', 'barx']
79
+ #
80
+ # # With arguments and a block
81
+ # array.map(:capitalize){ |e| e + 'x' } => ['Foox', 'Barx']
82
+ #--
83
+ # The Array class actually has its own implementation of the +map+ method,
84
+ # hence the duplication.
85
+ #
86
+ def map(method=nil, *args, &block)
87
+ if method
88
+ array = []
89
+ method = method.to_sym unless method.is_a?(Symbol)
90
+
91
+ each{ |obj|
92
+ temp = obj.send(method, *args)
93
+ if block
94
+ array << block.call(temp)
95
+ else
96
+ array << temp
97
+ end
98
+ }
99
+ array
100
+ else
101
+ old_map(&block)
102
+ end
103
+ end
104
+
105
+ # Same as Array#map, but modifies the receiver in place. Also note that
106
+ # a block is _not_ required. If no block is given, an array of values
107
+ # is returned instead
108
+ #
109
+ def map!(method=nil, *args, &block)
110
+ self.replace(map(method, *args, &block))
111
+ end
112
+
113
+ =begin
114
+ def select(method=nil, condition = nil, *args, &block)
115
+ array = [] unless block
116
+ if method
117
+ if block
118
+ warn 'block ignored when arguments provided'
119
+ end
120
+
121
+ if condition.nil?
122
+ raise 'condition must be provided if method is provided'
123
+ end
124
+
125
+ method = method.to_sym unless method.is_a?(Symbol)
126
+
127
+ each{ |obj|
128
+ if args.length > 0
129
+ if obj.send(method, condition, *args)
130
+ array << obj
131
+ end
132
+ else
133
+ if obj.send(method, condition)
134
+ array << obj
135
+ end
136
+ end
137
+ }
138
+
139
+ return array
140
+ else
141
+ old_select(&block)
142
+ end
143
+ end
144
+ =end
145
+
146
+ # Reset the aliases
147
+ alias collect map
148
+ alias collect! map!
149
+ end
@@ -0,0 +1,77 @@
1
+ ########################################################################
2
+ # tc_enumerable_extra.rb
3
+ #
4
+ # Test case for the enumerable-extra library. You should run this
5
+ # test via the 'rake test' task.
6
+ ########################################################################
7
+ require 'test/unit'
8
+ require 'enumerable/extra'
9
+
10
+ class TC_Enumerable_Extra < Test::Unit::TestCase
11
+ def setup
12
+ @words = %w/foo bar baz/
13
+ @numbers = [1,2,3]
14
+ @hash = {'foo', 1, 'bar', 2}
15
+ @array = []
16
+ end
17
+
18
+ def test_version
19
+ assert_equal('0.1.0', Enumerable::EXTRA_VERSION)
20
+ end
21
+
22
+ def test_sum
23
+ assert_respond_to(@numbers, :sum)
24
+ assert_equal(6, @numbers.sum)
25
+ assert_equal(20, @numbers.sum(14))
26
+ end
27
+
28
+ def test_sum_expected_errors
29
+ assert_raises(TypeError){ @words.sum }
30
+ end
31
+
32
+ def test_map_array_no_block
33
+ assert_nothing_raised{ @words.map }
34
+ assert_equal(%w/foo bar baz/, @words.map)
35
+ assert_equal(%w/FOO BAR BAZ/, @words.map(:upcase))
36
+ assert_equal(%w/fooA barA bazA/, @words.map(:+, 'A'))
37
+ assert_equal(%w/foo bar baz/, @words) # Verify receiver unmodified
38
+ end
39
+
40
+ # Test the alias explicitly
41
+ def test_collect_array_no_block
42
+ assert_nothing_raised{ @words.collect }
43
+ assert_equal(%w/foo bar baz/, @words.collect)
44
+ assert_equal(%w/FOO BAR BAZ/, @words.collect(:upcase))
45
+ assert_equal(%w/fooA barA bazA/, @words.collect(:+, 'A'))
46
+ assert_equal(%w/foo bar baz/, @words) # Verify receiver unmodified
47
+ end
48
+
49
+ def test_map_bang_array_no_block
50
+ assert_nothing_raised{ @words.map! }
51
+ assert_equal(%w/foo bar baz/, @words.map!)
52
+ assert_equal(%w/FOO BAR BAZ/, @words.map!(:upcase))
53
+ assert_equal(%w/FOO BAR BAZ/, @words) # Verify receiver modified
54
+ end
55
+
56
+ def test_map_with_block
57
+ assert_nothing_raised{ @words.map{} }
58
+ assert_nothing_raised{ @words.map{ |e| @array << e } }
59
+ assert_equal(%w/foo bar baz/, @array)
60
+
61
+ @array = []
62
+ assert_nothing_raised{ @words.map(:upcase){ |e| @array << e } }
63
+ assert_equal(%w/FOO BAR BAZ/, @array)
64
+
65
+ @array = []
66
+ assert_nothing_raised{ @words.map(:+, 'A'){ |e| @array << e } }
67
+ assert_equal(%w/fooA barA bazA/, @array)
68
+ assert_equal(%w/foo bar baz/, @words) # Verify receiver unmodified
69
+ end
70
+
71
+ def teardown
72
+ @words = nil
73
+ @numbers = nil
74
+ @hash = nil
75
+ @array = nil
76
+ end
77
+ end
metadata ADDED
@@ -0,0 +1,61 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: enumerable-extra
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Daniel Berger
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2009-05-14 00:00:00 -06:00
13
+ default_executable:
14
+ dependencies: []
15
+
16
+ description: " The enumerable-extra library provides overridden Enumerable methods\n that make it easier to handle common operations that apply to each\n element of a list without resorting to Symbol#to_proc. It also adds\n an Enumerable#sum method.\n"
17
+ email: djberg96@gmail.com
18
+ executables: []
19
+
20
+ extensions: []
21
+
22
+ extra_rdoc_files:
23
+ - README
24
+ - CHANGES
25
+ - MANIFEST
26
+ files:
27
+ - lib/enumerable/extra.rb
28
+ - test/tc_enumerable_extra.rb
29
+ - README
30
+ - CHANGES
31
+ - MANIFEST
32
+ has_rdoc: true
33
+ homepage: http://www.rubyforge.org/projects/shards
34
+ licenses: []
35
+
36
+ post_install_message:
37
+ rdoc_options: []
38
+
39
+ require_paths:
40
+ - lib
41
+ required_ruby_version: !ruby/object:Gem::Requirement
42
+ requirements:
43
+ - - <
44
+ - !ruby/object:Gem::Version
45
+ version: 1.9.0
46
+ version:
47
+ required_rubygems_version: !ruby/object:Gem::Requirement
48
+ requirements:
49
+ - - ">="
50
+ - !ruby/object:Gem::Version
51
+ version: "0"
52
+ version:
53
+ requirements: []
54
+
55
+ rubyforge_project: shards
56
+ rubygems_version: 1.3.3
57
+ signing_key:
58
+ specification_version: 3
59
+ summary: Enhanced methods for Enumerable objects
60
+ test_files:
61
+ - test/tc_enumerable_extra.rb