3

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
3
  • So, to clarify, what you want to do is be able to call someStringVariable:readArgs()? Commented Dec 7, 2014 at 7:46
  • Yes. Maybe call it on something like string:readArgs() and then have it return a table of arguments or something Commented Dec 7, 2014 at 15:37
  • Terminology: functions have values as paramters; not variables. The LHS of : is an expression. Commented Dec 8, 2014 at 2:34

1 Answer 1

3

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.

Sign up to request clarification or add additional context in comments.

4 Comments

What does the self parameter used here represent? The table being called? I tested the code you provided with the my syntax, and it works just fine, but I would like to be able to better understand this block of code
I've added some explanation. See if that helps.
So just to clarify, because Lua couldn't find lines["readArgs"], it looked for __index["readArgs"] inside the metatable?
Correct, if you query for a key in a table that doesn't exist, lua will consult the metatable as a fallback. If there's no metatable associated with that table then you just get nil as usual.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.