lua-users home
lua-l archive

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


Hi, Rich, and welcome to Lua.

I thought a bit more about your example, and I think that the generalised
"for" statement suits your needs pretty well.

It certainly works for your first example, with a while statement (with
limited scope):

(*) while x := foo() do print(x) end  (to use Mark's syntax)

is simply

    for x in foo do print(x) end

(as I said yesterday). I think that covers a number of cases where you
might want to do this; others could easily be coded. For example, the
typical construction:

(*) while p := p.link do print(p.val) end

becomes

    for p in function(p) return p.link end
      do print(p.val)
    end

which is slightly less concise, but that might encourage the use of
accessor methods.


> Why my interest in this?  In part because I'm finding my code heavily
> populated with duplicated pattern matches, along the lines of:

>           if string.find(s,"<lhs><rhs>") then
>                _,_,rhs = string.find(s,"<lhs>(<rhs>)")

> which is pretty awful on several fronts, when what I need is just:

Yes, I understand that. It is rather ugly. You could use the string.gfind
library function with a break statement:

  for rhs in string.gfind(s, "<lhs>(<rhs>)") do
    -- do something with rhs
    break
  end

Of course, that doesn't give you "if then else". But there are some
interesting alternatives, with a little functional infrastructure.

For example:

  -- fn, s, v can be any triple suitable for "for in"
  function once(fn, s, v)
    return function(s, flag)
      if flag == nil return fn(s, v) or false
    end, s
  end

  -- Now we have:
  for rhs in once(string.gfind(s, "<lhs>(<rhs>)") do
    if rhs then
      print (rhs)
    else
      print "No match!"
    end
  end

  -- But it also works with pairs:
  for k in once(pairs(t)) do
    if k then
      print "t has at least one key"
    else
      print "t is empty"
    end
  end

Warning: None of this code is tested.

R.

PD:

> but the valid alternative of:

>    _,_,rhs = string.find(s,"<lhs>(<rhs>)")
>    if rhs then

> doesn't limit scope to block of use

True, but:

     do local _, _, rhs = string.find(s, "<lhs>(<rhs>)")
        if rhs then
          -- ...
        end
     end

does.