lua-users home
lua-l archive

[Date Prev][Date Next][Thread Prev][Thread Next] [Date Index] [Thread Index]


> Ahhhh... I see what you're doing now. Good idea. It allows the
> closure to receive additional arguments when it's called.

That's what currying is.

> However, it won't work as written because in the expression:
>
> f(unpack(fix), unpack(arg))
>
> f will only receive the first value returned by 'unpack(fix)' and
> all the values returned by 'unpack(arg)' For instance, this code:

Thanks for pointing this out (and to Philipp). My mistake owing to a
mis-translation from Lua 4. Since I've not tried to curry on more than one
argument since then, I'd not noticed the problem.

For anyone who's interested, a working version that is a bit more
decomposed than Philipp's (and exposes two other useful functions in the
process) is:

-- @func table.clone: Make a shallow copy of a table, including any
-- metatable
--   @param t: table
-- returns
--   @param u: copy of table
function table.clone (t)
  local u = setmetatable ({}, getmetatable (t))
  for i, v in pairs (t) do
    u[i] = v
  end
  return u
end

-- @func table.merge: Merge two tables
-- If there are duplicate fields, u's will be used. The metatable of
-- the returned table is that of t
--   @param t, u: tables
-- returns
--   @param r: the merged table
function table.merge (t, u)
  local r = table.clone (t)
  for i, v in pairs (u) do
    r[i] = v
  end
  return r
end

-- curry: Partially apply a function
--   f: function to apply partially
--   a1 ... an: arguments to fix
-- returns
--   g: function with ai fixed
function curry (f, ...)
  local fix = arg
  return function (...)
           return f (table.merge (unpack (fix), unpack (arg)))
         end
end

Another useful functional is

-- compose: Compose some functions
--   f1 ... fn: functions to compose
-- returns
--   g: composition of f1 ... fn
--     args: arguments
--   returns
--     f1 (...fn (args)...)
function compose (...)
  local fns, n = arg, table.getn (arg)
    return function (...)
             for i = n, 1, -1 do
               arg = pack (fns[i](unpack (arg)))
             end
             return unpack (arg)
           end
  end
end

which is like currying, but one level up: it wraps up function
application rather than argument application. In lazy languages you don't
need compose.

ADVERT: All the code above is from my stdlib project, in CVS on
lua-users.org. I'm currently making over the code for Lua 5 (it's all
working in Lua 5, and I'm now "restyling" it a bit, mostly renaming the
functions into tables, but also more subtle Lua 5-ification). Unlike the
Wiki, CVS is still working fine for reading *and* writing. See
http://cvs.sourceforge.net/viewcvs.py/lua-users/stdlib/modules/

-- 
http://www.mupsych.org/~rrt/ | taciturn, n.  a silent pot