lua-users home
lua-l archive

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


On Thu, 27 Jun 2019 at 10:13, Dirk Laurie <dirk.laurie@gmail.com> wrote:
> Op Do. 27 Jun. 2019 om 13:08 het Dibyendu Majumdar
> <mobile@majumdar.org.uk> geskryf:
> I've been a Lua user for almost ten years, and I've succeeded in
> understanding and sometimes using every language addition in that
> time. Not so with <toclose>.
>
> My perceptions about it are:
>
> 1. It solves a problem encountered by a very small fraction of Lua users.

Have you ever a directory iterator? (e.g. for file in lfs.dir() ) If
so, you ran into this problem (maybe without realizing it).

To be quite honest, I've considered suggesting an ultra-minimalistic
approach for this whole issue: only provide to-be-closed behavior to
the `for` loop, and allow `for` to be used as a sort of `with`.

The thing about a so-called "minimalistic" langauge is that it has few
concepts, but those are often heavily overloaded.

The most obvious example is that a Lua table is an array, a hashtable,
an object etc.

Some languages have separate statements for `for` and `foreach`. Lua
overloads `for` with "numeric for" and "generic for".

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

You could read this as a "for that only runs once because it has no
iteration second argument".

Generic-for would also be extended to support __close, of course.

HOWEVER, if we were to take a page from what's now mainstream syntax
in 21st century languages like Swift and Rust, and instead of
overloading `for` we overload `if`. The above example would turn into
this instead, which is super nice:

if local fd, err = io.open("file", "r") then
   print(fd:read("*a"))
else
   print("failed!", err)
end

Since this is new syntax, one could simply establish that the __close
check runs at the end of every if-local block.

-- Hisham