lua-users home
lua-l archive

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


On Thu, May 20, 2010 at 12:27 PM, Roberto Ierusalimschy
<roberto@inf.puc-rio.br> wrote:
> In these discussions in the list, sometimes it looks like people are
> changing environments all the time, in all sorts of code. I may be
> very wrong, but my impression is that changing the environment is
> seldom done, mainly (only?) in the setup of a module or when running
> untrusted code. I would like it to look "ugly", to be easily seen
> and found (e.g., "/_ENV"), not to look like "code as usual".

I agree but would add that there have been attempts to use
environments for hierarchical DSLs [1] embedded in Lua code.  The
problem with this application is that although it's plausible to use
environments to simplify syntax like `myname = struct "name" { int
"bar"; string "baz"; }`, where `struct` introduces an environment
local to the braces, the semantics and corner cases are jarring, so
it's more resigned to toy code.

The best we can do for embedded DSLs is probably things like `local o
= pwith(shapes)(function() return rectangle { point(0,y), point(3,4) }
end)` in 5.1 or the slightly uglier but more efficient/simpler `local
o = (function(_ENV) return rectangle { point(0,y), point(3,4) }
end)(shapes)` or `local o; do local _ENV = shapes; o = rectangle {
point(0,y), point(3,4) } end` in 5.2.0-work3.  That can work if we
avoid interfering locals and don't need to switch environments that
often.

A tangential point on DSLs: environments or not, it often feels to me
that fitting DSL's into unmodified Lua syntax in clunky.  I think it's
because that unlike XML or s-expressions, Lua has a particular
evaluation order (not pure data), can only be combined in certain ways
(e.g. expressions v.s. statements), and omits order and multiplicity
of key-value pair lists (tables), so the DSL must be fit into this
"Lua" model.  Lua punctuation rules can also add cruft to a DSL.  A
more ideal solution is some regular way for users to introduce their
own keywords in the manner of Metalua.  There are very common examples
like defining a class, for which you can either restort to Lua syntax
tricks like in Coat [2] or make things more explicit by adding real
syntax to the language:

class Point do
  has x is:rw isa:number = 0
  has y is:rw isa:number = 0
  if threedimensions then -- note: allowing this suggests statement
rather than expression context is preferred for the DSL.
    has z is:rw isa:number = 0
  end
  overload __tostring() return '(' .. self:x() .. ', ' .. self:y() .. ')' end
  method draw() return "drawing " .. self._CLASS .. tostring(self) end
end

[1] http://lua-users.org/wiki/TableScope
[2] http://lua-coat.luaforge.net/coat.html#examples