5

I'm using Lua as a data description language for my C++ app. I have a bunch of C++ classes bound to Lua using SLB 2.0. I have methods bound such as 'SetPos' or 'SetName'. I specify the position or name (for example) using a table with values keyed as 'pos' or 'name'. I want to be able to take the key, prepend 'set', and call the method, if it exists (it may not). Is that possible? If so, any suggestions?

I know I could make my bound methods lower case, but I'd rather keep them the same as the methods they're bound to (that may be my fallback though). I could try to build the method name based on my naming standards, but case insensitivity is less error prone.

I feel there should be a tricky piece of Lua that could solve this using metatables, but I haven't been able to work it out myself.

Any suggestions?

Thanks!

  • I'm not familiar with SLB. Do you have a table full of functions that are somehow bound to your C++? It's certainly possible to do what you want if you have a table full of functions, because you can define the `__index` metatable method to do a case-insensitive search of your table for a matching method and return that. That said, why do you even need this? Lua functions in general are case-sensitive, so I see no problem with leaving your functions as-is. – Lily Ballard Feb 01 '12 at 20:41
  • 2
    I would *strongly* suggest adopting, and adhering to, a policy of consistency where the names are exactly the same (+/- the `set` prefix) in both places. – Matt Fenwick Feb 01 '12 at 20:42
  • The reason I want to be a little lax with case is that if I make an error in the case, I won't know til runtime. Obviously not a show-stopper, but it would be nice. As for why I'd want to do it in the first place, the reason is I want to take a variable (name = "blah") in my lua file (e.g. in an array of definitions), and map it to a call to a method (myObj.SetName("blah")). – Graham MacDonald Feb 01 '12 at 23:38

1 Answers1

5

Case insensitivity is not really something Lua handles. All table lookups and local variable accesses are ultimately case sensitive string compares.

The best solution would be to just accept that you're dealing with a case sensitive system, just like C++, and deal with it.

However, if you really want to, you can do this. The simplest way would be to put every possible case permutation of a name in your function table. So your function table would have this:

["setname"] = theFunction,
["Setname"] = theFunction,
["sEtname"] = theFunction,
["SEtname"] = theFunction,
...

You can of course automate this with a function that takes each name in the table and replicates its data based on the case permutations.

A more involved but easier to use mechanism would be to use the __index and __newindex metamethods along with the empty table trick.

function CreateCaseInsensitiveTable()
  local metatbl = {}

  function metatbl.__index(table, key)
    if(type(key) == "string") then
      key = key:lower()
    end

    return rawget(table, key)
  end

  function metatbl.__newindex(table, key, value)
    if(type(key) == "string") then
      key = key:lower()
    end

    rawset(table, key, value)
  end

  local ret = {}
  setmetatable(ret, metatbl)
  return ret
end

Instead of creating a table with {}, you create the table with this function call. The table should otherwise function as normal (though obviously member access will be slightly slower).

Nicol Bolas
  • 449,505
  • 63
  • 781
  • 982
  • Thanks. I decided to modify SLB to create a lower-case alias for my method binding. I can then look this up using __index in my class and call it using the 'funcName(objectInstance, methodName)' form. I only want this functionality for serializing the data, so I'll avoid modifying the __index & __newindex functions for now. – Graham MacDonald Feb 01 '12 at 23:44
  • 1
    Permutation example is nice, however it should be noted that it is NOT practical at all, and no programmer on earth is endorsed to seriously implement that. If you are programming software that has to adapt to the programmer rather than being quick and efficient to the user, this is definitely the WRONG way to do it. – Gerald Apr 24 '20 at 03:25