Skip to content

Instantly share code, notes, and snippets.

@mistidoi
Last active December 27, 2015 06:59
Show Gist options
  • Save mistidoi/7285732 to your computer and use it in GitHub Desktop.
Save mistidoi/7285732 to your computer and use it in GitHub Desktop.
Taking off from Jeff's curry exercise, Brandon tries to implement curry while using a Y combinator for the recursion.
# Jeff's setup:
def pc(arg, offset = 0)
file, line = caller.first.split(":")
actual_line = line.to_i - 1 + offset
code = File.read(file).split("\n")[actual_line].strip.sub("pc ", "")
result = arg.is_a?(String) ? arg : arg.inspect
puts "Line ##{actual_line}:"
puts " #{[code, result].join(" # => ")}"
puts
end
PrintsParameters = ->(a, b, c, d, e) {
[a, b, c, d, e]
}
# OG Jeff's version:
#
# Curry = ->(proc){
# inner = ->(*args) {
# if args.length == proc.parameters.length
# proc.call(*args)
# elsif args.length > proc.parameters.length
# raise ArgumentError
# else
# ->(*inner_args) {
# args += inner_args
# inner.(*args)
# }
# end
# }
# }
# This one implements recursion by assigning the inner proc to a variable and calling that proc on line 29.
# Can we implement the recursion with a Y combinator?
# Homemade Y combinator (with splat support):
y_combinator = ->(p) {
->(func) {
func.(func)
}.(->(func2) {
p.(->(*x) { func2.(func2).(*x) })
})
}
# The fun to be had:
CurryPartial = ->(curry_partial) {
->(proc){
->(*args) {
if args.length == proc.parameters.length
proc.(*args)
elsif args.length > proc.parameters.length
raise ArgumentError
else
->(*inner_args) {
args += inner_args
curry_partial.(proc).(*args)
}
end
}
}
}
curry_y_combined = y_combinator.(CurryPartial)
# Jeff's tests:
CurriedPrintsParameters = curry_y_combined.(PrintsParameters)
pc CurriedPrintsParameters.(1)
pc CurriedPrintsParameters.(1).(2)
pc CurriedPrintsParameters.(1).(2).(3)
pc CurriedPrintsParameters.(1).(2).(3).(4)
pc CurriedPrintsParameters.(1).(2).(3).(4).(5)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment