module Eco::Language
Public Class Methods
test_values_at()
click to toggle source
# File lib/eco/language/values_at.rb, line 142 def self.test_values_at h = {'pops' => 'aghr!', pops: 5, 'nops' => 'nope!'} a = Test::A.new('hello!') b = Test::B.new('bye') b.c = 'cheese' pp Handy.values_at(h, 'nops', :pops) pp Handy.values_at(a, 'rops', 'mops', rops: 'EVERY', xops: ['Dear', xop: 'SOMETHING BETTER']) pp Handy.values_at(a, 'mops', 'gops', rops: 'EVERY THING') pp Handy.values_at_dot(b, 'c', 'bofs' => ['stranberry', v2: 'combines'], 'a.rops': 'DOTTED CALL') pp "+" * 60 pp Handy.values_at_dot(b, 'c', 'bofs' => ['stranberry', v2: 'combines'], debug: true, 'a.rops': 'DOTTED CALL') pp "+" * 60 end
Public Instance Methods
curry(method)
click to toggle source
# File lib/eco/language/curry.rb, line 12 def curry(method) -> (*args, **kargs) { required = method.parameters.select { |type, _| type == :req } krequired = method.parameters.select { |type, _| type == :keyreq } all_args = (required.length <= args.length) all_keys = krequired.all? { |_, name| kargs.has_key?(name) } if all_args && all_keys final_args = (args + kargs.map {|k,v| {k => v} }) method.call(*final_args) else -> (*args_, **kargs_) { curry(method)[*args, *args_, **kargs, **kargs_] } end } end
get_accessor(object, attr, accessors: [])
click to toggle source
adapted from: stackoverflow.com/a/16908153/4352306
# File lib/eco/language/values_at.rb, line 35 def get_accessor(object, attr, accessors: []) accessors.push( ->(obj, att) { object.method(att) } ) #accessors.push( ->(obj, att) { object[att] } ) accessors.reduce(nil) { |chosen, acc| chosen ? chosen : (acc[object, attr] && acc rescue nil) || chosen } #accessors.reduce(nil) { |chosen, acc| # puts "attr: #{attr} => current: #{acc}" # chosen ? chosen : (acc[object, attr] && acc rescue nil) || chosen # puts "attr: #{attr} => after check - chosen: #{chosen}" # chosen # } end
hash_transform(hash, mode = HashTransformModifier.new)
click to toggle source
# File lib/eco/language/hash_transform.rb, line 25 def hash_transform(hash, mode = HashTransformModifier.new) hash = (mode.clone?) ? Marshal.load(Marshal.dump(hash)) : hash hash.keys.each do |key| value = (mode.keys?) ? hash.delete(key) : hash[key] value = (value.is_a?(Hash) && mode.recurse?) ? hash_transform(value, mode) : value value = sym_str_transform(value, mode) if mode.values? key = sym_str_transform(key, mode) if mode.keys? hash[key] = value end hash end
match?(value, at, mode = MatchModifier.new, depth: 0)
click to toggle source
# File lib/eco/language/match.rb, line 4 def match?(value, at, mode = MatchModifier.new, depth: 0) out_match = ->(v) { match?(v, at, mode, depth: depth + 1) } in_match = ->(a) { match?(value, a, mode, depth: depth + 1) } indent_msg = ->(m) { puts (" " * depth) + m if mode.debug? } case when mode.reverse? indent_msg.call("reverse value #{value} <--> at: #{at}") match?(at , value, mode.new.reset_reverse, depth: depth + 1) when mode.pattern? indent_msg.call("at to pattern: #{at}") at = mode.to_regex(at) match?(value, at, mode.new.reset_pattern, depth: depth + 1) when value.is_a?(Array) indent_msg.call("array #{value} value.#{mode.any?? "any?" : "all?"} match(v_item, at) at: #{at}") return value.any?(&out_match) if mode.any? value.all?(&out_match) # defaults to EVERY when at.is_a?(Array) indent_msg.call("array #{at} at.#{mode.and?? "all?" : "any?"} match(value, at_item). value: #{value}") return at.all?(&in_match) if mode.and? at.any?(&in_match) # defaullts to OR when at.is_a?(Regexp) indent_msg.call("(#{at.inspect}) at.match?(value); value: #{value}") at.match?(value) when value.is_a?(Regexp) indent_msg.call("(#{value.inspect}) value.match?(at); at: #{at}") value.match?(at) else # final compare indent_msg.call("-- final -- mode: #{mode.to_a}; value: #{value}; at: #{at}") m = (value == at) || (mode.insensitive? && at&.downcase == value&.downcase) (mode.not?) ? !m : m end end
required_parameters(method)
click to toggle source
# File lib/eco/language/curry.rb, line 4 def required_parameters(method) method.parameters.select { |type, _| type == :req || :keyreq} end
required_parameters?(method)
click to toggle source
# File lib/eco/language/curry.rb, line 8 def required_parameters?(method) required_parameters(method).length > 0 end
stringify_hash(hash, mode = HashTransformModifier.new)
click to toggle source
# File lib/eco/language/hash_transform.rb, line 62 def stringify_hash(hash, mode = HashTransformModifier.new) mode = mode.new.stringify.keys.values hash_transform(hash, mode) end
stringify_keys(hash, mode = HashTransformModifier.new)
click to toggle source
# File lib/eco/language/hash_transform.rb, line 42 def stringify_keys(hash, mode = HashTransformModifier.new) mode = mode.new.stringify.keys hash_transform(hash, mode) end
stringify_values(hash, mode = HashTransformModifier.new)
click to toggle source
# File lib/eco/language/hash_transform.rb, line 52 def stringify_values(hash, mode = HashTransformModifier.new) mode = mode.new.stringify.values hash_transform(hash, mode) end
sym_str_transform(value, mode = HashTransformModifier.new)
click to toggle source
# File lib/eco/language/hash_transform.rb, line 4 def sym_str_transform(value, mode = HashTransformModifier.new) v = value if value && (value.is_a?(Symbol) || value.is_a?(String)) if mode.symbolize? && !value.is_a?(Symbol) colon = mode.colon? && !value.include?(" ") && ( starts = value.start_with?(":") || ends = value.end_with?(":") ) if !mode.colon? || colon value = value.slice(1, value.length) if colon && starts value = value.slice(0, -1) if colon && ends v = (value.to_sym rescue value) || value end elsif !value.is_a?(String) # stringify v = (value.to_s rescue value) || value v = ":" + v if mode.colon? end end v end
symbolize_hash(hash, mode = HashTransformModifier.new)
click to toggle source
# File lib/eco/language/hash_transform.rb, line 57 def symbolize_hash(hash, mode = HashTransformModifier.new) mode = mode.new.symbolize.keys.values hash_transform(hash, mode) end
symbolize_keys(hash, mode = HashTransformModifier.new)
click to toggle source
# File lib/eco/language/hash_transform.rb, line 37 def symbolize_keys(hash, mode = HashTransformModifier.new) mode = mode.new.symbolize.keys hash_transform(hash, mode) end
symbolize_values(hash, mode = HashTransformModifier.new)
click to toggle source
# File lib/eco/language/hash_transform.rb, line 47 def symbolize_values(hash, mode = HashTransformModifier.new) mode = mode.new.symbolize.values hash_transform(hash, mode) end
to_key(pr)
click to toggle source
# File lib/eco/language/values_at.rb, line 4 def to_key(pr) pr.is_a?(Hash) ? pr.keys.first : pr end
to_value(pr)
click to toggle source
# File lib/eco/language/values_at.rb, line 8 def to_value(pr) pr.is_a?(Hash) ? pr.values.first : pr end
values_at(object, *attrs, **kattrs)
click to toggle source
# File lib/eco/language/values_at.rb, line 12 def values_at(object, *attrs, **kattrs) all_params = attrs + kattrs.map {|k,v| {k => v} } return object.values_at(*all_params) if object.is_a?(Hash) all_keys = all_params.map { |pr| to_key(pr) } arguments = all_params.each_with_index.map { |pr, i| pr.values[0] if pr.is_a?(Hash)} #puts "all_keys: #{all_keys}; arguments: #{arguments}" values = all_keys.each_with_index.map do |k, i| a = k; v = [] v = arguments[i] if all_params[i].is_a?(Hash) # with params attr_method = get_accessor(object, a)[object, a] rescue nil #puts "attr: #{a} - method: #{attr_method}" next if !attr_method args = v.is_a?(Array) ? v : [].push(v) attr_method = curry(attr_method) if required_parameters?(attr_method) # final call to the method #puts "args: #{args}" value = attr_method[*args] # rescue nil value = nil if value.is_a?(Proc) value end end
values_at_dot(object, *attrs, curry: false, debug: false, **kattrs)
click to toggle source
enables dot notation to do object nesting access
# File lib/eco/language/values_at.rb, line 49 def values_at_dot (object, *attrs, curry: false, debug: false, **kattrs) all_params = attrs + kattrs.map {|k,v| {k => v} } return object.values_at(*all_params) if object.is_a?(Hash) to_s = ->(k) { ((k.to_s rescue k) || key) } to_sym = ->(k) { ((k.to_sym rescue k) || key) } dotted = ->(k) { to_s[k].include?('.') } pdotted = ->(pr) { dotted[to_key(pr)] } haccess = ->(dp) { # prepare call k = dp k, v = [dp.keys.first, dp.values.first] if (hash = dp.is_a?(Hash)) kf, kr = [ (ss = to_s[k].split('.')).first , ss.slice(1)] nxt_cll = hash ? {kr => v} : kr {k => {'a' => kf, 'v' => nxt_cll }} } all_keys = all_params.map { |pr| to_key(pr) } hash_params = all_params.reduce({}) { |h,pr| h.merge!(pr) if pr.is_a?(Hash); h } dot_params = all_params.select { |pr| pdotted[pr] } dot_keys = dot_params.map { |dp| to_key(dp) } dot_wrappers = dot_params.reduce({}) { |h,dp| h.merge(haccess[dp]) } if debug pp "object : #{object}" pp "all_params: #{all_params}" pp "dot_keys : #{dot_keys}" end values = all_keys.map do |k| a = k; v = [] puts "key: #{k}" if debug case true when dot_keys.include?(k) # dotted (recursive) dot = dot_wrappers[k] a, v = dot.values_at('a', 'v') when hash_params.key?(k) # no dotted, with params v = hash_params[k] end attr_method = get_accessor(object, a)[object, a] rescue nil next if !attr_method args = v.is_a?(Array) ? v : [].push(v) attr_method = curry(attr_method) if required_parameters?(attr_method) if dot_keys.include?(k) # recurse (dotted) args.push({ curry: curry, debug: debug }) value = values_at(attr_method.call, *args).first else # final call to the method value = attr_method[*args] # rescue nil puts "value: #{value}" if debug end value = nil if !curry && value.is_a?(Proc) value end end