Skip to content

Instantly share code, notes, and snippets.

@gilbert
Last active August 29, 2015 14:05
Show Gist options
  • Save gilbert/b131bcd0f72f87110582 to your computer and use it in GitHub Desktop.
Save gilbert/b131bcd0f72f87110582 to your computer and use it in GitHub Desktop.
[Practical] Partial Application in Ruby
require 'deterministic'
class X
include Deterministic
def go
# The `>>` is from Deterministic. It feeds the result
# of the left side into the right side.
# get_num >> mcurry(:add, 1) >> mcurry(:double)
get_num >> _add(1) >> _double
end
def get_num
Success(11)
end
def add(x,y)
Success(x + y)
end
def double(x)
Success(x * 2)
end
# A helper to curry an existing instance method
def mcurry(method_name, *args)
m = method(method_name).to_proc
if args.length - m.arity > 1
raise ArgumentError.new("too many curried arguments for #{method_name} (#{args.length} for #{m.arity}; you need to leave exactly one open)")
elsif args.length - m.arity == 0
lambda { m[*args] }
else
m.curry[*args]
end
end
# By prepending a method call with _, we can automatically generate
# a curried lamda version of that intsance method!
def method_missing(meth, *args, &block)
name = meth.to_s
real_method = name[1..-1]
if name[0] == '_' && self.respond_to?(real_method)
mcurry(real_method, *args, &block)
else
super
end
end
end
x = X.new
puts "RESULT: #{x.go.inspect}"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment