functional-ruby 0.7.7 → 1.0.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.
Files changed (63) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +92 -152
  3. data/doc/memo.txt +192 -0
  4. data/doc/pattern_matching.txt +485 -0
  5. data/doc/protocol.txt +221 -0
  6. data/doc/record.txt +144 -0
  7. data/doc/thread_safety.txt +8 -0
  8. data/lib/functional.rb +48 -18
  9. data/lib/functional/abstract_struct.rb +161 -0
  10. data/lib/functional/delay.rb +117 -0
  11. data/lib/functional/either.rb +222 -0
  12. data/lib/functional/memo.rb +93 -0
  13. data/lib/functional/method_signature.rb +72 -0
  14. data/lib/functional/option.rb +209 -0
  15. data/lib/functional/pattern_matching.rb +117 -100
  16. data/lib/functional/protocol.rb +157 -0
  17. data/lib/functional/protocol_info.rb +193 -0
  18. data/lib/functional/record.rb +155 -0
  19. data/lib/functional/type_check.rb +112 -0
  20. data/lib/functional/union.rb +152 -0
  21. data/lib/functional/version.rb +3 -1
  22. data/spec/functional/abstract_struct_shared.rb +154 -0
  23. data/spec/functional/complex_pattern_matching_spec.rb +205 -0
  24. data/spec/functional/configuration_spec.rb +17 -0
  25. data/spec/functional/delay_spec.rb +147 -0
  26. data/spec/functional/either_spec.rb +237 -0
  27. data/spec/functional/memo_spec.rb +207 -0
  28. data/spec/functional/option_spec.rb +292 -0
  29. data/spec/functional/pattern_matching_spec.rb +279 -276
  30. data/spec/functional/protocol_info_spec.rb +444 -0
  31. data/spec/functional/protocol_spec.rb +274 -0
  32. data/spec/functional/record_spec.rb +175 -0
  33. data/spec/functional/type_check_spec.rb +103 -0
  34. data/spec/functional/union_spec.rb +110 -0
  35. data/spec/spec_helper.rb +6 -4
  36. metadata +55 -45
  37. data/lib/functional/behavior.rb +0 -138
  38. data/lib/functional/behaviour.rb +0 -2
  39. data/lib/functional/catalog.rb +0 -487
  40. data/lib/functional/collection.rb +0 -403
  41. data/lib/functional/inflect.rb +0 -127
  42. data/lib/functional/platform.rb +0 -120
  43. data/lib/functional/search.rb +0 -132
  44. data/lib/functional/sort.rb +0 -41
  45. data/lib/functional/utilities.rb +0 -189
  46. data/md/behavior.md +0 -188
  47. data/md/catalog.md +0 -32
  48. data/md/collection.md +0 -32
  49. data/md/inflect.md +0 -32
  50. data/md/pattern_matching.md +0 -512
  51. data/md/platform.md +0 -32
  52. data/md/search.md +0 -32
  53. data/md/sort.md +0 -32
  54. data/md/utilities.md +0 -55
  55. data/spec/functional/behavior_spec.rb +0 -528
  56. data/spec/functional/catalog_spec.rb +0 -1206
  57. data/spec/functional/collection_spec.rb +0 -752
  58. data/spec/functional/inflect_spec.rb +0 -85
  59. data/spec/functional/integration_spec.rb +0 -205
  60. data/spec/functional/platform_spec.rb +0 -501
  61. data/spec/functional/search_spec.rb +0 -187
  62. data/spec/functional/sort_spec.rb +0 -61
  63. data/spec/functional/utilities_spec.rb +0 -277
@@ -0,0 +1,175 @@
1
+ require 'spec_helper'
2
+ require_relative 'abstract_struct_shared'
3
+
4
+ module Functional
5
+
6
+ describe Record do
7
+
8
+ let!(:expected_fields){ [:a, :b, :c] }
9
+ let!(:expected_values){ [42, nil, nil] }
10
+
11
+ let(:struct_class) { Record.new(*expected_fields) }
12
+ let(:struct_object) { struct_class.new(struct_class.fields.first => 42) }
13
+ let(:other_object) { struct_class.new(struct_class.fields.first => Object.new) }
14
+
15
+ it_should_behave_like :abstract_struct
16
+
17
+ context 'definition' do
18
+
19
+ it 'registers the new class with Record when given a string name' do
20
+ Record.new('Foo', :foo, :bar, :baz)
21
+ expect(defined?(Record::Foo)).to eq 'constant'
22
+ end
23
+
24
+ it 'default all fields values to nil' do
25
+ fields = [:foo, :bar, :baz]
26
+ clazz = Record.new(*fields)
27
+
28
+ record = clazz.new
29
+
30
+ fields.each do |field|
31
+ expect(record.send(field)).to be_nil
32
+ end
33
+ end
34
+
35
+ it 'sets initial values based on values given at object construction' do
36
+ clazz = Record.new(:foo, :bar, :baz)
37
+ record = clazz.new(foo: 1, bar: 2, baz: 3)
38
+
39
+ expect(record.foo).to eq 1
40
+ expect(record.bar).to eq 2
41
+ expect(record.baz).to eq 3
42
+ end
43
+
44
+ it 'defaults fields to values given during class creation' do
45
+ clazz = Record.new(:foo, :bar, :baz) do
46
+ default :foo, 42
47
+ default :bar, 'w00t!'
48
+ end
49
+
50
+ record = clazz.new
51
+ expect(record.foo).to eq 42
52
+ expect(record.bar).to eq 'w00t!'
53
+ expect(record.baz).to be_nil
54
+ end
55
+
56
+ it 'overrides default values with values provided at object construction' do
57
+ clazz = Record.new(:foo, :bar, :baz) do
58
+ default :foo, 42
59
+ default :bar, 'w00t!'
60
+ default :baz, :bogus
61
+ end
62
+
63
+ record = clazz.new(foo: 1, bar: 2)
64
+
65
+ expect(record.foo).to eq 1
66
+ expect(record.bar).to eq 2
67
+ expect(record.baz).to eq :bogus
68
+ end
69
+
70
+ it 'duplicates default values when assigning to a new object' do
71
+ original = 'Foo'
72
+ clazz = Record.new(:foo, :bar, :baz) do
73
+ default :foo, original
74
+ end
75
+
76
+ record = clazz.new
77
+ expect(record.foo).to eq original
78
+ expect(record.foo.object_id).to_not eql original.object_id
79
+ end
80
+
81
+ it 'does not conflate defaults across record classes' do
82
+ clazz_foo = Record.new(:foo, :bar, :baz) do
83
+ default :foo, 42
84
+ end
85
+
86
+ clazz_matz = Record.new(:foo, :bar, :baz) do
87
+ default :foo, 'Matsumoto'
88
+ end
89
+
90
+ expect(clazz_foo.new.foo).to eq 42
91
+ expect(clazz_matz.new.foo).to eq 'Matsumoto'
92
+ end
93
+
94
+ it 'raises an exception when values for requred field are not provided' do
95
+ clazz = Record.new(:foo, :bar, :baz) do
96
+ mandatory :foo
97
+ end
98
+
99
+ expect {
100
+ clazz.new(bar: 1)
101
+ }.to raise_exception(ArgumentError)
102
+ end
103
+
104
+ it 'raises an exception when required values are nil' do
105
+ clazz = Record.new(:foo, :bar, :baz) do
106
+ mandatory :foo
107
+ end
108
+
109
+ expect {
110
+ clazz.new(foo: nil, bar: 1)
111
+ }.to raise_exception(ArgumentError)
112
+ end
113
+
114
+ it 'allows a field to be required and have a default value' do
115
+ clazz = Record.new(:foo, :bar, :baz) do
116
+ mandatory :foo
117
+ default :foo, 42
118
+ end
119
+
120
+ expect {
121
+ clazz.new
122
+ }.to_not raise_exception
123
+
124
+ expect(clazz.new.foo).to eq 42
125
+ end
126
+
127
+ it 'allows multiple required fields to be specified together' do
128
+ clazz = Record.new(:foo, :bar, :baz) do
129
+ mandatory :foo, :bar, :baz
130
+ end
131
+
132
+ expect {
133
+ clazz.new(foo: 1, bar: 2)
134
+ }.to raise_exception(ArgumentError)
135
+
136
+ expect {
137
+ clazz.new(bar: 2, baz: 3)
138
+ }.to raise_exception(ArgumentError)
139
+
140
+ expect {
141
+ clazz.new(foo: 1, bar: 2, baz: 3)
142
+ }.to_not raise_exception
143
+ end
144
+
145
+ it 'raises an exception if the default value for a require field is nil' do
146
+ clazz = Record.new(:foo, :bar, :baz) do
147
+ mandatory :foo
148
+ default :foo, nil
149
+ end
150
+
151
+ expect {
152
+ clazz.new
153
+ }.to raise_exception(ArgumentError)
154
+ end
155
+
156
+ it 'does not conflate default values across record classes' do
157
+ clazz_foo = Record.new(:foo, :bar, :baz) do
158
+ mandatory :foo
159
+ end
160
+
161
+ clazz_baz = Record.new(:foo, :bar, :baz) do
162
+ mandatory :baz
163
+ end
164
+
165
+ expect {
166
+ clazz_foo.new(foo: 42)
167
+ }.to_not raise_error
168
+
169
+ expect {
170
+ clazz_baz.new(baz: 42)
171
+ }.to_not raise_error
172
+ end
173
+ end
174
+ end
175
+ end
@@ -0,0 +1,103 @@
1
+ require 'spec_helper'
2
+
3
+ module Functional
4
+
5
+ describe TypeCheck do
6
+
7
+ context 'Type?' do
8
+
9
+ it 'returns true when value is of any of the types' do
10
+ target = 'foo'
11
+ expect(TypeCheck.Type?(target, String, Array, Hash)).to be true
12
+ end
13
+
14
+ it 'returns false when value is not of any of the types' do
15
+ target = 'foo'
16
+ expect(TypeCheck.Type?(target, Fixnum, Array, Hash)).to be false
17
+ end
18
+ end
19
+
20
+ context 'Type!' do
21
+
22
+ it 'returns the value when value is of any of the types' do
23
+ target = 'foo'
24
+ expect(TypeCheck.Type!(target, String, Array, Hash)).to be target
25
+ end
26
+
27
+ it 'raises an exception when value is not of any of the types' do
28
+ target = 'foo'
29
+ expect {
30
+ TypeCheck.Type!(target, Fixnum, Array, Hash)
31
+ }.to raise_error(TypeError)
32
+ end
33
+ end
34
+
35
+ context 'Match?' do
36
+
37
+ it 'returns true when value is an exact match for at least one of the types' do
38
+ target = 'foo'
39
+ expect(TypeCheck.Match?(target, String, Array, Hash)).to be true
40
+ end
41
+
42
+ it 'returns false when value is not an exact match for at least one of the types' do
43
+ target = 'foo'
44
+ expect(TypeCheck.Match?(target, Fixnum, Array, Hash)).to be false
45
+ end
46
+ end
47
+
48
+ context 'Match!' do
49
+
50
+ it 'returns the value when value is an exact match for at least one of the types' do
51
+ target = 'foo'
52
+ expect(TypeCheck.Match!(target, String, Array, Hash)).to eq target
53
+ end
54
+
55
+ it 'raises an exception when value is not an exact match for at least one of the types' do
56
+ target = 'foo'
57
+ expect {
58
+ expect(TypeCheck.Match!(target, Fixnum, Array, Hash)).to eq target
59
+ }.to raise_error(TypeError)
60
+ end
61
+ end
62
+
63
+ context 'Child?' do
64
+
65
+ it 'returns true if value is a class and is also a match or subclass of one of types' do
66
+ target = String
67
+ expect(TypeCheck.Child?(target, Comparable, Array, Hash)).to be true
68
+ end
69
+
70
+ it 'returns false if value is not a class' do
71
+ target = 'foo'
72
+ expect(TypeCheck.Child?(target, Comparable, Array, Hash)).to be false
73
+ end
74
+
75
+ it 'returns false if value is not a subclass/match for any of the types' do
76
+ target = Fixnum
77
+ expect(TypeCheck.Child?(target, Symbol, Array, Hash)).to be false
78
+ end
79
+ end
80
+
81
+ context 'Child!' do
82
+
83
+ it 'returns the value if value is a class and is also a match or subclass of one of types' do
84
+ target = String
85
+ expect(TypeCheck.Child!(target, Comparable, Array, Hash)).to eq target
86
+ end
87
+
88
+ it 'raises an exception if value is not a class' do
89
+ target = 'foo'
90
+ expect {
91
+ TypeCheck.Child!(target, Comparable, Array, Hash)
92
+ }.to raise_error(TypeError)
93
+ end
94
+
95
+ it 'raises an exception if value is not a subclass/match for any of the types' do
96
+ target = Fixnum
97
+ expect {
98
+ TypeCheck.Child!(target, Symbol, Array, Hash)
99
+ }.to raise_error(TypeError)
100
+ end
101
+ end
102
+ end
103
+ end
@@ -0,0 +1,110 @@
1
+ require 'spec_helper'
2
+ require_relative 'abstract_struct_shared'
3
+
4
+ module Functional
5
+
6
+ describe Union do
7
+
8
+ let!(:expected_fields){ [:a, :b, :c] }
9
+ let!(:expected_values){ [42, nil, nil] }
10
+
11
+ let(:struct_class) { Union.new(*expected_fields) }
12
+ let(:struct_object) { struct_class.send(struct_class.fields.first, 42) }
13
+ let(:other_object) { struct_class.send(struct_class.fields.first, Object.new) }
14
+
15
+ it_should_behave_like :abstract_struct
16
+
17
+ context 'definition' do
18
+
19
+ it 'registers the new class with Record when given a string name' do
20
+ Union.new('Foo', :foo, :bar, :baz)
21
+ expect(defined?(Union::Foo)).to eq 'constant'
22
+ end
23
+ end
24
+
25
+ context 'factories' do
26
+
27
+ specify 'exist for each field' do
28
+ expected_fields.each do |field|
29
+ expect(struct_class).to respond_to(field)
30
+ end
31
+ end
32
+
33
+ specify 'require a value' do
34
+ expected_fields.each do |field|
35
+ expect(struct_class.method(field).arity).to eq 1
36
+ end
37
+ end
38
+
39
+ specify 'set the field appropriately' do
40
+ clazz = Union.new(:foo, :bar)
41
+ obj = clazz.foo(10)
42
+ expect(obj.field).to eq :foo
43
+ end
44
+
45
+ specify 'set the value appropriately' do
46
+ clazz = Union.new(:foo, :bar)
47
+ obj = clazz.foo(10)
48
+ expect(obj.value).to eq 10
49
+ end
50
+
51
+ specify 'return a frozen union' do
52
+ clazz = Union.new(:foo, :bar)
53
+ expect(clazz.foo(10)).to be_frozen
54
+ end
55
+
56
+ specify 'force #new to be private' do
57
+ clazz = Union.new(:foo, :bar)
58
+ expect {
59
+ clazz.new
60
+ }.to raise_error(NoMethodError)
61
+ end
62
+ end
63
+
64
+ context 'readers' do
65
+
66
+ specify '#field returns the appropriate field' do
67
+ clazz = Union.new(:foo, :bar)
68
+ expect(clazz.foo(10).field).to eq :foo
69
+ end
70
+
71
+ specify '#value returns the appropriate field' do
72
+ clazz = Union.new(:foo, :bar)
73
+ expect(clazz.foo(10).value).to eq 10
74
+ end
75
+
76
+ specify 'return the appropriate value for the set field' do
77
+ clazz = Union.new(:foo, :bar)
78
+ expect(clazz.foo(10).foo).to eq 10
79
+ end
80
+
81
+ specify 'return nil for the unset field' do
82
+ clazz = Union.new(:foo, :bar, :baz)
83
+ expect(clazz.foo(10).bar).to be_nil
84
+ expect(clazz.foo(10).baz).to be_nil
85
+ end
86
+ end
87
+
88
+ context 'predicates' do
89
+
90
+ specify 'exist for each field' do
91
+ expected_fields.each do |field|
92
+ predicate = "#{field}?".to_sym
93
+ expect(struct_object).to respond_to(predicate)
94
+ expect(struct_object.method(predicate).arity).to eq 0
95
+ end
96
+ end
97
+
98
+ specify 'return true for the set field' do
99
+ clazz = Union.new(:foo, :bar)
100
+ expect(clazz.foo(10).foo?).to be true
101
+ end
102
+
103
+ specify 'return false for the unset fields' do
104
+ clazz = Union.new(:foo, :bar, :baz)
105
+ expect(clazz.foo(10).bar?).to be false
106
+ expect(clazz.foo(10).baz?).to be false
107
+ end
108
+ end
109
+ end
110
+ end
@@ -7,13 +7,15 @@ SimpleCov.formatter = SimpleCov::Formatter::MultiFormatter[
7
7
  ]
8
8
 
9
9
  SimpleCov.start do
10
- project_name 'functional-ruby'
11
- add_filter '/md/'
12
- add_filter '/pkg/'
10
+ project_name 'Functional Ruby'
13
11
  add_filter '/spec/'
14
- add_filter '/tasks/'
15
12
  end
16
13
 
14
+ #require 'coveralls'
15
+ #Coveralls.wear!
16
+ #require 'codeclimate-test-reporter'
17
+ #CodeClimate::TestReporter.start
18
+
17
19
  require 'functional'
18
20
 
19
21
  # import all the support files
metadata CHANGED
@@ -1,27 +1,27 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: functional-ruby
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.7.7
4
+ version: 1.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jerry D'Antonio
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-01-27 00:00:00.000000000 Z
11
+ date: 2014-07-30 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
- - - '>='
17
+ - - ">="
18
18
  - !ruby/object:Gem::Version
19
19
  version: '0'
20
20
  type: :development
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
- - - '>='
24
+ - - ">="
25
25
  - !ruby/object:Gem::Version
26
26
  version: '0'
27
27
  description: |2
@@ -32,41 +32,47 @@ extensions: []
32
32
  extra_rdoc_files:
33
33
  - README.md
34
34
  - LICENSE
35
+ - doc/memo.txt
36
+ - doc/pattern_matching.txt
37
+ - doc/protocol.txt
38
+ - doc/record.txt
39
+ - doc/thread_safety.txt
35
40
  files:
36
41
  - LICENSE
37
42
  - README.md
43
+ - doc/memo.txt
44
+ - doc/pattern_matching.txt
45
+ - doc/protocol.txt
46
+ - doc/record.txt
47
+ - doc/thread_safety.txt
38
48
  - lib/functional.rb
39
- - lib/functional/behavior.rb
40
- - lib/functional/behaviour.rb
41
- - lib/functional/catalog.rb
42
- - lib/functional/collection.rb
43
- - lib/functional/inflect.rb
49
+ - lib/functional/abstract_struct.rb
50
+ - lib/functional/delay.rb
51
+ - lib/functional/either.rb
52
+ - lib/functional/memo.rb
53
+ - lib/functional/method_signature.rb
54
+ - lib/functional/option.rb
44
55
  - lib/functional/pattern_matching.rb
45
- - lib/functional/platform.rb
46
- - lib/functional/search.rb
47
- - lib/functional/sort.rb
48
- - lib/functional/utilities.rb
56
+ - lib/functional/protocol.rb
57
+ - lib/functional/protocol_info.rb
58
+ - lib/functional/record.rb
59
+ - lib/functional/type_check.rb
60
+ - lib/functional/union.rb
49
61
  - lib/functional/version.rb
50
62
  - lib/functional_ruby.rb
51
- - md/behavior.md
52
- - md/catalog.md
53
- - md/collection.md
54
- - md/inflect.md
55
- - md/pattern_matching.md
56
- - md/platform.md
57
- - md/search.md
58
- - md/sort.md
59
- - md/utilities.md
60
- - spec/functional/behavior_spec.rb
61
- - spec/functional/catalog_spec.rb
62
- - spec/functional/collection_spec.rb
63
- - spec/functional/inflect_spec.rb
64
- - spec/functional/integration_spec.rb
63
+ - spec/functional/abstract_struct_shared.rb
64
+ - spec/functional/complex_pattern_matching_spec.rb
65
+ - spec/functional/configuration_spec.rb
66
+ - spec/functional/delay_spec.rb
67
+ - spec/functional/either_spec.rb
68
+ - spec/functional/memo_spec.rb
69
+ - spec/functional/option_spec.rb
65
70
  - spec/functional/pattern_matching_spec.rb
66
- - spec/functional/platform_spec.rb
67
- - spec/functional/search_spec.rb
68
- - spec/functional/sort_spec.rb
69
- - spec/functional/utilities_spec.rb
71
+ - spec/functional/protocol_info_spec.rb
72
+ - spec/functional/protocol_spec.rb
73
+ - spec/functional/record_spec.rb
74
+ - spec/functional/type_check_spec.rb
75
+ - spec/functional/union_spec.rb
70
76
  - spec/spec_helper.rb
71
77
  homepage: https://github.com/jdantonio/functional-ruby/
72
78
  licenses:
@@ -78,29 +84,33 @@ require_paths:
78
84
  - lib
79
85
  required_ruby_version: !ruby/object:Gem::Requirement
80
86
  requirements:
81
- - - '>='
87
+ - - ">="
82
88
  - !ruby/object:Gem::Version
83
- version: 1.9.2
89
+ version: 1.9.3
84
90
  required_rubygems_version: !ruby/object:Gem::Requirement
85
91
  requirements:
86
- - - '>='
92
+ - - ">="
87
93
  - !ruby/object:Gem::Version
88
94
  version: '0'
89
95
  requirements: []
90
96
  rubyforge_project:
91
- rubygems_version: 2.2.1
97
+ rubygems_version: 2.2.2
92
98
  signing_key:
93
99
  specification_version: 4
94
- summary: Erlang and Clojure inspired functional programming tools for Ruby.
100
+ summary: Erlang, Clojure, and Haskell inspired functional programming tools to Ruby.
95
101
  test_files:
96
- - spec/functional/behavior_spec.rb
97
- - spec/functional/catalog_spec.rb
98
- - spec/functional/collection_spec.rb
99
- - spec/functional/inflect_spec.rb
100
- - spec/functional/integration_spec.rb
102
+ - spec/functional/abstract_struct_shared.rb
103
+ - spec/functional/complex_pattern_matching_spec.rb
104
+ - spec/functional/configuration_spec.rb
105
+ - spec/functional/delay_spec.rb
106
+ - spec/functional/either_spec.rb
107
+ - spec/functional/memo_spec.rb
108
+ - spec/functional/option_spec.rb
101
109
  - spec/functional/pattern_matching_spec.rb
102
- - spec/functional/platform_spec.rb
103
- - spec/functional/search_spec.rb
104
- - spec/functional/sort_spec.rb
105
- - spec/functional/utilities_spec.rb
110
+ - spec/functional/protocol_info_spec.rb
111
+ - spec/functional/protocol_spec.rb
112
+ - spec/functional/record_spec.rb
113
+ - spec/functional/type_check_spec.rb
114
+ - spec/functional/union_spec.rb
106
115
  - spec/spec_helper.rb
116
+ has_rdoc: