lua-users home
lua-l archive

Re: What are the use cases of in-do-end?

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


GrayFace wrote:
And, again, in-end doesn't quite fit. Table passed to in-end would be set as environment for functions you declare in the classes, which isn't good I guess.
Good catch, but can be a Good Thing (tm). It lets you detect lookups of globals which aren't defined (a la "strict"). So that's why I've got:
require "strict"
in class .A do
 import(Strict)
 a = String -- an instance attribute definition
 -- we're in a proxy, so "a" is actually nil here
 assert(a == nil) -- true, but will error because strict is on
 function naughty_method()
 thwack = Number -- error decorating the class from a method
 end
 local function evil_function()
 boom = Any -- error works for upval functions too
 end
 function f()
 print(not_defined) -- error "not_defined" is nil
 end
end
Essentially the environment is just a proxy, so it's not polluted much (it has "static" and "__uptable" and that's it). The danger lies in methods trying to set globals at "run time" which the env proxy would then interpret as part of the class/module definition, which is obviously not what you'd want. Having the methods defined within inherit the environment gives you a way of implementing pragmas like "strict".
The everything-is-an-object is a good thing :)
On 27.01.2010 23:33, Richard Hundt wrote:
GrayFace wrote:
So far I've read mentions of several use cases, but I don't understand how exactly it may be useful in them. Here's what I read about: 1) Obvious usecase: something like Deplhi's 'with'. This is not the main use case Lua developers targeted, for sure. Inability to call global functions, a need for additional local variable to call methods makes this incomplete. 2) Modules. Maybe it's due to the fact that I didn't work with modules, but I don't see it useful. I don't see a reason for setting current environment like 'module' does in 5.1 or use of in-end of 5.2 due to the same reason: inability to call global functions. Generally, I'd prefer to directly write "function P.f() end" instead of "function f() end" given P is the module table.
2) Modules...
This is the one that I'm playing with atm.
Basically using environments to trap setglobal in class and module definitions to set up metatables: function definitions become virtual methods, "types" become attributes, constants become static members... etc. It's mainly sugar, but you can get really close to Ruby's class and module semantics, and still have it look nice:
in module .Acme do
 in module .Friendly do
 function greet(self, whom) -- instance method (visible on mixin)
 print(self.name.." says: Hello "..whom.."!")
 end
 function static.answer() -- static method (doesn't mixin)
 return 42
 end
 end
 answer() -- 42 (static methods visible here)
 in class .Person do
 name = String -- instance attribute (type checked)
 function __init(self, name)
 self.name = name -- TypeError if name is not a string
 end
 end
end
in class .Hacker (Acme.Person) do
 import(Acme.Friendly)
 function __init(self, name)
 super.__init(self, name) -- "super" injected into environ
 end
end
local bob = Hacker.new("Roberto")
bob:greet("World") -- "Roberto says: Hello World!"
I've got the above working (by breaking just about every rule: "module" is no longer a function, but a magic table, and all primitives have metatables, except for nil). I appreciate it's not very Lua'esque to everything-is-an-object'ify, but I think it's pretty cool that you can create new syntax like that with just the native language features.
-Rich

AltStyle によって変換されたページ (->オリジナル) /