qo 0.5.0 → 0.99.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,126 +0,0 @@
1
- require 'qo/exceptions'
2
-
3
- module Qo
4
- module Matchers
5
- # Creates a PatternMatch in a succinct block format:
6
- #
7
- # ```ruby
8
- # Qo.match(target) { |m|
9
- # m.when(/^F/, 42) { |(name, age)| "#{name} is #{age}" }
10
- # m.else { "We need a default, right?" }
11
- # }
12
- # ```
13
- #
14
- # The Public API obscures the fact that the matcher is only called when it
15
- # is explicitly given an argument to match against. If it is not, it will
16
- # just return a class waiting for a target, as such:
17
- #
18
- # ```ruby
19
- # def get_url(url)
20
- # Net::HTTP.get_response(URI(url)).yield_self(&Qo.match { |m|
21
- # m.when(Net::HTTPSuccess) { |response| response.body.size }
22
- # m.else { |response| raise response.message }
23
- # })
24
- # end
25
- #
26
- # get_url('https://github.com/baweaver/qo')
27
- # # => 142387
28
- # get_url('https://github.com/baweaver/qo/does_not_exist')
29
- # # => RuntimeError: Not Found
30
- # ```
31
- #
32
- # This is intended for flexibility between singular calls and calls as a
33
- # paramater to higher order functions like `map` and `yield_self`.
34
- #
35
- # This variant was inspired by ideas from Scala, Haskell, and various Ruby
36
- # libraries dealing with Async and self-yielding blocks. Especially notable
37
- # were websocket handlers and dry-ruby implementations.
38
- #
39
- # @author baweaver
40
- # @since 0.3.0
41
- #
42
- class PatternMatch
43
- def initialize
44
- @matchers = []
45
-
46
- yield(self)
47
- end
48
-
49
- # Creates a match case. This is the exact same as any other `and` style
50
- # match reflected in the public API, except that it's a Guard Block
51
- # match being performed. That means if the left side matches, the right
52
- # side function is invoked and that value is returned.
53
- #
54
- # @param *array_matchers [Array[Any]]
55
- # Array style matchers
56
- #
57
- # @param **keyword_matchers [Hash[Any, Any]]
58
- # Hash style matchers
59
- #
60
- # @param &fn [Proc]
61
- # If matched, this function will be called. If no function is provided
62
- # Qo will default to identity
63
- #
64
- # @return [Array[GuardBlockMatcher]]
65
- # The return of this method should not be directly depended on, but will
66
- # provide all matchers currently present. This will likely be left for
67
- # ease of debugging later.
68
- def when(*array_matchers, **keyword_matchers, &fn)
69
- @matchers << Qo::Matchers::GuardBlockMatcher.new(
70
- array_matchers,
71
- keyword_matchers,
72
- &(fn || Qo::IDENTITY)
73
- )
74
- end
75
-
76
- # Else is the last statement that will be evaluated if all other parts
77
- # fail. It should be noted that it won't magically appear, you have to
78
- # explicitly put an `else` case in for it to catch on no match unless
79
- # you want a `nil` return
80
- #
81
- # @param &fn [Proc]
82
- # Function to call when all other matches have failed. If no value is
83
- # provided, it assumes `Qo::IDENTITY` which will return the value given.
84
- #
85
- # @return [Proc]
86
- def else(&fn)
87
- raise Qo::Exceptions::MultipleElseClauses if @else
88
-
89
- @else = fn || Qo::IDENTITY
90
- end
91
-
92
- # Proc version of a PatternMatch
93
- #
94
- # @return [Proc]
95
- # Any -> Any | nil
96
- def to_proc
97
- Proc.new { |target| self.call(target) }
98
- end
99
-
100
- # Immediately invokes a PatternMatch
101
- #
102
- # @param target [Any]
103
- # Target to run against and pipe to the associated block if it
104
- # "matches" any of the GuardBlocks
105
- #
106
- # @return [Any]
107
- # Result of the piped block
108
- #
109
- # @return [nil]
110
- # No matches were found, so nothing is returned
111
- def call(target)
112
- @matchers.each { |guard_block_matcher|
113
- next unless guard_block_matcher.match?(target)
114
- return guard_block_matcher.match(target)
115
- }
116
-
117
- return @else.call(target) if @else
118
-
119
- nil
120
- end
121
-
122
- alias_method :===, :call
123
- alias_method :[], :call
124
- end
125
- end
126
- end