#string #lua #io #luajit
Вопрос:
Как я могу добавить метод в string
таблицу и изменить себя внутри нее ?
В принципе, я пытаюсь имитировать поведение io.StringIO.read
метода в python, который считывает n
символы в строке и возвращает их, изменяя строку, «потребляя» ее.
Я попробовал это:
function string.read(str, n)
to_return = str:sub(1, n)
str = str:sub(n 1)
return to_return
end
local foo = "heyfoobarhello"
print(string.read(foo, 3))
print(foo)
Выход есть:
hey
heyfoobarhello
Я ожидал, что вторая строка будет только foobarhello
.
Как я могу этого достичь ?
Комментарии:
1. Строки в Lua неизменяемы. Вы можете обернуть строку как объект, который отслеживает, с чего начать. Или вы можете изменить API, чтобы возвращать строку и подстроку.
2. @lhf я понимаю, спасибо.
Ответ №1:
Чтобы имитировать io.StringIO
класс Python, вы должны создать объект, который хранит как базовую строку, так и текущую позицию в этой строке. Чтение из потока ввода-вывода обычно не изменяет базовые данные.
local StringIO_mt = {
read = function(self, n)
n = n or #self.buffer - self.position 1
local result = self.buffer:sub(self.position, self.position n - 1)
self.position = self.position n
return result
end,
}
StringIO_mt.__index = StringIO_mt
local function StringIO(buffer)
local o = {buffer = buffer, position = 1}
setmetatable(o, StringIO_mt)
return o
end
local foo = StringIO"heyfoobarhello"
print(foo:read(3))
print(foo:read())
Выход:
hey
foobarhello
Я не рекомендую добавлять этот класс или метод в string
библиотеку Lua, потому что объект должен быть более сложным, чем просто строка.
Комментарии:
1. Почему вы пишете код только для 5.4? У вопроса есть
LuaJIT
тег, это означает Lua 5.1.2. @EgorSkriptunoff Да, я сам это понял, я просто удалил теги
<something>
. Не беспокойтесь 😉3. @EgorSkriptunoff: Я совершенно пропустил этот тег. Исправлено.
Ответ №2:
Вы можете добавлять методы в строку типа данных независимо от таблицы строк.
Короткий пример, который показывает, что строковые методы работают даже в том случае, если таблица строк удаляется…
string=nil
return _VERSION:upper():sub(1,3)
-- Returning: LUA
Таким образом, вы можете добавить метод…
-- read.lua
local read = function(self, n1, n2)
return self:sub(n1, n2)
end
getmetatable(_VERSION).__index.read=read
return read
…для всех строк.
( Не только _ВЕРСИЯ )
И используй это…
do require('read') print(_VERSION:read(1,3):upper()) end
-- Print out: LUA