Lee Yi
Lee Yi

Reputation: 527

Lua How to create custom function that can be used on variables?

With methods like io.close(), you can use it like this:

file:close()

Is there a way to create a custom function that works like that, where you can call it on a variable?

For me I am trying to use it to separate arguments from a text file by using string.find to find spaces

So in the text file it looks like

this is some input

And the readArgs() function should return the entire line in a table with args[1] = "So", args[2] = "in", args[3] = "the" etc. after being called on the line

function readFile(file)
    local lines = {}
    assert(io.open(file), "Invalid or missing file")
    local f = io.open(file)
    for line in f:lines() do
        lines[#lines+1] = line
    end
    return lines
end

function readArgs(line) -- This is the function. Preferably call it on the string line
    --Some code here
end

Upvotes: 3

Views: 724

Answers (1)

greatwolf
greatwolf

Reputation: 20838

Based on your description it sounds like you're after something similar to this syntax:

local lines = readFile(file)
lines:readArgs(1) -- parse first line {"this", "is", "some", "input"}

Metatables can help with this:

local mt = { __index = {} }
function mt.__index.readArgs(self, linenum)
  if not self[linenum] then return nil end

  local args = {}
  for each in self[linenum]:gmatch "[^ ]+" do
    table.insert(args, each)
  end
  return args
end

You'll have to do a slight change in your readFile and attach that metatable to the lines you're returning:

function readFile(file)
  -- ...
  return setmetatable(lines, mt)
end

Edit: To answer the OP's comment, a call like this:

lines:readArgs(1)

is just syntactic sugar for:

lines.readArgs(lines, 1)

When the lua VM executes the above line the following happens:

  • Does the table lines have a readArgs key?
  • If yes then use its corresponding value as usual for the remaining part of the statement.
  • If no, does lines have a metatable.__index? In this case it does, so the function assigned to __index.readArgs is used.
  • readArgs is now called with the parameters above: self = lines, linenum = 1

There is nothing special about self here, it's just a regular parameter; you can name it anything you want really.

Upvotes: 3

Related Questions