Module: Qo::PublicApi

Includes:
Exceptions
Included in:
Qo
Defined in:
lib/qo/public_api.rb

Overview

The Public API consists of methods that should be openly accessible to the top level Qo namespace, and should not change. It should be used as the subject of Acceptance level tests for the library and should not have its externally facing methods renamed or moved under pain of a look of profound disappointment from the creator.

Author:

  • baweaver

Since:

  • 0.2.0

Instance Method Summary collapse

Instance Method Details

#and(*array_matchers, **keyword_matchers) ⇒ Proc[Any] Also known as: []

Creates an and type query matcher. All conditions in this type of matcher must pass to be considered a "match". It will short-circuit in the case of a false match.

Parameters:

  • *array_matchers (Array)

    Array-like conditionals

  • **keyword_matchers (Hash)

    Keyword style conditionals

Returns:

  • (Proc[Any])

    Any -> Bool # Given a target, will return if it "matches"

Since:

  • 0.2.0



26
27
28
# File 'lib/qo/public_api.rb', line 26

def and(*array_matchers, **keyword_matchers)
  create_matcher('and', array_matchers, keyword_matchers)
end

#case(value, destructure: false, &fn) ⇒ Any

Note:

I refer to the potential 2.6+ features currently being discussed here:

Similar to the common case statement of Ruby, except in that it behaves as if Array#=== and Hash#=== exist in the form of Qo matchers.

Examples:

Qo.case([1, 1]) { |m|
  m.when(Any, Any) { |a, b| a + b }
  m.else { |v| v }
}
=> 2

Parameters:

  • value (Any)

    Value to match against

  • destructure: (Boolean) (defaults to: false)

    Whether or not to destructure an object before yielding it to the given function.

  • &fn (Proc)

    Body of the matcher, as shown above

Returns:

  • (Any)

    The result of calling a pattern match with a provided value

See Also:

  • Qo#match

Since:

  • 0.2.0



121
122
123
# File 'lib/qo/public_api.rb', line 121

def case(value, destructure: false, &fn)
  Qo::PatternMatchers::PatternMatch.new(destructure: destructure, &fn).call(value)
end

#create_branch(name:, precondition: Any, extractor: IDENTITY, destructure: false, default: false) ⇒ Class

Dynamically creates a new branch to be used with custom pattern matchers.

Parameters:

  • name: (String)

    Name of the branch. This is what binds to the pattern match as a method, meaning a name of where will result in calling it as m.where.

  • precondition: (defaults to: Any)

    Any [Symbol, #===] A precondition to the branch being considered true. This is done for static conditions like a certain type or perhaps checking a tuple type like [:ok, value].

    If a Symbol is given, Qo will coerce it into a proc. This is done to make a nicer shorthand for creating a branch.

  • extractor: (defaults to: IDENTITY)

    IDENTITY [Proc, Symbol] How to pull the value out of a target object when a branch matches before calling the associated function. For a monadic type this might be something like extracting the value before yielding to the given block.

    If a Symbol is given, Qo will coerce it into a proc. This is done to make a nicer shorthand for creating a branch.

  • destructure: (defaults to: false)

    false Whether or not to destructure the given object before yielding to the associated block. This means that the given block now places great importance on the argument names, as they'll be used to extract values from the associated object by that same method name, or key name in the case of hashes.

  • default: (defaults to: false)

    false [Boolean] Whether this branch is considered to be a default condition. This is done to ensure that a branch runs last after all other conditions have failed. An example of this would be an else branch.

Returns:

  • (Class)

    Anonymous branch class to be bound to a constant or used directly

Since:

  • 0.2.0



220
221
222
223
224
225
226
227
228
# File 'lib/qo/public_api.rb', line 220

def create_branch(name:, precondition: Any, extractor: IDENTITY, destructure: false, default: false)
  Qo::Branches::Branch.create(
    name:         name,
    precondition: precondition,
    extractor:    extractor,
    destructure:  destructure,
    default:      default
  )
end

#create_pattern_match(branches:) ⇒ Class

Creates a new type of pattern matcher from a set of branches

Parameters:

  • branches: (Array[Branch])

    An array of branches that this pattern matcher will respond to

Returns:

  • (Class)

    Anonymous pattern matcher to be bound to a constant or used directly

Since:

  • 0.2.0



237
238
239
# File 'lib/qo/public_api.rb', line 237

def create_pattern_match(branches:)
  Qo::PatternMatchers::PatternMatch.create(branches: branches)
end

#match(destructure: false, &fn) ⇒ Qo::PatternMatch

A pattern match will try and run all guard block style matchers in sequence until it finds one that "matches". Once found, it will pass the target into the associated matcher's block function.

Examples:

[1,2,3].map(&Qo.match { |m|
  m.when(:even?) { |v| v * 3 }
  m.else         { |v| v - 1 }
})
=> [0, 6, 2]

Parameters:

  • destructure: (Boolean) (defaults to: false)

    Whether or not to destructure an object before yielding it to the given function.

  • fn (Proc)

    Body of the matcher, as shown in examples

Returns:

  • (Qo::PatternMatch)

    A function awaiting a value to match against

Since:

  • 0.2.0



85
86
87
88
89
# File 'lib/qo/public_api.rb', line 85

def match(destructure: false, &fn)
  return proc { false } unless block_given?

  Qo::PatternMatchers::PatternMatch.new(destructure: destructure, &fn)
end

#not(*array_matchers, **keyword_matchers) ⇒ Proc[Any]

Creates a not type query matcher. No conditions in this type of matcher should pass to be considered a "match". It will short-circuit in the case of a true match.

Parameters:

  • *array_matchers (Array)

    Array-like conditionals

  • **keyword_matchers (Hash)

    Keyword style conditionals

Returns:

  • (Proc[Any])

    Any -> Bool # Given a target, will return if it "matches"

Since:

  • 0.2.0



61
62
63
# File 'lib/qo/public_api.rb', line 61

def not(*array_matchers, **keyword_matchers)
  create_matcher('not', array_matchers, keyword_matchers)
end

#or(*array_matchers, **keyword_matchers) ⇒ Proc[Any]

Creates an or type query matcher. Any conditions in this type of matcher must pass to be considered a "match". It will short-circuit in the case of a true match.

Parameters:

  • *array_matchers (Array)

    Array-like conditionals

  • **keyword_matchers (Hash)

    Keyword style conditionals

Returns:

  • (Proc[Any])

    Any -> Bool # Given a target, will return if it "matches"

Since:

  • 0.2.0



45
46
47
# File 'lib/qo/public_api.rb', line 45

def or(*array_matchers, **keyword_matchers)
  create_matcher('or', array_matchers, keyword_matchers)
end

#result_case(target, destructure: false, &fn) ⇒ Any

Similar to case, except it uses a ResultPatternMatch instead.

Parameters:

  • target (Any)

    Target to match against

  • destructure: (Boolean) (defaults to: false)

    Whether or not to destructure an object before yielding it to the given function.

  • &fn (Proc)

    Body of the matcher, as shown above

Returns:

  • (Any)

    Result of the match

See Also:

Since:

  • 0.2.0



178
179
180
181
182
# File 'lib/qo/public_api.rb', line 178

def result_case(target, destructure: false, &fn)
  Qo::PatternMatchers::ResultPatternMatch
    .new(destructure: destructure, &fn)
    .call(target)
end

#result_match(destructure: false, &fn) ⇒ Proc[Any] => Any

Similar to match, except it uses a ResultPatternMatch which instead responds to tuple types:

Examples:


```ruby
pm = Qo.result_match { |m|
  m.success { |v| v + 10 }
  m.failure { |v| "Error: #{v}" }
}

pm.call([:ok, 3])
# => 13

pm.call([:err, "No Good"])
# => "Error: No Good"
```

Parameters:

  • destructure: (Boolean) (defaults to: false)

    Whether or not to destructure an object before yielding it to the given function.

  • &fn (Proc)

    Body of the matcher, as shown above

Returns:

  • (Proc[Any] => Any)

    Proc awaiting a value to match against.

See Also:

Since:

  • 0.2.0



154
155
156
157
158
# File 'lib/qo/public_api.rb', line 154

def result_match(destructure: false, &fn)
  return proc { false } unless block_given?

  Qo::PatternMatchers::ResultPatternMatch.new(destructure: destructure, &fn)
end