eqq 0.0.2 → 0.0.7

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: fd093a7aa8c034327d463c56bfe120a8ecc48b52649ba7900491f05cc130cc38
4
- data.tar.gz: 13f7ca2f2f40d9be41abd4408f5486b892f345347eb07eeb3f4d936c47cc92ab
3
+ metadata.gz: becfb749a93e73ea402265899e57d3deea45bf0eb457a29a66eafa03965b1572
4
+ data.tar.gz: 3f6578bd2f0b3334369834ff1f344b4b033318172586a9324496027a057507a0
5
5
  SHA512:
6
- metadata.gz: 2e510f5313e0f890bf3c8277a413f937b0a26e2ba58e501591288556783bc5fffc944c23a1216ddf95308a111b06c6ac82557526d9f7de49ef9dbe7806f93bb6
7
- data.tar.gz: 719905cbd2f71a388e13ca0427b7db49115513ce11395a436d8ef9fc43397c9c77cc408135862147bbfc3bac3fb36615332752f56ab28e4136bc74b8db3f97dd
6
+ metadata.gz: 3d76a45da1f1e181d77b6f9cbfc6f80d88af6abed0782b1da92f6562934bf551c2f55e5691be7108d0acf0521562a042bb5cba6f54f9846af78b7ba4031d35fb
7
+ data.tar.gz: 2ec4137407dfaf6b4189255532e59669798ac9ed57be8e6ecdb07c31525d132b9246da9d9fd6b98975e31b712e002e2693f523acf285d172df1b13c7c46617d5
data/README.md CHANGED
@@ -3,9 +3,7 @@
3
3
  ![Build Status](https://github.com/kachick/eqq/actions/workflows/test_behaviors.yml/badge.svg?branch=main)
4
4
  [![Gem Version](https://badge.fury.io/rb/eqq.png)](http://badge.fury.io/rb/eqq)
5
5
 
6
- Pattern objects builder.
7
-
8
- `eqq` means `#===`
6
+ Pattern objects builder
9
7
 
10
8
  ## Usage
11
9
 
@@ -14,7 +12,7 @@ Require Ruby 2.6 or later
14
12
  Add below code into your Gemfile
15
13
 
16
14
  ```ruby
17
- gem 'eqq', '0.0.2'
15
+ gem 'eqq', '>= 0.0.7', '< 0.1.0'
18
16
  ```
19
17
 
20
18
  ### Overview
@@ -26,13 +24,133 @@ require 'eqq'
26
24
  [42, nil, true, false, '', 0].grep(Eqq.BOOLEAN) #=> [true, false]
27
25
  [42, [], {}, 'string', Object.new, nil].grep(Eqq.CAN(:to_h)) #=> [[], {}, nil]
28
26
 
29
- pattern = Eqq.define do
27
+ pattern = Eqq.build do
30
28
  OR(AND(Float, 20..50), Integer)
31
29
  end
30
+
31
+ p pattern #=> "OR(AND(Float, 20..50), Integer)"
32
32
  [4.2, 42, 42.0, 420].grep(pattern) #=> [42, 42.0, 420]
33
+
34
+ inverted = Eqq.NOT(pattern)
35
+ p inverted #=> "NOT(OR(AND(Float, 20..50), Integer))"
36
+ [4.2, 42, 42.0, 420].grep(inverted) #=> [4.2]
37
+
38
+ Eqq.SEND(:all?, pattern) === [4.2, 42, 42.0, 420] #=> false
39
+ Eqq.SEND(:any?, pattern) === [4.2, 42, 42.0, 420] #=> true
40
+
41
+ ret_in_case = (
42
+ case 42
43
+ when pattern
44
+ 'Should be matched here! :)'
45
+ when inverted
46
+ 'Should not be matched here! :<'
47
+ else
48
+ 'Should not be matched here too! :<'
49
+ end
50
+ )
51
+
52
+ p ret_in_case #=> Should be matched here! :)
53
+
54
+ ret_in_case = (
55
+ case 4.2
56
+ when pattern
57
+ 'Should not be matched here! :<'
58
+ when inverted
59
+ 'Should be matched here! :)'
60
+ else
61
+ 'Should not be matched here too! :<'
62
+ end
63
+ )
64
+
65
+ p ret_in_case #=> Should be matched here! :)
66
+
67
+ class MyClass
68
+ include Eqq::Buildable
69
+
70
+ def example
71
+ [4.2, 42, 42.0, 420].grep(OR(AND(Float, 20..50), Integer))
72
+ end
73
+ end
74
+ MyClass.new.example #=> [42, 42.0, 420]
33
75
  ```
34
76
 
77
+ ### Explanation
78
+
79
+ All products can be called as `pattern === other`.
80
+
81
+ This signature will fit in most Ruby code.
82
+
83
+ * `case ~ when` syntax
84
+ * Enumerable#grep
85
+ * Enumerable#grep_v
86
+ * Enumerable#all?
87
+ * Enumerable#any?
88
+ * Enumerable#none?
89
+ * Enumerable#one?
90
+ * Enumerable#slice_after
91
+ * Enumerable#slice_before
92
+
93
+ They can take this interface as the `pattern`.
94
+
95
+ And you already saw. All of patterns can be mixed with other patterns as a parts.
96
+ Reuse as you wish!
97
+
98
+ ### Builders
99
+
100
+ * OR(*patterns) - Product returns `true` when matched even one pattern
101
+ * AND(*patterns) - Product returns `true` when matched all patterns
102
+ * NOT(pattern) - Product returns `true` when not matched the pattern
103
+ * CAN(*method_names) - Product returns `true` when it has all of the methods (checked with `respond_to?`)
104
+ * RESCUE(exception_class/module, pattern) - Product returns `true` when the pattern raises the exception
105
+ * QUIET(*patterns) - Product returns `true` when all patterns did not raise any exception
106
+ * EQ(object) - Product returns `true` when matched with `#==`
107
+ * SAME(object) - Product returns `true` when matched with `#equal?`
108
+ * SEND(name, pattern) - Basically provided for Enumerable
109
+ * BOOLEAN() - Product returns `true` when matched to `true` or `false`
110
+ * NIL() - Product returns `true` when matched to `nil` (Not consider `nil?`)
111
+ * ANYTHING() - Product returns `true`, always `true`
112
+ * NEVER() - Product returns `false`, always `false`
113
+ * XOR(pattern1, pattern2) - Product returns `true` when matched one of the pattern, when matched both returns `false`
114
+ * NAND(*patterns) - Product is an inverted `AND`
115
+ * NOR(*patterns) - Product is an inverted `OR`
116
+
117
+ ### Best fit for RSpec's `satisfy` matcher too
118
+
119
+ All builders actually generate a `Proc (lambda)` instance.
120
+ The signature will fit for RSpec's built-in [`satisfy` matcher](https://relishapp.com/rspec/rspec-expectations/v/3-10/docs/built-in-matchers/satisfy-matcher) too.
121
+
122
+ ```ruby
123
+ RSpec.describe RSpec::Matchers::BuiltIn::Satisfy do
124
+ let(:product) { Eqq.AND(Integer, 24..42) }
125
+
126
+ it 'perfectly works' do
127
+ expect(23).not_to satisfy(&product)
128
+ expect(24).to satisfy(&product)
129
+ expect(24.0).not_to satisfy(&product)
130
+ expect(42).to satisfy(&product)
131
+ expect(42.0).not_to satisfy(&product)
132
+ expect(43).not_to satisfy(&product)
133
+ end
134
+ end
135
+ ```
136
+
137
+ ### Use builders without receiver specifying
138
+
139
+ When you felt annoy to write `Eqq` in many place, some ways exist.
140
+
141
+ * `Eqq.build(&block)` - In the block scope, all builder methods can be used without receiver
142
+ * `extend Eqq::Buildable` - In the class/module, all builders can be used as class methods
143
+ * `include Eqq::Buildable` - In the class/module, all builders can be used as instance methods
144
+
145
+ ### Signature
146
+
147
+ * This gem provides [ruby/rbs](https://github.com/ruby/rbs) signature file
148
+
35
149
  ## Links
36
150
 
37
151
  * [Repository](https://github.com/kachick/eqq)
38
152
  * [API documents](https://kachick.github.io/eqq)
153
+
154
+ ## NOTE
155
+
156
+ * [`eqq` is the implementation name of `#===` in CRuby](https://github.com/ruby/ruby/blob/2a685da1fcd928530509e99f5edb4117bc377994/range.c#L1859)
data/lib/eqq.rb CHANGED
@@ -4,21 +4,18 @@
4
4
  # Copyright (c) 2011 Kenichi Kamiya
5
5
  # Forked from https://github.com/kachick/validation at 2021
6
6
 
7
- require_relative 'eqq/buildable'
8
7
  require_relative 'eqq/version'
9
8
 
9
+ # Pattern objects builder
10
10
  module Eqq
11
- extend Buildable
12
-
11
+ # Base error of this library
13
12
  class Error < StandardError; end
14
- class InvalidProductError < Error; end
15
13
 
16
- class DSLScope
17
- include Buildable
18
- end
14
+ # Raised when found some products are invalid as a pattern object
15
+ class InvalidProductError < Error; end
19
16
 
20
17
  class << self
21
- def valid?(object)
18
+ def pattern?(object)
22
19
  case object
23
20
  when Proc, Method
24
21
  object.arity == 1
@@ -31,11 +28,41 @@ module Eqq
31
28
  end
32
29
  end
33
30
 
34
- def define(&block)
31
+ # @deprecated Use {pattern?} instead. This will be dropped since `0.1.0`
32
+ def valid?(object)
33
+ pattern?(object)
34
+ end
35
+
36
+ # @api private
37
+ def satisfy?(object)
38
+ (Proc === object) && object.lambda? && (object.arity == 1) && object.respond_to?(:inspect)
39
+ end
40
+
41
+ # @return [Proc]
42
+ # @raise [InvalidProductError] if the return value is not looks to be built with builders
43
+ def build(&block)
44
+ raise ArgumentError, 'might be mis used the `Eqq.build` in your code' unless block
45
+
35
46
  pattern = DSLScope.new.instance_exec(&block)
36
- raise InvalidProductError unless valid?(pattern)
47
+ raise InvalidProductError, 'might be mis used the `Eqq.build` in your code' unless satisfy?(pattern)
37
48
 
38
49
  pattern
39
50
  end
51
+
52
+ # @deprecated Use {build} instead. This will be dropped since `0.1.0`
53
+ def define(&block)
54
+ build(&block)
55
+ end
56
+ end
57
+ end
58
+
59
+ require_relative 'eqq/buildable'
60
+
61
+ module Eqq
62
+ extend Buildable
63
+
64
+ class DSLScope
65
+ include Buildable
40
66
  end
67
+ private_constant(:DSLScope)
41
68
  end
data/lib/eqq/buildable.rb CHANGED
@@ -2,20 +2,69 @@
2
2
  # frozen_string_literal: true
3
3
 
4
4
  module Eqq
5
+ # Actually having definitions for the pattern builders
5
6
  module Buildable
6
- extend self
7
+ class << self
8
+ # When the inspection is failed some unexpected reasons, it will fallback to this value
9
+ # This value is not fixed as a spec, might be changed in future
10
+ INSPECTION_FALLBACK = 'UninspectableObject'
7
11
 
12
+ # @api private
13
+ # @return [String]
14
+ def safe_inspect_for(object)
15
+ String.try_convert(object.inspect) || INSPECTION_FALLBACK
16
+ rescue Exception
17
+ # This implementation used `RSpec::Support::ObjectFormatter::UninspectableObjectInspector` as a reference, thank you!
18
+ # ref: https://github.com/kachick/times_kachick/issues/97
19
+ singleton_class = class << object; self; end
20
+ begin
21
+ klass = singleton_class.ancestors.detect { |ancestor| !ancestor.equal?(singleton_class) }
22
+ native_object_id = '%#016x' % (object.__id__ << 1)
23
+ "#<#{klass}:#{native_object_id}>"
24
+ rescue Exception
25
+ INSPECTION_FALLBACK
26
+ end
27
+ end
28
+
29
+ # @api private
30
+ # @return [void]
31
+ def define_inspect_on(product, name:, arguments:)
32
+ inspect = "#{name}(#{arguments.map { |argument| safe_inspect_for(argument) }.join(', ')})".freeze
33
+ product.define_singleton_method(:inspect) do
34
+ inspect
35
+ end
36
+ end
37
+
38
+ # @api private
39
+ # @return [void]
40
+ def validate_patterns(*patterns)
41
+ invalids = patterns.reject { |pattern| Eqq.pattern?(pattern) }
42
+ invalid_inspections = invalids.map { |invalid| safe_inspect_for(invalid) }.join(', ')
43
+ raise ArgumentError, "given `#{invalid_inspections}` are invalid as pattern objects" unless invalids.empty?
44
+ end
45
+ end
46
+
47
+ # Product returns `true` when matched all patterns
48
+ #
8
49
  # @param pattern1 [Proc, Method, #===]
9
50
  # @param pattern2 [Proc, Method, #===]
10
51
  # @param patterns [Array<Proc, Method, #===>]
11
52
  # @return [Proc]
12
- # this lambda return true if match all patterns
13
53
  def AND(pattern1, pattern2, *patterns)
14
- ->v {
15
- [pattern1, pattern2, *patterns].all? { |pattern| pattern === v }
54
+ patterns = [pattern1, pattern2, *patterns].freeze
55
+ Buildable.validate_patterns(*patterns)
56
+
57
+ product = ->v {
58
+ patterns.all? { |pattern| pattern === v }
16
59
  }
60
+
61
+ Buildable.define_inspect_on(product, name: 'AND', arguments: patterns)
62
+
63
+ product
17
64
  end
18
65
 
66
+ # Product is an inverted {#AND}
67
+ #
19
68
  # @param pattern1 [Proc, Method, #===]
20
69
  # @param pattern2 [Proc, Method, #===]
21
70
  # @param patterns [Array<Proc, Method, #===>]
@@ -24,17 +73,26 @@ module Eqq
24
73
  NOT(AND(pattern1, pattern2, *patterns))
25
74
  end
26
75
 
76
+ # Product returns `true` when matched even one pattern
77
+ #
27
78
  # @param pattern1 [Proc, Method, #===]
28
79
  # @param pattern2 [Proc, Method, #===]
29
80
  # @param patterns [Array<Proc, Method, #===>]
30
81
  # @return [Proc]
31
- # this lambda return true if match a any pattern
32
82
  def OR(pattern1, pattern2, *patterns)
33
- ->v {
34
- [pattern1, pattern2, *patterns].any? { |pattern| pattern === v }
83
+ patterns = [pattern1, pattern2, *patterns].freeze
84
+ Buildable.validate_patterns(*patterns)
85
+
86
+ product = ->v {
87
+ patterns.any? { |pattern| pattern === v }
35
88
  }
89
+ Buildable.define_inspect_on(product, name: 'OR', arguments: patterns)
90
+
91
+ product
36
92
  end
37
93
 
94
+ # Product is an inverted {#OR}
95
+ #
38
96
  # @param pattern1 [Proc, Method, #===]
39
97
  # @param pattern2 [Proc, Method, #===]
40
98
  # @param patterns [Array<Proc, Method, #===>]
@@ -43,56 +101,72 @@ module Eqq
43
101
  NOT(OR(pattern1, pattern2, *patterns))
44
102
  end
45
103
 
104
+ # Product returns `true` when matched one of the pattern, when matched both returns `false`
105
+ #
46
106
  # @param pattern1 [Proc, Method, #===]
47
107
  # @param pattern2 [Proc, Method, #===]
48
- # @param patterns [Array<Proc, Method, #===>]
49
108
  # @return [Proc]
50
- def XOR(pattern1, pattern2, *patterns)
51
- ->v {
52
- [pattern1, pattern2, *patterns].one? { |pattern| pattern === v }
109
+ def XOR(pattern1, pattern2)
110
+ patterns = [pattern1, pattern2].freeze
111
+ Buildable.validate_patterns(*patterns)
112
+
113
+ product = ->v {
114
+ patterns.one? { |pattern| pattern === v }
53
115
  }
54
- end
116
+ Buildable.define_inspect_on(product, name: 'XOR', arguments: patterns)
55
117
 
56
- # @param pattern1 [Proc, Method, #===]
57
- # @param pattern2 [Proc, Method, #===]
58
- # @param patterns [Array<Proc, Method, #===>]
59
- # @return [Proc]
60
- def XNOR(pattern1, pattern2, *patterns)
61
- NOT(XOR(pattern1, pattern2, *patterns))
118
+ product
62
119
  end
63
120
 
121
+ # Product returns `true` when not matched the pattern
122
+ #
64
123
  # @param pattern [Proc, Method, #===]
65
124
  # @return [Proc]
66
125
  def NOT(pattern)
67
- raise ArgumentError, 'wrong object for pattern' unless Eqq.valid?(pattern)
126
+ Buildable.validate_patterns(pattern)
68
127
 
69
- ->v { !(pattern === v) }
128
+ product = ->v { !(pattern === v) }
129
+
130
+ Buildable.define_inspect_on(product, name: 'NOT', arguments: [pattern])
131
+
132
+ product
70
133
  end
71
134
 
72
- # A pattern builder.
135
+ # Product returns `true` when matched with `#==`
136
+ #
73
137
  # @param obj [#==]
74
138
  # @return [Proc]
75
139
  def EQ(obj)
76
- ->v { obj == v }
140
+ product = ->v { obj == v }
141
+ Buildable.define_inspect_on(product, name: 'EQ', arguments: [obj])
142
+ product
77
143
  end
78
144
 
145
+ # Product returns `true` when matched with `#equal?`
146
+ #
79
147
  # @param obj [#equal?]
80
148
  # @return [Proc]
81
149
  def SAME(obj)
82
- ->v { obj.equal?(v) }
150
+ product = ->v { obj.equal?(v) }
151
+ Buildable.define_inspect_on(product, name: 'SAME', arguments: [obj])
152
+ product
83
153
  end
84
154
 
85
- # @param message1 [Symbol, String]
86
- # @param messages [Array<Symbol, String>]
155
+ # Product returns `true` when it has all of the methods (checked with `respond_to?`)
156
+ #
157
+ # @param message1 [Symbol, String, #to_sym]
158
+ # @param messages [Array<Symbol, String, #to_sym>]
87
159
  # @return [Proc]
88
160
  def CAN(message1, *messages)
89
- messages = begin
90
- [message1, *messages].map(&:to_sym)
91
- rescue NoMethodError
92
- raise ArgumentError
93
- end
161
+ messages = (
162
+ begin
163
+ [message1, *messages].map(&:to_sym).freeze
164
+ rescue NoMethodError
165
+ raise ArgumentError
166
+ end
167
+ )
94
168
 
95
- ->v {
169
+ product = ->v {
96
170
  messages.all? { |message|
97
171
  begin
98
172
  v.respond_to?(message)
@@ -101,18 +175,22 @@ module Eqq
101
175
  end
102
176
  }
103
177
  }
178
+
179
+ Buildable.define_inspect_on(product, name: 'CAN', arguments: messages)
180
+
181
+ product
104
182
  end
105
183
 
184
+ # Product returns `true` when all patterns did not raise any exception
185
+ #
106
186
  # @param pattern1 [Proc, Method, #===]
107
187
  # @param patterns [Array<Proc, Method, #===>]
108
188
  # @return [Proc]
109
189
  def QUIET(pattern1, *patterns)
110
- patterns = [pattern1, *patterns]
111
- unless patterns.all? { |pattern| Eqq.valid?(pattern) }
112
- raise ArgumentError, 'wrong object for pattern'
113
- end
190
+ patterns = [pattern1, *patterns].freeze
191
+ Buildable.validate_patterns(*patterns)
114
192
 
115
- ->v {
193
+ product = ->v {
116
194
  patterns.all? { |pattern|
117
195
  begin
118
196
  pattern === v
@@ -123,16 +201,22 @@ module Eqq
123
201
  end
124
202
  }
125
203
  }
204
+
205
+ Buildable.define_inspect_on(product, name: 'QUIET', arguments: patterns)
206
+
207
+ product
126
208
  end
127
209
 
210
+ # Product returns `true` when the pattern raises the exception
211
+ #
128
212
  # @param mod [Module]
129
213
  # @param pattern [Proc, Method, #===]
130
214
  # @return [Proc]
131
215
  def RESCUE(mod, pattern)
132
- raise ArgumentError unless Eqq.valid?(pattern)
216
+ Buildable.validate_patterns(pattern)
133
217
  raise ArgumentError unless Module === mod
134
218
 
135
- ->v {
219
+ product = ->v {
136
220
  begin
137
221
  pattern === v
138
222
  false
@@ -142,31 +226,76 @@ module Eqq
142
226
  false
143
227
  end
144
228
  }
229
+
230
+ Buildable.define_inspect_on(product, name: 'RESCUE', arguments: [mod, pattern])
231
+
232
+ product
145
233
  end
146
234
 
147
- # @param name [Symbol, #to_sym]
235
+ # Basically provided for Enumerable
236
+ #
237
+ # @param name [Symbol, String, #to_sym]
148
238
  # @param pattern [Proc, Method, #===]
149
239
  # @return [Proc]
150
240
  def SEND(name, pattern)
151
- raise InvalidProductError unless Eqq.valid?(pattern)
241
+ name = (
242
+ begin
243
+ name.to_sym
244
+ rescue NoMethodError
245
+ raise ArgumentError
246
+ end
247
+ )
248
+ Buildable.validate_patterns(pattern)
152
249
 
153
- ->v {
250
+ product = ->v {
154
251
  v.__send__(name, pattern)
155
252
  }
253
+
254
+ Buildable.define_inspect_on(product, name: 'SEND', arguments: [name, pattern])
255
+
256
+ product
156
257
  end
157
258
 
158
- # @return [BasicObject]
259
+ EQQ_BUILTIN_ANYTHING = ->_v { true }
260
+ define_inspect_on(EQQ_BUILTIN_ANYTHING, name: 'ANYTHING', arguments: [])
261
+
262
+ # Product returns `true`, always `true`
263
+ #
264
+ # @return [Proc]
159
265
  def ANYTHING
160
- # BasicObject.=== always passing
161
- BasicObject
266
+ EQQ_BUILTIN_ANYTHING
267
+ end
268
+
269
+ EQQ_BUILTIN_NEVER = ->_v { false }
270
+ define_inspect_on(EQQ_BUILTIN_NEVER, name: 'NEVER', arguments: [])
271
+
272
+ # Product returns `false`, always `false`
273
+ #
274
+ # @return [Proc]
275
+ def NEVER
276
+ EQQ_BUILTIN_NEVER
162
277
  end
163
278
 
164
- BOOLEAN = OR(SAME(true), SAME(false))
165
- private_constant :BOOLEAN
279
+ EQQ_BUILTIN_BOOLEAN = ->v { true.equal?(v) || false.equal?(v) }
280
+ define_inspect_on(EQQ_BUILTIN_BOOLEAN, name: 'BOOLEAN', arguments: [])
166
281
 
167
- # @return [BOOLEAN]
282
+ # Product returns `true` when matched to `true` or `false`
283
+ #
284
+ # @return [Proc]
168
285
  def BOOLEAN
169
- BOOLEAN
286
+ EQQ_BUILTIN_BOOLEAN
287
+ end
288
+
289
+ EQQ_BUILTIN_NIL = ->v { nil.equal?(v) }
290
+ define_inspect_on(EQQ_BUILTIN_NIL, name: 'NIL', arguments: [])
291
+
292
+ # Product returns `true` when matched to `nil` (Not consider `nil?`)
293
+ #
294
+ # @return [Proc]
295
+ def NIL
296
+ EQQ_BUILTIN_NIL
170
297
  end
298
+
299
+ private_constant(:EQQ_BUILTIN_ANYTHING, :EQQ_BUILTIN_NEVER, :EQQ_BUILTIN_BOOLEAN, :EQQ_BUILTIN_NIL)
171
300
  end
172
301
  end
data/lib/eqq/version.rb CHANGED
@@ -2,5 +2,6 @@
2
2
  # frozen_string_literal: true
3
3
 
4
4
  module Eqq
5
- VERSION = '0.0.2'
5
+ # This will be same as latest published gem version
6
+ VERSION = '0.0.7'
6
7
  end
data/sig/eqq.rbs CHANGED
@@ -1,3 +1,4 @@
1
+ # Pattern objects builder
1
2
  module Eqq
2
3
  interface _Patternable
3
4
  def ===: (untyped object) -> bool
@@ -7,43 +8,114 @@ module Eqq
7
8
  def to_sym: -> Symbol
8
9
  end
9
10
 
11
+ interface _Inspectable
12
+ def inspect: () -> String
13
+ end
14
+
10
15
  module Buildable
11
- # A pribate constant. Should not be used in your code.
12
- BOOLEAN: ^(untyped object) -> bool
13
-
14
- extend Buildable
15
- def OR: (_Patternable, _Patternable, *_Patternable) -> ^(untyped object) -> bool
16
- def AND: (_Patternable, _Patternable, *_Patternable) -> ^(untyped object) -> bool
17
- def NAND: (_Patternable, _Patternable, *_Patternable) -> ^(untyped object) -> bool
18
- def NOR: (_Patternable, _Patternable, *_Patternable) -> ^(untyped object) -> bool
19
- def XOR: (_Patternable, _Patternable, *_Patternable) -> ^(untyped object) -> bool
20
- def XNOR: (_Patternable, _Patternable, *_Patternable) -> ^(untyped object) -> bool
21
- def NOT: (_Patternable) -> ^(untyped object) -> bool
22
- def EQ: (untyped object) -> ^(untyped object) -> bool
23
- def SAME: (untyped object) -> ^(untyped object) -> bool
24
- def CAN: (_ToSym, *_ToSym) -> ^(untyped object) -> bool
25
- def RESCUE: (Module, _Patternable) -> ^(untyped object) -> bool
26
- def QUIET: (_Patternable, *_Patternable) -> ^(untyped object) -> bool
27
- def SEND: (Symbol | String name, _Patternable) -> ^(untyped object) -> bool
28
- def ANYTHING: () -> BasicObject
29
- def BOOLEAN: () -> ^(untyped object) -> bool
16
+ type patternable_lambda = ^(untyped object) -> bool
17
+ type product = patternable_lambda & _Inspectable
18
+
19
+ # A private constant. Should not be used in your code.
20
+ EQQ_BUILTIN_ANYTHING: product
21
+
22
+ # A private constant. Should not be used in your code.
23
+ EQQ_BUILTIN_NEVER: product
24
+
25
+ # A private constant. Should not be used in your code.
26
+ EQQ_BUILTIN_BOOLEAN: product
27
+
28
+ # A private constant. Should not be used in your code.
29
+ EQQ_BUILTIN_NIL: product
30
+
31
+ # A private API. Should not be used in your code.
32
+ def self.safe_inspect_for: (untyped object)-> String
33
+
34
+ # A private API. Should not be used in your code.
35
+ def self.define_inspect_on: (patternable_lambda product, name: String, arguments: Array[untyped])-> void
36
+
37
+ # A private API. Should not be used in your code.
38
+ def self.validate_patterns: (*untyped) -> void
39
+
40
+ # Product returns `true` when matched even one pattern
41
+ def OR: (_Patternable, _Patternable, *_Patternable) -> product
42
+
43
+ # Product returns `true` when matched all patterns
44
+ def AND: (_Patternable, _Patternable, *_Patternable) -> product
45
+
46
+ # Product is an inverted `AND`
47
+ def NAND: (_Patternable, _Patternable, *_Patternable) -> product
48
+
49
+ # Product is an inverted `OR`
50
+ def NOR: (_Patternable, _Patternable, *_Patternable) -> product
51
+
52
+ # Product returns `true` when matched one of the pattern, when matched both returns `false`
53
+ def XOR: (_Patternable, _Patternable) -> product
54
+
55
+ # Product returns `true` when not matched the pattern
56
+ def NOT: (_Patternable) -> product
57
+
58
+ # Product returns `true` when matched with `#==`
59
+ def EQ: (untyped object) -> product
60
+
61
+ # Product returns `true` when matched with `#equal?`
62
+ def SAME: (untyped object) -> product
63
+
64
+ # Product returns `true` when it has all of the methods (checked with `respond_to?`)
65
+ def CAN: (_ToSym, *_ToSym) -> product
66
+
67
+ # Product returns `true` when the pattern raises the exception
68
+ def RESCUE: (Module, _Patternable) -> product
69
+
70
+ # Product returns `true` when all patterns did not raise any exception
71
+ def QUIET: (_Patternable, *_Patternable) -> product
72
+
73
+ # Basically provided for Enumerable
74
+ def SEND: (Symbol | String name, _Patternable) -> product
75
+
76
+ # Product returns `true`, always `true`
77
+ def ANYTHING: () -> product
78
+
79
+ # Product returns `false`, always `false`
80
+ def NEVER: () -> product
81
+
82
+ # Product returns `true` when matched to `true` or `false`
83
+ def BOOLEAN: () -> product
84
+
85
+ # Product returns `true` when matched to `nil` (Not consider `nil?`)
86
+ def NIL: () -> product
30
87
  end
31
88
 
32
89
  extend Buildable
33
90
 
91
+ # Base error of this library
34
92
  class Error < StandardError
35
93
  end
36
94
 
95
+ # Raised when found some products are invalid as a pattern object
37
96
  class InvalidProductError < Error
38
97
  end
39
98
 
40
- # A pribate API. Should not be used in your code.
99
+ # A private API. Should not be used in your code.
41
100
  class DSLScope
42
101
  include Buildable
43
102
  end
44
103
 
45
104
  VERSION: String
46
105
 
106
+ # Returns `true` when given object has patternable signature
107
+ def self.pattern?: (untyped object) -> bool
108
+
109
+ # Alias of `pattern?`. But deperecated. Do not use in your code anymore.
47
110
  def self.valid?: (untyped object) -> bool
111
+
112
+ # Returns `true` when given object has correct signature as a product of builders
113
+ # Basically this is a private API. Should not be used in your code.
114
+ def self.satisfy?: (untyped object) -> bool
115
+
116
+ # In the block scope, all builder methods can be used without receiver
117
+ def self.build: { () -> _Patternable } -> _Patternable
118
+
119
+ # Alias of `build`. But deperecated. Do not use in your code anymore.
48
120
  def self.define: { () -> _Patternable } -> _Patternable
49
121
  end
metadata CHANGED
@@ -1,16 +1,23 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: eqq
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.2
4
+ version: 0.0.7
5
5
  platform: ruby
6
6
  authors:
7
7
  - Kenichi Kamiya
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2021-06-01 00:00:00.000000000 Z
11
+ date: 2021-06-06 00:00:00.000000000 Z
12
12
  dependencies: []
13
- description: " [4.2, 42, 42.0, 420].grep(Eqq.AND(Integer, 20..50)) #=> [42]\n"
13
+ description: |2
14
+ Pattern objects builder.
15
+
16
+ All products can be used as `pattern === something`.
17
+
18
+ All products can be mixed with other products as a parts.
19
+
20
+ Reuse as you wish!
14
21
  email:
15
22
  - kachick1+ruby@gmail.com
16
23
  executables: []
@@ -49,5 +56,5 @@ requirements: []
49
56
  rubygems_version: 3.2.15
50
57
  signing_key:
51
58
  specification_version: 4
52
- summary: Pattern objects builder. `eqq` means `#===`
59
+ summary: Pattern objects builder
53
60
  test_files: []