lua-users home
lua-l archive

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


пн, 15 июл. 2019 г. в 23:01, Hisham <h@hisham.hm>:
>
> Have you ever a directory iterator? (e.g. for file in lfs.dir() ) If
> so, you ran into this problem (maybe without realizing it).
lua 5.4 solve this using toclose and 4-th parameter for "for"
print(io.lines"readme.txt")
function: 0x23af370    nil    nil    file (0x23af130)

> So here's an idea for a third one, let's call it "resource for":
>
> stat ::=
>    ...
>    for Name ‘=’ exp ‘,’ exp [‘,’ exp] do block end |
>    for namelist in explist do block end |
>    for namelist ‘=’ exp do block end |
>    ...
>
> (as you can see, it is syntactically a mix of the other two: you can
> get multiple names on the LHS but a single expression on the RHS: if
> it uses `=` but no `,`, it's a resource-for). It works in pseudo-code
> like this:
>
> do
>    local x, y, ... = exp
>    if x == nil and y == nil then break end -- only auto-breaks if
> _all_ values are nil, so we can use libraries which use nil-err
> errors.
>    block
>    if x then
>       local xmt = getmetatable(x)
>       if xmt and xmt.__close then
>          xmt.__close(x)
>       end
>    end
> end
>
> Example usage:
>
> for fd, err = io.open("file", "r") do
>    if err then
>       print("failed!", err)
>       break
>    end
>    print(fd:read("*a"))
> end

I think solution should cover typical usage scenarios. For example
open source and destination files for processing and rise error if it
impossible. "Happy ways" is shorter and simpler to write. Also it
should be able to handle errors by user if he want it.
src=auto(io.close){ io.open(src_filename,"rb") }
dst=auto(io.close){ io.open(dst_filename,"wb") }
-- do somethig with src and dst


> You could read this as a "for that only runs once because it has no
> iteration second argument".
This could be done even now in lua 5.4

-- open.lua
function io_open(name,mode)
  local first=true
  local f,err=io.open(name,mode)
  local close=function() if f then f:close() end f=nil end
  return function()
    if first then first=false return f or false,err end
  end,nil,nil,setmetatable({},{__close=close})
end

for f,err in io_open "readme.txt" do
  if not f then warn(err) break end
  print(f:read())
end

> if local fd, err = io.open("file", "r") then
>    print(fd:read("*a"))
> else
>    print("failed!", err)
> end
This is too heavy nested in case of 2 files or if you open an array of
files you have to use recursion. So this is not like it should be.