lua-users home
lua-l archive

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


[bug: see bottom block separated by '-----']

On 30/07/2019 16.54, Soni "They/Them" L. wrote:
On 2019-07-30 11:49 a.m., nobody wrote:
On 30/07/2019 16.42, Soni "They/Them" L. wrote:
since lua doesn't have refcounting and some ppl wanna do basically io.open(file):read("*a") I wanna propose io.lines("filename", "*a")()
(or alternatively io.lines("filename", "*a", "*l")) should close the
file as if the iterator ran out.

function readfile( name )
  local <toclose> f, err = io.open( name, "r" )
  if not f then  return nil, err  end
  return f:read "*a"
end

(or something like that) should work, right?

Sometimes it actually makes sense to read '*a' and then seek back
and read(/write) again…

sometimes you don't wanna leak file descriptors which you can only
have about 1000 or so per user or something I might be off by an
order of magnitude or so but you get the idea.

Which is why you (locally) "build" the language that you need to solve
your problem…  (People usually call that "writing helper functions", but
thinking about this in terms of (efficient) communication (with both
humans and the computer) is a very useful perspective.)

Changing file:read "*a" to auto-close the file would be guaranteed to
break code.  Not all files are unchanging data, e.g. for log files it
totally makes sense to read everything and then wait for more stuff to
come in.  For stuff like "status bitmaps" it also makes sense to read
everything and then update/re-write select positions in the file (that
was opened as "r+".)  Etc.…

For io.lines, I'm not sure if that would be a problem…  but it's a `for`
iterator, which technically is a triple (next,state,position).  Relying
on the implementation detail that state/position are unused just so you
don't need to write a (very small) helper functions is not a good idea.

-----

When experimenting with this, I actually noticed a bug:

The manual says:

When the iterator function detects the end of file, it returns no
values (to finish the loop) and automatically closes the file.
but actually

for l in io.lines( "foo.txt", "*a" ) do  print( l )  end

or equivalently

f = io.open "foo.txt"
for l in f:lines( "*a" ) do  print( l )  end

will loop forever (tested in 5.3 and 5.4(git)).

(And if that's fixed so that file:lines( "*a" ) return nil at EOF, then
io.lines will also finish and close the file… so that should get Soni
the behavior that they want?)

-- nobody