lua-users home
lua-l archive

[Date Prev][Date Next][Thread Prev][Thread Next] [Date Index] [Thread Index]


On Tue, 7 Nov 2023 at 04:56, Родион Горковенко <rodiongork@gmail.com> wrote:
> function behavior, I would like it to return "nil" sometimes (say upon
> reading number when
> no digits were provided).
>
> io.read = function(...)
>   res = {}
>   for _, typ in ipairs(table.pack(...)) do
>     val = someCodeWhichCallsPrompt()
>     if typ == '*n' then val = parseNumberWhimsically(val) end
>     table.insert(res, val)
>   end
>   return table.unpack(res)
> end
>
> The difficulty is that if "parseNumberWhimsically" may return "nil",
> it won't be inserted into the table. I don't know whether "table.pack"
> users some complicated magic for this or on contrary I'm missing
> something obvious. Thanks in advance for any hints!

You cannot trust ipairs and #table when doing this kind of stuff, with
nils in the middle. To begin with:

ipairs (t)
Returns three values (an iterator function, the table t, and 0) so
that the construction
     for i,v in ipairs(t) do body end
will iterate over the key–value pairs (1,t[1]), (2,t[2]), ..., up to
the first absent index.

So your "input" loop will stop at the first nil.

Also table.insert uses #t as offset, #t is not defined if your "array"
contains nils.

Just iterate with a simple loop:

io.read = function(...)
  local res = table.pack(...) -- this leaves length in .n
  for i in 1, res.n do
    local typ = res[i]
    local val = someCodeWhichCallsPrompt()
    if typ == '*n' then val = parseNumberWhimsically(val) end
    res[i] = val
  end
  return table.unpack(res, 1, res.n) -- use explicit size.
end

I just reused the res table for everything, but more complex thing can
be made, just put the args in an args.table, and keep a running count
of res table size with a explicit var:

io.read = function(...)
  local args = table.pack(...) -- this leaves length in .n
  local res = {}, nres=0
  for i in 1, args.n do
    local arg=args[i]
    -- Insert anything, this is just a sample.
    if i%2==0 then
      res[nres]=nil; nres=nres+1
    end
    if i%3==0 then
      res[nres]=arg; nres=nres+1
    end
    local val = someCodeWhichCallsPrompt()
    if typ == '*n' then val = parseNumberWhimsically(val) end
    res[nres] = val ; nres=nres+1
  end
  return table.unpack(res, 1, nres) -- use explicit size.
end

If I added some forgotten local to make it safer.

I have uses both flavors for doing some stuff. But this code is
untested, check it first.


Francisco Olarte.