matchete 0.0.2 → 0.2.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: d82680012c34cb8d63c1e461711b34727036a455
4
- data.tar.gz: a23af03a534d39a1295855a959eb362ceebbda82
3
+ metadata.gz: c15b81dead014a1340a37b9172d0ae776022403e
4
+ data.tar.gz: 41f24df6592f9844db61c761244adc461a7f188d
5
5
  SHA512:
6
- metadata.gz: 29d6a30c0274d6fbe59c79dcbbc1c78c5359f76bddc2791c8afeb8980e3219bcc44e6eebe837997e4644497fd9f50dc89f7503130c3488a33757a787f2e9d4bf
7
- data.tar.gz: 9fae0969b2f2aa630d3608d38db7c91fca1a56f32ca423a0aacfbb11952bf1db45bf025a510faf96694a702e280007cf59468719bbc8138be15f7fa64385b076
6
+ metadata.gz: 374025ed07b2683c768cb4129e72ec3b0d6293282ea6356122f630271bf6d53ff198175344d98e27d8673e11e280ba3443f644d6f71b68e607e82188358b65e8
7
+ data.tar.gz: ef2763cf51026c47d1e9fd04b8087ee0ea2183c8647c68414159af74b79e6bf771d216373130249bcc0a9a37bca162968733400316b8d647aedba0cc39618b18
data/README.md CHANGED
@@ -5,10 +5,26 @@ Matchete provides a DSL for method overloading based on pattern matching for Rub
5
5
 
6
6
  It's just a quick hack inspired by weissbier and the use-return-values-of-method-definitions DSL technique used in [harmonic](https://github.com/s2gatev/harmonic)
7
7
 
8
+ **It supports only ruby 2.1+**
9
+
10
+ Features
11
+ --------
12
+
13
+ * `on [:value, Integer]` matches an arg with the same internal structure
14
+ * `on '#method_name'` matches args responding to `method_name`
15
+ * `on AClass` matches instances of `AClass`
16
+ * `on a: 2, method:...` matches keyword args
17
+ * `on :test?` matches with user-defined predicate methods
18
+ * `on either('#count', Array)` matches if any of the tests returns true for an arg
19
+ * `on full_match('#count', '#combine')` matches if all of the tests return true for an arg
20
+
21
+
22
+
8
23
  Install
9
24
  -----
10
25
  `gem install matchete`
11
26
 
27
+
12
28
  Usage
13
29
  -----
14
30
 
@@ -34,70 +50,99 @@ FactorialStrikesAgain.new.factorial(-2) #Matchete::NotResolvedError No matching
34
50
  ```
35
51
 
36
52
  ```ruby
37
- require 'matchete'
38
-
39
53
  class Converter
40
54
  include Matchete
41
55
 
56
+ on '#special_convert',
57
+ def convert(value)
58
+ value.special_convert
59
+ end
60
+
42
61
  on Integer,
43
62
  def convert(value)
44
63
  [:integer, value]
45
64
  end
46
-
65
+
47
66
  on Hash,
48
67
  def convert(values)
49
68
  [:dict, values.map { |k, v| [convert(k), convert(v)] }]
50
69
  end
51
-
70
+
52
71
  on /reserved_/,
53
72
  def convert(value)
54
73
  [:reserved_symbol, value]
55
74
  end
56
-
75
+
57
76
  on String,
58
77
  def convert(value)
59
78
  [:string, value]
60
79
  end
61
-
80
+
62
81
  on ['deleted', [Integer, Any]],
63
82
  def convert(value)
64
83
  ['deleted', value[1]]
65
84
  end
66
-
67
- on :not_implemented?,
85
+
86
+ on :starts_with_cat?,
68
87
  def convert(value)
69
88
  [:fail, value]
70
89
  end
71
-
90
+
72
91
  on free: Integer, method:
73
92
  def convert(free:)
74
93
  [:rofl, free]
75
94
  end
76
95
 
96
+ on either('#count', Array),
97
+ def convert(value)
98
+ value.count
99
+ end
100
+
101
+ on full_match('#count', '#lala'),
102
+ def convert(value)
103
+ value.count + value.lala
104
+ end
105
+
77
106
  default def convert(value)
78
107
  [:z, value]
79
108
  end
80
-
81
- def not_implemented?(value)
82
- value.is_a? Symbol
109
+
110
+ def starts_with_cat?(value)
111
+ value.to_s.start_with?('cat')
112
+ end
113
+ end
114
+
115
+ class Z
116
+ def special_convert
117
+ [:special_convert, nil]
83
118
  end
84
119
  end
85
120
 
86
121
  converter = Converter.new
122
+ p Converter.instance_methods
87
123
  p converter.convert(2) #[:integer, 2]
124
+ p converter.convert(Z.new) #[:special_convert, nil]
125
+ p converter.convert([4, 4]) # 2
88
126
  p converter.convert({2 => 4}) #[:dict, [[[:integer, 2], [:integer, 4]]]
89
- p converter.convert('reserved_l') #[;reserved_symbol, 'l']
127
+ p converter.convert('reserved_l') #[:reserved_symbol, 'reserved_l']
90
128
  p converter.convert('zaza') #[:string, 'zaza']
91
129
  p converter.convert(['deleted', [2, Array]]) #['deleted', [2, Array]]
92
- p converter.convert(:f) #[:fail, :f]
130
+ p converter.convert(:cat_hehe) #[:fail, :cat_hehe]
93
131
  p converter.convert(free: 2) #[:rofl, 2]
94
132
  p converter.convert(2.2) #[:z, 2.2]
133
+
95
134
  ```
135
+ cbb
136
+ -----
137
+ ![](https://global3.memecdn.com/kawaii-danny-trejo_o_2031011.jpg)
96
138
 
97
139
  Todo
98
140
  -----
141
+ * Clean up the specs, right now they're a mess.
142
+ * Fix all kinds of edge cases
143
+
99
144
 
100
145
  Copyright
101
146
  -----
102
147
 
103
- Copyright (c) 2014 Alexander Ivanov. See LICENSE for further details.
148
+ Copyright (c) 2015 Alexander Ivanov. See LICENSE for further details.
data/lib/matchete.rb CHANGED
@@ -32,6 +32,14 @@ module Matchete
32
32
  convert_to_matcher method_name
33
33
  end
34
34
 
35
+ def either(*guards)
36
+ -> arg { guards.any? { |g| match_guard(g, arg) } }
37
+ end
38
+
39
+ def full_match(*guards)
40
+ -> arg { guards.all? { |g| match_guard(g, arg) } }
41
+ end
42
+
35
43
  def supporting(*method_names)
36
44
  -> object do
37
45
  method_names.all? do |method_name|
@@ -46,22 +54,22 @@ module Matchete
46
54
  end
47
55
  end
48
56
  end
49
-
57
+
50
58
  def call_overloaded(method_name, args: [], kwargs: {})
51
59
  handler = find_handler(method_name, args, kwargs)
52
- if handler.parameters.any? do |type, _|
53
- [:key, :keyrest, :keyreq].include? type
54
- end
55
- handler.bind(self).call *args, **kwargs
56
- else
60
+
61
+ if kwargs.empty?
57
62
  handler.bind(self).call *args
63
+ else
64
+ handler.bind(self).call *args, **kwargs
58
65
  end
59
66
  #insane workaround, because if you have
60
67
  #def z(f);end
61
68
  #and you call it like that
62
- #a(2, **{e: 4})
69
+ #empty = {}
70
+ #z(2, **empty)
63
71
  #it raises wrong number of arguments (2 for 1)
64
- #clean later
72
+ #clean up later
65
73
  end
66
74
 
67
75
  def find_handler(method_name, args, kwargs)
@@ -77,12 +85,13 @@ module Matchete
77
85
  raise NotResolvedError.new("No matching #{method_name} method for args #{args}")
78
86
  end
79
87
  else
80
- guards[2]
88
+ guards.last
81
89
  end
82
90
  end
83
91
 
84
92
  def match_guards(guard_args, guard_kwargs, args, kwargs)
85
- return false if guard_args.count != args.count || guard_kwargs.count != kwargs.count
93
+ return false if guard_args.count != args.count ||
94
+ guard_kwargs.count != kwargs.count
86
95
  guard_args.zip(args).all? do |guard, arg|
87
96
  match_guard guard, arg
88
97
  end and
@@ -92,20 +101,25 @@ module Matchete
92
101
  end
93
102
 
94
103
  def match_guard(guard, arg)
104
+ p
95
105
  case guard
96
106
  when Module
97
107
  arg.is_a? guard
98
108
  when Symbol
99
109
  send guard, arg
100
110
  when Proc
101
- guard.call arg
111
+ instance_exec arg, &guard
102
112
  when Regexp
103
113
  arg.is_a? String and guard.match arg
104
114
  when Array
105
115
  arg.is_a?(Array) and
106
116
  guard.zip(arg).all? { |child_guard, child| match_guard child_guard, child }
107
117
  else
108
- guard == arg
118
+ if guard.is_a?(String) && guard[0] == '#'
119
+ arg.respond_to? guard[1..-1]
120
+ else
121
+ guard == arg
122
+ end
109
123
  end
110
124
  end
111
125
  end
data/matchete.gemspec CHANGED
@@ -3,7 +3,7 @@ $:.push File.expand_path("../lib", __FILE__)
3
3
 
4
4
  Gem::Specification.new do |s|
5
5
  s.name = 'matchete'
6
- s.version = '0.0.2'
6
+ s.version = '0.2.0'
7
7
  s.platform = Gem::Platform::RUBY
8
8
  s.authors = ["Alexander Ivanov"]
9
9
  s.email = ["alehander42@gmail.com"]
@@ -12,10 +12,10 @@ Gem::Specification.new do |s|
12
12
  s.description = %q{A DSL for method overloading for Ruby based on pattern matching}
13
13
 
14
14
  s.add_development_dependency 'rspec', '~> 0'
15
-
15
+
16
16
  s.license = 'MIT'
17
17
  s.files = `git ls-files`.split("\n")
18
18
  s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
19
19
  s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
20
20
  s.require_paths = ["lib"]
21
- end
21
+ end
@@ -20,8 +20,8 @@ describe Matchete do
20
20
  end
21
21
 
22
22
  a = A.new
23
- a.play(2).should eq :integer
24
- a.play(2.2, 4).should eq :float
23
+ expect(a.play(2)).to eq :integer
24
+ expect(a.play(2.2, 4)).to eq :float
25
25
  end
26
26
 
27
27
  it 'can use a pattern based on classes and modules' do
@@ -45,9 +45,9 @@ describe Matchete do
45
45
  end
46
46
 
47
47
  a = A.new
48
- a.play(2).should eq :integer
49
- a.play(2.2).should eq :float
50
- a.play([2]).should eq :enumerable
48
+ expect(a.play(2)).to eq :integer
49
+ expect(a.play(2.2)).to eq :float
50
+ expect(a.play([2])).to eq :enumerable
51
51
  end
52
52
 
53
53
  it 'can use a pattern based on nested arrays with classes/modules' do
@@ -66,8 +66,8 @@ describe Matchete do
66
66
  end
67
67
 
68
68
  a = A.new
69
- a.play([2, 2.2]).should eq [:integer, :float]
70
- a.play([[2], Matchete]).should eq :s
69
+ expect(a.play([2, 2.2])).to eq [:integer, :float]
70
+ expect(a.play([[2], Matchete])).to eq :s
71
71
  end
72
72
 
73
73
  it 'can use a pattern based on exact values' do
@@ -86,9 +86,9 @@ describe Matchete do
86
86
  end
87
87
 
88
88
  a = A.new
89
- a.play(2, 4).should eq 2
90
- a.play(4, 4).should eq 4
91
- -> { a.play(8, 2) }.should raise_error(Matchete::NotResolvedError)
89
+ expect(a.play(2, 4)).to eq 2
90
+ expect(a.play(4, 4)).to eq 4
91
+ expect { a.play(8, 2) }.to raise_error(Matchete::NotResolvedError)
92
92
  end
93
93
 
94
94
  it 'can use a pattern based on regexes' do
@@ -107,8 +107,8 @@ describe Matchete do
107
107
  end
108
108
 
109
109
  a = A.new
110
- a.play('zewr').should eq 'z'
111
- a.play('yy').should eq 'y'
110
+ expect(a.play('zewr')).to eq 'z'
111
+ expect(a.play('yy')).to eq 'y'
112
112
  end
113
113
 
114
114
  it 'can use a default method when everything else fails' do
@@ -121,15 +121,15 @@ describe Matchete do
121
121
  end
122
122
  end
123
123
 
124
- -> { A.new.play(2.2) }.should raise_error(Matchete::NotResolvedError)
125
-
124
+ expect { A.new.play(2.2) }.to raise_error(Matchete::NotResolvedError)
125
+
126
126
  class A
127
127
  default def play(value)
128
128
  :else
129
129
  end
130
130
  end
131
131
 
132
- A.new.play(2.2).should eq :else
132
+ expect(A.new.play(2.2)).to eq :else
133
133
  end
134
134
 
135
135
  it 'can use a pattern based on existing predicate methods given as symbols' do
@@ -140,14 +140,14 @@ describe Matchete do
140
140
  def play(value)
141
141
  value
142
142
  end
143
-
143
+
144
144
  def even?(value)
145
145
  value.remainder(2).zero? #so gay and gay
146
146
  end
147
147
  end
148
148
 
149
- A.new.play(2).should eq 2
150
- -> { A.new.play(5) }.should raise_error(Matchete::NotResolvedError)
149
+ expect(A.new.play(2)).to eq 2
150
+ expect { A.new.play(5) }.to raise_error(Matchete::NotResolvedError)
151
151
  end
152
152
 
153
153
  it 'can use a pattern based on a lambda predicate' do
@@ -160,8 +160,8 @@ describe Matchete do
160
160
  end
161
161
  end
162
162
 
163
- A.new.play(2).should eq 2
164
- -> { A.new.play(7) }.should raise_error(Matchete::NotResolvedError)
163
+ expect(A.new.play(2)).to eq 2
164
+ expect { A.new.play(7) }.to raise_error(Matchete::NotResolvedError)
165
165
  end
166
166
 
167
167
  it 'can use a pattern based on responding to methods' do
@@ -174,8 +174,8 @@ describe Matchete do
174
174
  end
175
175
  end
176
176
 
177
- A.new.play([]).should eq []
178
- -> { A.new.play(4) }.should raise_error(Matchete::NotResolvedError)
177
+ expect(A.new.play([])).to eq []
178
+ expect { A.new.play(4) }.to raise_error(Matchete::NotResolvedError)
179
179
  end
180
180
 
181
181
  it 'can match on different keyword arguments' do
@@ -188,8 +188,8 @@ describe Matchete do
188
188
  end
189
189
  end
190
190
 
191
- A.new.play(e: 0, f: "y").should eq :y
192
- -> { A.new.play(e: "f", f: Class)}.should raise_error(Matchete::NotResolvedError)
191
+ expect(A.new.play(e: 0, f: "y")).to eq :y
192
+ expect { A.new.play(e: "f", f: Class)}.to raise_error(Matchete::NotResolvedError)
193
193
  end
194
194
 
195
195
  it 'can match on multiple different kinds of patterns' do
@@ -197,7 +197,7 @@ describe Matchete do
197
197
  include Matchete
198
198
  end
199
199
 
200
- A.new.match_guards([Integer, Float], {}, [8, 8.8], {}).should be_true
200
+ expect(A.new.match_guards([Integer, Float], {}, [8, 8.8], {})).to be_truthy
201
201
  end
202
202
 
203
203
  describe '#match_guard' do
@@ -213,33 +213,33 @@ describe Matchete do
213
213
  end
214
214
 
215
215
  it 'matches modules and classes' do
216
- @a.match_guard(Integer, 2).should be_true
217
- @a.match_guard(Class, 4).should be_false
216
+ expect(@a.match_guard(Integer, 2)).to be_truthy
217
+ expect(@a.match_guard(Class, 4)).to be_falsey
218
218
  end
219
219
 
220
220
  it 'matches methods given as symbols' do
221
- @a.match_guard(:even?, 2).should be_true
222
- -> { @a.match_guard(:odd?, 4) }.should raise_error
221
+ expect(@a.match_guard(:even?, 2)).to be_truthy
222
+ expect { @a.match_guard(:odd?, 4) }.to raise_error
223
223
  end
224
224
 
225
225
  it 'matches predicates given as lambdas' do
226
- @a.match_guard(-> x { x == {} }, {}).should be_true
226
+ expect(@a.match_guard(-> x { x == {} }, {})).to be_truthy
227
227
  end
228
228
 
229
229
  it 'matches on regex' do
230
- @a.match_guard(/a/, 'aw').should be_true
231
- @a.match_guard(/z/, 'lol').should be_false
230
+ expect(@a.match_guard(/a/, 'aw')).to be_truthy
231
+ expect(@a.match_guard(/z/, 'lol')).to be_falsey
232
232
  end
233
233
 
234
234
  it 'matches on nested arrays' do
235
- @a.match_guard([Integer, [:even?]], [2, [4]]).should be_true
236
- @a.match_guard([Float, [:even?]], [2.2, [7]]).should be_false
235
+ expect(@a.match_guard([Integer, [:even?]], [2, [4]])).to be_truthy
236
+ expect(@a.match_guard([Float, [:even?]], [2.2, [7]])).to be_falsey
237
237
  end
238
238
 
239
239
  it 'matches on exact values' do
240
- @a.match_guard(2, 2).should be_true
241
- @a.match_guard('d', 'f').should be_false
240
+ expect(@a.match_guard(2, 2)).to be_truthy
241
+ expect(@a.match_guard('d', 'f')).to be_falsey
242
242
  end
243
243
  end
244
244
  end
245
-
245
+
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: matchete
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.2
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Alexander Ivanov
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-03-20 00:00:00.000000000 Z
11
+ date: 2015-06-03 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rspec
@@ -60,8 +60,10 @@ required_rubygems_version: !ruby/object:Gem::Requirement
60
60
  version: '0'
61
61
  requirements: []
62
62
  rubyforge_project:
63
- rubygems_version: 2.2.2
63
+ rubygems_version: 2.4.6
64
64
  signing_key:
65
65
  specification_version: 4
66
66
  summary: Method overloading for Ruby based on pattern matching
67
- test_files: []
67
+ test_files:
68
+ - spec/matchete_spec.rb
69
+ - spec/spec_helper.rb