Skip to content

Instantly share code, notes, and snippets.

@lavoiesl
Created August 23, 2019 18:39
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save lavoiesl/9e1153ab1f448857df86cd5c46be085d to your computer and use it in GitHub Desktop.
Save lavoiesl/9e1153ab1f448857df86cd5c46be085d to your computer and use it in GitHub Desktop.
module KeywordCurry
def initialize
@vars = {}
end
def with_argument(name, val)
d = self.dup
d.bind_argument(name.to_sym, val)
d
end
protected
def bound_argument_sig(param)
if @vars[param[1]]
case param[0]
when :keyreq
param[0] = :key
when :key
else
raise("Unable to set value #{name} for type #{param[0]}")
end
end
case param[0]
when :key
"#{param[1]}: @vars.fetch(:#{param[1]})"
when :keyreq
"#{param[1]}:"
when :rest
"*#{param[1]}"
when :keyrest
"**#{param[1]}"
when :block
"&#{param[1]}"
else
raise("Unsupported arg type: #{param[0]}")
end
end
def bind_argument(name, val)
@vars[name] = val
public_methods(false).each do |m|
params = method(m).parameters
next unless params.any? { |p| p[1] == name }
sig = params.map(&method(:bound_argument_sig))
instance_eval(<<~RUBY)
def #{m}(#{sig.join(', ')})
super
end
RUBY
end
end
end
class Paths
include KeywordCurry
def root(root:)
root
end
def projects_root(root:)
File.join(root(root: root), 'projects')
end
def project_path(root:, project:)
File.join(projects_root(root: root), project)
end
end
paths = Paths.new
puts paths.project_path(root: '/root', project: 'myproject')
root = paths.with_argument(:root, '/root')
puts root.project_path(project: 'myproject')
project = root.with_argument(:project, 'myproject')
puts project.project_path
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment