module FunctionalLightService
Constants
- Option
- Result
- VERSION
Public Class Methods
guard_context(obj, args)
click to toggle source
# File lib/functional-light-service/functional/enum.rb, line 180 def self.guard_context(obj, args) if obj.is_a?(FunctionalLightService::EnumBuilder::DataType::Binary) Struct.new(*args).new(*obj.value.values) else Struct.new(*args).new(obj.value) end end
match(obj, &block)
click to toggle source
# File lib/functional-light-service/functional/enum.rb, line 139 def self.match(obj, &block) caller_ctx = block.binding.eval 'self' matcher = self::Matcher.new(obj) matcher.instance_eval(&block) variants_in_match = matcher.matches.collect do |e| e[1].name.split('::')[-1].to_sym end.uniq.sort variants_not_covered = variants - variants_in_match unless variants_not_covered.empty? raise Enum::MatchError, "Match is non-exhaustive, #{variants_not_covered} not covered" end type_matches = matcher.matches.select { |r| r[0].is_a?(r[1]) } type_matches.each do |match| obj, _type, block, args, guard = match return caller_ctx.instance_eval(&block) if args.count.zero? if args.count != obj.args.count msg = "Pattern (#{args.join(', ')}) must match (#{obj.args.join(', ')})" raise Enum::MatchError, msg end guard_ctx = guard_context(obj, args) return caller_ctx.instance_exec(* obj.wrapped_values, &block) unless guard if guard && guard_ctx.instance_exec(obj, &guard) return caller_ctx.instance_exec(* obj.wrapped_values, &block) end end raise Enum::MatchError, "No match could be made" end
new(obj)
click to toggle source
# File lib/functional-light-service/functional/enum.rb, line 194 def initialize(obj) @obj = obj @matches = [] @vars = [] end
variants()
click to toggle source
# File lib/functional-light-service/functional/enum.rb, line 176 def self.variants constants - %i[Matcher MatchError] end
Public Instance Methods
+(other)
click to toggle source
# File lib/functional-light-service/functional/option.rb, line 68 def +(other) match do None() { other } Some(where { !other.is_a?(Option) }) { |_| raise TypeError, "Other must be an #{Option}" } Some(where { other.some? }) { |s| Option::Some.new(s + other.value) } Some() { |_| self } end end
and(other)
click to toggle source
# File lib/functional-light-service/functional/result.rb, line 59 def and(other) unless other.is_a? Result msg = "Expected #{other.inspect} to be a Result" raise FunctionalLightService::Monad::NotMonadError, msg end match do Success() { |_| other } Failure() { |_| self } end end
enum(&block)
click to toggle source
rubocop:disable Metrics/AbcSize rubocop:disable Metrics/CyclomaticComplexity rubocop:disable Metrics/MethodLength rubocop:disable Metrics/PerceivedComplexity
# File lib/functional-light-service/functional/enum.rb, line 135 def enum(&block) mod = Class.new do # the enum to be built private_class_method :new def self.match(obj, &block) caller_ctx = block.binding.eval 'self' matcher = self::Matcher.new(obj) matcher.instance_eval(&block) variants_in_match = matcher.matches.collect do |e| e[1].name.split('::')[-1].to_sym end.uniq.sort variants_not_covered = variants - variants_in_match unless variants_not_covered.empty? raise Enum::MatchError, "Match is non-exhaustive, #{variants_not_covered} not covered" end type_matches = matcher.matches.select { |r| r[0].is_a?(r[1]) } type_matches.each do |match| obj, _type, block, args, guard = match return caller_ctx.instance_eval(&block) if args.count.zero? if args.count != obj.args.count msg = "Pattern (#{args.join(', ')}) must match (#{obj.args.join(', ')})" raise Enum::MatchError, msg end guard_ctx = guard_context(obj, args) return caller_ctx.instance_exec(* obj.wrapped_values, &block) unless guard if guard && guard_ctx.instance_exec(obj, &guard) return caller_ctx.instance_exec(* obj.wrapped_values, &block) end end raise Enum::MatchError, "No match could be made" end def self.variants constants - %i[Matcher MatchError] end def self.guard_context(obj, args) if obj.is_a?(FunctionalLightService::EnumBuilder::DataType::Binary) Struct.new(*args).new(*obj.value.values) else Struct.new(*args).new(obj.value) end end end enum = EnumBuilder.new(mod) enum.instance_eval(&block) type_variants = mod.constants matcher = Class.new do def initialize(obj) @obj = obj @matches = [] @vars = [] end attr_reader :matches, :vars def where(&guard) guard end type_variants.each do |m| define_method(m) do |guard = nil, &inner_block| raise ArgumentError, "No block given to `#{m}`" if inner_block.nil? params_spec = inner_block.parameters if params_spec.any? { |spec| spec.size < 2 } msg = "Unnamed param found in block parameters: #{params_spec.inspect}" raise ArgumentError, msg end if params_spec.any? { |spec| spec[0] != :req && spec[0] != :opt } msg = "Only :req & :opt params allowed; parameters=#{params_spec.inspect}" raise ArgumentError, msg end args = params_spec.map { |spec| spec[1] } type = mod.const_get(m) guard = nil if guard && !guard.is_a?(Proc) @matches << [@obj, type, inner_block, args, guard] end end end mod.const_set(:Matcher, matcher) type_variants.each do |variant| mod.singleton_class.class_exec do define_method(variant) do |*args| const_get(variant).new(*args) end end end mod end
failure?()
click to toggle source
# File lib/functional-light-service/functional/result.rb, line 43 def failure? is_a? Result::Failure end
fmap() { |s| ... }
click to toggle source
# File lib/functional-light-service/functional/option.rb, line 33 def fmap match do Some() { |s| self.class.new(yield(s)) } None() { self } end end
impl(enum_type, &block)
click to toggle source
rubocop:enable Metrics/AbcSize rubocop:enable Metrics/CyclomaticComplexity rubocop:enable Metrics/MethodLength rubocop:enable Metrics/PerceivedComplexity
# File lib/functional-light-service/functional/enum.rb, line 247 def impl(enum_type, &block) enum_type.variants.each do |v| name = "#{enum_type.name}::#{v}" type = Kernel.eval(name) type.class_eval(&block) end end
map(&fn)
click to toggle source
# File lib/functional-light-service/functional/option.rb, line 40 def map(&fn) match do Some() { |_s| bind(&fn) } None() { self } end end
map_err(proc = nil, &block)
click to toggle source
# File lib/functional-light-service/functional/result.rb, line 26 def map_err(proc = nil, &block) failure? ? bind(proc || block) : self end
Also aliased as: or_else
none?()
click to toggle source
# File lib/functional-light-service/functional/option.rb, line 51 def none? is_a? Option::None end
Also aliased as: empty?
or(other)
click to toggle source
# File lib/functional-light-service/functional/result.rb, line 47 def or(other) unless other.is_a? Result msg = "Expected #{other.inspect} to be a Result" raise FunctionalLightService::Monad::NotMonadError, msg end match do Success() { |_| self } Failure() { |_| other } end end
pipe(proc = nil, &block)
click to toggle source
# File lib/functional-light-service/functional/result.rb, line 32 def pipe(proc = nil, &block) (proc || block).call(self) self end
Also aliased as: <<
some?()
click to toggle source
# File lib/functional-light-service/functional/option.rb, line 47 def some? is_a? Option::Some end
success?()
click to toggle source
# File lib/functional-light-service/functional/result.rb, line 39 def success? is_a? Result::Success end
try(proc = nil, &block)
click to toggle source
# File lib/functional-light-service/functional/result.rb, line 85 def try(proc = nil, &block) map(proc, &block) rescue StandardError => e Result::Failure.new(e) end
Also aliased as: >=
value_or(n)
click to toggle source
# File lib/functional-light-service/functional/option.rb, line 57 def value_or(n) match do Some() { |s| s } None() { n } end end
value_to_a()
click to toggle source
# File lib/functional-light-service/functional/option.rb, line 64 def value_to_a @value end
where(&guard)
click to toggle source
# File lib/functional-light-service/functional/enum.rb, line 202 def where(&guard) guard end