Hi,
Let's suppose you are writing a library that produces a lot of
table-based objects with operations, and you want the control the
unnecessary production of new objects as result of manipulations. Think
a complex number or matrix library, or things like that. For example:
M = {}
M.new = function ( s )
return s or { n=0 }
end
So, you want to provide methods that either produce a new object, or
store the result in a existing one. I've seen two style of APIs, one
with separate methods:
M.add = function ( a, b )
return M.new{ n=a.n+b.n }
end
M.set_add = function ( a, b )
a.n = a.n + b.n
return a -- for concatenating calls
end
return M
--usage:
local m = require 'module'
...
a = m.add( b,c ) -- produces object
m.set_add( b, c ) -- store in place
-- with adequate metamethods
a = b:add( c ) -- produces object
b:set_add( c ) -- store in place
And another alternative, with optional out parameter:
m.add = function ( a, b, out )
if out then
out.n = a.n + b.n
return out -- for concatenating calls
else
return m.new{ n=a.n+b.n }
end
end
--usage
local m = require 'module'
...
a = m.add( b, c ) -- produces object
m.add( b, c, b ) -- store in place
-- with adequate metamethods
a = b:add( c ) -- produces object
b:add( c, b ) -- store in place
b:add( c, d ) -- store in a different existing object
The option with the separate calls seems to lead to clearer user code,
tough de API can get very long and annoying. The "out parameter" version
allows to store the result in a separate object, thus is more flexible,
while looking ugly sometimes. It also add a if-then check on every call.
Any ideas or thoughts?
Jorge