Class: ToyAdt::Matcher
- Inherits:
-
Object
- Object
- ToyAdt::Matcher
- Extended by:
- T::Sig
- Defined in:
- lib/toy_adt/matcher.rb
Constant Summary collapse
- POSITIONAL_ARGS =
Set[:req, :opt, :rest]
- KEYWORD_ARGS =
Set[:keyreq, :key, :keyrest]
- BLOCK_ARGS =
Set[:block]
Instance Method Summary collapse
- #call(input) ⇒ Object (also: #===)
- #else(&fn) ⇒ Object
-
#initialize(from:, &fn) ⇒ Matcher
constructor
A new instance of Matcher.
- #to_proc ⇒ Object
Constructor Details
#initialize(from:, &fn) ⇒ Matcher
Returns a new instance of Matcher.
14 15 16 17 18 19 20 21 22 |
# File 'lib/toy_adt/matcher.rb', line 14 def initialize(from:, &fn) @from = from @fields = from::FIELDS @sub_classes = @fields.to_h { [_1, from.const_get(_1.capitalize)] } create_branch_methods instance_eval(&fn) if block_given? end |
Instance Method Details
#call(input) ⇒ Object Also known as: ===
28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 |
# File 'lib/toy_adt/matcher.rb', line 28 def call(input) # Find the subclass the input matches to branch_name, _ = @sub_classes.find do |_, klass| matches_type?(klass, input) end # If there are none either hit the else or fail hard if branch_name.nil? return @else_fn.call(input) if @else_fn T.absurd(input) end # All values to compare against conditions values = input.deconstruct_keys(nil) # Try to find the first matching branch function via # conditions: # # value.match do |m| # m.some(value: 0..5) {} # m.some {} # m.else {} # end # # In this case a "Some" type with a value matching will hit # first. Granted less specific branches going first means # those get hit first, so not recommended. _, branch_fn = @branches.find do |branch_condition, _| name, conditions = branch_condition # First thing is the key is a tuple of subclass / branch # name, the second part is the condition if there are any. branch_name == name && conditions.all? { |k, condition| matches_type?(condition, values[k]) } end return branch_fn.call(input) if branch_fn return @else_fn.call(input) if @else_fn T.absurd(input) end |
#else(&fn) ⇒ Object
24 25 26 |
# File 'lib/toy_adt/matcher.rb', line 24 def else(&fn) @else_fn = fn end |
#to_proc ⇒ Object
73 74 75 |
# File 'lib/toy_adt/matcher.rb', line 73 def to_proc -> input { call(input) } end |