Skip to content

Instantly share code, notes, and snippets.

@Peeja
Created February 20, 2010 05:58
Show Gist options
  • Save Peeja/309535 to your computer and use it in GitHub Desktop.
Save Peeja/309535 to your computer and use it in GitHub Desktop.
module Curryable
# Quirk: #curry on a nullary function calls the function.
def curry(args = [])
if self.arity == args.length
self[*args]
else
lambda do |next_arg|
self.curry(args + [next_arg])
end
end
end
def uncurry
lambda { |*args| args.inject(self) { |f, arg| f[arg] } }
end
end
Proc.send(:include, Curryable)
Method.send(:include, Curryable)
class Class
def curry(method_name)
original_method = instance_method(method_name)
define_method(method_name) do
original_method.bind(self).curry
end
end
end
require 'rubygems'
require 'spec'
require 'spec/autorun'
describe "#uncurry" do
context "given a curried function of two parameters" do
it "uncurries it" do
curried_function = lambda { |a| lambda { |b| [a, b] } }
curried_function[1][2].should == [1, 2]
curried_function.uncurry[1, 2].should == [1, 2]
end
end
context "given a curried function of three parameters" do
it "uncurries it" do
curried_function = lambda { |a| lambda { |b| lambda { |c| [a, b, c] } } }
curried_function[1][2][3].should == [1, 2, 3]
curried_function.uncurry[1, 2, 3].should == [1, 2, 3]
end
end
end
describe "Proc#curry" do
context "on a unary function" do
it "curries it (trivially)" do
function = lambda { |a| a }
function.curry[1].should == 1
end
end
context "on a binary function" do
it "curries it" do
function = lambda { |a, b| [a, b] }
function.curry[1][2].should == [1, 2]
end
end
context "on a trinary function" do
it "curries it" do
function = lambda { |a, b, c| [a, b, c] }
function.curry[1][2][3].should == [1, 2, 3]
end
end
end
describe "Class.curry" do
context "on a unary method" do
it "curries it (trivially)" do
class UnaryCurried
def identity(a)
a
end
curry :identity
end
UnaryCurried.new.identity[1].should == 1
end
end
context "on a binary method" do
it "curries it" do
class BinaryCurried
def identity(a, b)
[a, b]
end
curry :identity
end
BinaryCurried.new.identity[1][2].should == [1, 2]
end
end
context "on a trinary method" do
it "curries it" do
class TrinaryCurried
def identity(a, b, c)
[a, b, c]
end
curry :identity
end
TrinaryCurried.new.identity[1][2][3].should == [1, 2, 3]
end
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment