lua-users home
lua-l archive

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


On Wed, Feb 22, 2017 at 1:36 AM, p. shkadzko <p.shkadzko@gmail.com> wrote:
> Here is a function that finds all files in nested dirs and returns a table
> of file paths. I can't figure out how to keep the table variable inside the
> function. For example.

A lot of code has already been proposed for this. I'd like to point
the standard way to do this kind of functions ( a recursive functions
which needs co accumulate things ) is to use a helper.

local function _accum(whatever, state)
  .... something recursive using state
end

local function accum(whatever)
   local state = {}
   _accum(whatever, state)
   return state
end

You can vary from that a lot, specially in lua. You can defing _accum
inside accum, and, in this case, use state via local capture ( which
is easier specially if there are many recursive call points, it saves
typing and stack ( not too sure about the last one in lua ). You can
return state from _accum so accum just reduces to "return
_accum(whatever,{})" which is zapped as a tail call. If you are very
sure about the callers you can directly use _accum but do state=state
or {} and return it. It mainly depends on the exact use case. For a
directory walker I would personally opt for _accum inside accum,
return state, pass {} to init:

function dir_walk(dir)
   local function dw(dir, fpaths)
      .....
      return fpaths
   end
   return dw(dir, {})
end

Regarding the closures, you can do:

function dir_walk(dir)
   local fpaths = {}
   local function dw(dir) -- this is a closure, it captures the outer fpath
      .....
      return
   end
   dw(dir) - No need to pass fpath, captured by the closure.
   return fpaths
end




And, in some cases, I've resorted to passing the size of the table in
C, and it may be useful in lua to avoid repeating the #fpaths in
table.insert, but this needs some more code.

function dir_walk(dir)
   local function dw(dir, fpaths, n)
      -- Change table.insert(fpaths,files[i]) to
      n = n+1; fpaths[n]=files[i]
      -- When recursing do
      n = dw(files[i], fpatchs, n)
      .....
      return n -- not fpaths, to account for inserted data
   end
   local fpaths = {}
   dw(dir, t, 0)
   return fpaths
end

But I would not use it for listing dirs normally ( syscalls time
dwarfs everything else ).

Francisco Olarte.