Module: PatternMatching
- Defined in:
- lib/pattern_matching.rb,
lib/pattern_matching/methods.rb,
lib/pattern_matching/version.rb,
lib/pattern_matching/bindings.rb,
lib/pattern_matching/bindings_set.rb,
lib/pattern_matching/proc_helpers.rb,
lib/pattern_matching/configuration.rb,
lib/pattern_matching/pattern_match.rb,
lib/pattern_matching/case_equality_reversal.rb,
lib/pattern_matching/methods_with_binding_helper.rb
Overview
Allows for crude pattern-matching like behavior. Very crude. Currently just a Symbol as a status tag paired with a value. Provides capitalized methods (bad form, perhaps?) to make them stand out: ‘#Pattern`, `#Result` and `#Match`.
Example usage:
def some_computation
Result(:ok, "awesome sauce")
end
case (result = some_computation) when Match(:ok)
puts "Things went okay: #{result.value}"
when Match(:error)
puts "Something went wrong: #{result.value}"
end
# => “Things went okay: awesome sauce”
Originally named ‘Result` but that would have a conflicting meaning with the typical use of the Result Monad in most languages/environments. So while this is not true pattern matching, it might one day grow into something of the sort, and so the name fits… in a limited way.
Defined Under Namespace
Modules: Methods, MethodsWithBindingHelper, ProcHelpers Classes: Bindings, BindingsSet, CaseEqualityReversal, Configuration, PatternMatch
Constant Summary collapse
- Undefined =
Additional singleton constants and wildcards
Object.new
- Any =
Object.new
- Head =
Object.new
- Tail =
Object.new
- VERSION =
'0.1.0'
Class Method Summary collapse
-
.build_custom_binding_helper(binding_helper) ⇒ Object
The implementation of the METHODS heredoc should remain identical to the contents of the Match and Pattern methods of PatternMatching::MethodsWithBindingHelper except that here we are interpolating on our.
-
.build_custom_proc_helpers(send_helper, call_helper) ⇒ Object
Implementations internal to the blocks of the define_method calls should remain identical to the implementations in the PatternMatching::ProcHelpers module, with the only change being that the produced module has different names for the methods behind the call and send helpers.
-
.config ⇒ Object
Simple class-instance variable to hold configuration.
-
.configure(&block) ⇒ Object
Available configuration options are:.
-
.custom_proc_helpers ⇒ Object
Will only be set with a proper module if a call to ::configure results in there being proc helpers with non-default names.
-
.default_configuration! ⇒ Object
For of use in testing, because of how Ruby loading works when testing behavior that is thread-global (?) for the instance of this module.
-
.included(base) ⇒ Object
Configure behavior based on existing configuration.
-
.methods_with_custom_binding_helper ⇒ Object
Will only be set with a proper module if a call to ::configure results in a binding helper set to a name which is not the default.
Class Method Details
.build_custom_binding_helper(binding_helper) ⇒ Object
The implementation of the METHODS heredoc should remain identical to the contents of the Match and Pattern methods of PatternMatching::MethodsWithBindingHelper except that here we are interpolating on our
138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 |
# File 'lib/pattern_matching.rb', line 138 def self.build_custom_binding_helper(binding_helper) methods_with_binding = ->() { eval( <<-METHODS def Match(*pattern) result = ::PatternMatching::CaseEqualityReversal.new(*pattern) (self.class)::#{binding_helper}._clear_bindings!(caller_locations(1,1)[0].label) unless result result end def Pattern(*pattern) (self.class)::#{binding_helper}._clear_bindings!(caller_locations(1,1)[0].label) ::PatternMatching::PatternMatch.new(*pattern) end METHODS ) } @methods_with_custom_binding_helper = Module.new @methods_with_custom_binding_helper.class_exec(&methods_with_binding) end |
.build_custom_proc_helpers(send_helper, call_helper) ⇒ Object
Implementations internal to the blocks of the define_method calls should remain identical to the implementations in the PatternMatching::ProcHelpers module, with the only change being that the produced module has different names for the methods behind the call and send helpers.
119 120 121 122 123 124 125 126 127 128 129 130 131 132 |
# File 'lib/pattern_matching.rb', line 119 def self.build_custom_proc_helpers(send_helper, call_helper) proc_helpers = ->() { define_method(send_helper) do |symbol| symbol.to_proc end define_method(call_helper) do |symbol| Proc.new { |obj| self.send(symbol, obj) } end } @custom_proc_helpers = Module.new @custom_proc_helpers.class_exec(&proc_helpers) end |
.config ⇒ Object
Simple class-instance variable to hold configuration
84 85 86 |
# File 'lib/pattern_matching.rb', line 84 def self.config @config ||= ::PatternMatching::Configuration.default end |
.configure(&block) ⇒ Object
Available configuration options are:
-
use_proc_helpers: controls whether or not helpers for sending messages and calling a method in the local context are included with this module.
-
use_binding_helper: controls whether or not bindings are enabled (and thus) whether or not helpers are included.
-
send_helper: the method name used as the proc helper for “sending a message” to the object when matching.
-
call_helper: the method name used as the proc helper for “calling a method in the current context” with the object as an argument when matching.
-
binding_helper: the method name used as the binding set for each match.
69 70 71 72 73 74 75 76 77 78 79 80 |
# File 'lib/pattern_matching.rb', line 69 def self.configure(&block) block.call(config) unless config.default_proc_helpers? build_custom_proc_helpers(config.send_helper, config.call_helper) end if config.use_binding_helper && !config.default_binding_helper? build_custom_binding_helper(config.binding_helper) puts "Using a custom binding helper are we?" end end |
.custom_proc_helpers ⇒ Object
Will only be set with a proper module if a call to ::configure results in there being proc helpers with non-default names. Is not intelligently assigned, nor should it be used, when called in any manner before a call to ::configure that specifies an alternative value to config.call_helper and config.binding_helper.
101 102 103 |
# File 'lib/pattern_matching.rb', line 101 def self.custom_proc_helpers @custom_proc_helpers end |
.default_configuration! ⇒ Object
For of use in testing, because of how Ruby loading works when testing behavior that is thread-global (?) for the instance of this module.
91 92 93 |
# File 'lib/pattern_matching.rb', line 91 def self.default_configuration! @config = ::PatternMatching::Configuration.default end |
.included(base) ⇒ Object
Configure behavior based on existing configuration. This is a lot of noodley-looking nested conditional logic but that’s kind of the point with lots of boolean-based configuration of behavior!
31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 |
# File 'lib/pattern_matching.rb', line 31 def self.included(base) if PatternMatching.config.use_binding_helper base.const_set(PatternMatching.config.binding_helper, PatternMatching::BindingsSet.new) if PatternMatching.config.default_binding_helper? base.send(:include, PatternMatching::MethodsWithBindingHelper) else base.send(:include, PatternMatching.methods_with_custom_binding_helper) end else base.send(:include, PatternMatching::Methods) end if PatternMatching.config.use_proc_helpers if PatternMatching.config.default_proc_helpers? base.send(:include, PatternMatching::ProcHelpers) else base.send(:include, PatternMatching.custom_proc_helpers) end end end |
.methods_with_custom_binding_helper ⇒ Object
Will only be set with a proper module if a call to ::configure results in a binding helper set to a name which is not the default. Is not intelligently assigned, nor should it be used, when called in any manner before a call to ::configure that specifies an alternative value to config.binding_helper
110 111 112 |
# File 'lib/pattern_matching.rb', line 110 def self.methods_with_custom_binding_helper @methods_with_custom_binding_helper end |