views:

120

answers:

2

I am developing a Lua library in which I needed to uppercase the first letter of a given string. Hence I created the following function:

local capitalize = function(s)
  return string.gsub (s,
    "(%w)([%w]*)",
    function (first, rest) 
      return string.upper(first) .. rest
    end, 
    1 )
end

This initially was an "internal" function, used only on my library.

Now I've realized that my users will want to use this function in some cases.

Question 1 I am thinking about extending the string table, but I am unsure about how to proceed. Is it enough to do this, or is there a more "lua-oriented" way?

string.capitalize = function(s)
  ... etc etc (same code as above)

Question 2 I wonder if it's even a good idea to monkeypatch string. Should I provide a public "capitalize" function instead?

EDIT - In case anyone finds this in the future, a far simpler "capitalize" function is shown on the string recipes page:

str = str:gsub("^%l", string.upper)
+2  A: 

The answer to Question 1 is "yes". The answer to Question 2 is "it's a matter of taste".

lhf
+4  A: 

I frequently make extensions to builtin tables. I do this primarily when I think something really important is missing. Capitalization hasn't made my "important" list, but something called string.split has, for example.

When I do this I follow a programming convention:

require 'stringutil' -- load extra stuff into string.*
require 'osutil'     -- load extra stuff into os.*

You get the idea.

The other thing I do when I'm being careful is make sure I don't overwrite something that isn't already there, so that I'm future-proofed:

function extend(tab, field, val)
   if tab[field] == nil then
     tab[field] = val
     return val
   elseif tab[field] ~= val then
     error(string.format('Extension %s.%s failed: already occupied by %s',
                         nameof(tab), field, tostring(val)))
   else
     return val
   end
end

The nameof function is like this:

function nameof(val)
    for name, v in pairs(_G) do if v == val then return name end end
    return '?'
end

Final note: when I intend to share code with others, I tend not to modify the predefined tables. According to the Golden Rule, that namespace is shared by everybody, and if I'm going to have other people using my code, it's not fair for me just to grab whatever fields I want in the predefined string table.

Norman Ramsey
Thanks for sharing this. I'll finally follow your "final note" and not pollute string with my own functions - I think I found a better way. But your notes might come up handy in the future.
egarcia