Lua override # для строк

Я пытаюсь реализовать свой собственный метод длины для строк в Lua. Я успешно переопределил метод len() для строки, но я не знаю, как это сделать для оператора #.

orig_len = string.len
function my_len(s)
  print(s)
  return orig_len(s)
end

string.len = my_len
abc = 'abc'

Если я позвоню:

print(abc:len())

Это выводит:

abc
3

Но

print(#abc)

Выводит только "3", а это значит, что она называется функцией исходной длины вместо моей. Есть ли способ заставить # вызвать мою функцию длины?

2 ответа

Решение

Я пытаюсь реализовать свой собственный метод длины для строк в Lua.

Вы не можете сделать это от Луа.

Вам нужно изменить исходный код Lua, в частности виртуальную машину (lvm.c) и изменить обработку кода операции. OP_LEN, В Lua 5.2 вам нужно изменить luaV_objlen чтобы проверить метаметод перед получением фактической длины строки:

case LUA_TSTRING: {
  tm = luaT_gettmbyobj(L, rb, TM_LEN);        // <--- add this line
  if (!ttisnil(tm))                           // <--- add this line
      break;                                  // <--- add this line
  setnvalue(ra, cast_num(tsvalue(rb)->len));
  return;
}

Но это похоже на злоупотребление перегрузкой оператора, как перегрузка + означать разделение или что-то.

Вы не можете переопределить # оператор для строк в Lua, даже с метатаблицами: __len Метаметод не применяется к строкам.

На самом деле, в Lua нет понятия переопределения операторов. Метаметоды Lua - это запасные варианты: они используются, когда Lua не может действовать самостоятельно. Таким образом, арифметические метаметоды не применяются к числам, а метаметод длины не применяется к строкам.

Ситуация отличается для таблиц, потому что они предназначены для реализации объектов в Lua.

Другие вопросы по тегам