Gmane
From: Rici Lake <lua <at> ricilake.net>
Subject: Re: The Curry Challenge
Newsgroups: gmane.comp.lang.lua.general
Date: 2007-01-11 23:25:30 GMT (1 year, 18 weeks, 13 hours and 5 minutes ago)

On 11-Jan-07, at 4:01 PM, Bret Victor wrote:

> Challenge #1:  Write "curry".  (You may assume that none of the values
> are nil, since nil and ... don't play nice together.)

OK, this one works with nil, but it definitely tests the length of ... 
and uses different code for different lengths. On the other hand, the 
different code is not explicit, and the generation is reasonably 
efficient thanks to Memoize (included below):

function Memoise(fn)
     return setmetatable({},
       {
        __index = function(t, k)
                    local val = fn(k); t[k] = val; return val
                  end,
        __call  = function(t, k)
                    return t[k]
                  end
       })
end

local concat = table.concat
Arglist = Memoise(
   function(n)
     local t = {}
     for i = 1, n do t[i] = "a"..i end
     return function(c) return concat(t, c) end
   end
)

Partial = Memoise(
   function(n) return loadstring(
       "return function(f, "..Arglist[n]", "..") return function(...) 
return f("..Arglist[n]", "..", ...) end end"
     )()
   end
)
Partial[0] = function(f) return f end

function partial(f, ...) return Partial[select("#", ...)](f, ...) end

print123 = partial(print, 1, 2, 3)
printdcba = partial(print, "d", "c", "b", "a")
print123("foo", "bar")
printdcba(1, 3)

---- Here's another application of Arglist, to produce efficient string 
catenators:

Catter = Memoise(
   function(n) return loadstring(
       "return function("..Arglist[n]", "..") return 
"..Arglist[n]"..".." end"
     )()
   end
)

c6 = Catter[6]
print(c6("a", "b", "c", "d", "e", "f"))