lua-users home
lua-l archive

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


2009/8/16 François Perrad <francois.perrad@gadz.org>:
> 2009/8/15 David Manura <dm.lua@math2.org>:
>> On Fri, Aug 14, 2009 at 11:02 AM, François Perrad wrote:
>>> lua-Coat is a Lua 5.1 port of Coat (http://www.sukria.net/perl/coat/),
>>> a Perl module which mimics Moose (http://www.iinteractive.com/moose/),
>>> an object system for Perl5 which borrows features from Perl6,
>>> CLOS (LISP), Smalltalk and many other languages.
>>> ...The homepage is at http://lua-coat.luaforge.net/,
>>
>>
>> That seems to have some traction [3-4].
>>
>
> Yes, it's a port.
>
>> In this syntax:
>>
>>  require 'Coat'
>>  class 'Point'
>>  has( 'x', { is = 'rw', isa = 'number', default = 0 } )
>>  has( 'y', { is = 'rw', isa = 'number', default = 0 } )
>>  overload( '__tostring', function (self)
>>    return '(' .. self:x() .. ', ' .. self:y() .. ')'
>>  end )
>>  method( 'draw', function (self)
>>    return "drawing " .. self._CLASS .. tostring(self)
>>  end )
>>
>> the "end )" feels a bit awkward to write for every method in a
>> program: it's a statement-level keyword (end) contained inside an
>> expression-level ")", which tend not to mix in Lua.  The "end" and ")"
>> don't align to their matching start tokens, and the function block has
>> less indentation than the "function" keyword.  The original also
>> involves quoting identifiers ('draw').
>>
>
> I agree. The syntax needs improvement.
> I wrote small patches (see patch/) which allows a more perlish syntax.
> I will send a specific message about them.
>
>> It could be written in a more luaesque way a follows:
>>
>>  require 'Coat'
>>  class 'Point'
>>  has.x = { is = 'rw', isa = 'number', default = 0 }
>>  has.y = { is = 'rw', isa = 'number', default = 0 }
>>  overload.__tostring = function (self)
>>    return '(' .. self.x .. ', ' .. self.y .. ')'
>>  end
>>  method.draw = function (self)
>>    return "drawing " .. self._CLASS .. tostring(self)
>>  end
>>  -- The above can also be written as such:
>>  -- function method.draw(self)
>>  --   return "drawing " .. self._CLASS .. tostring(self)
>>  -- end
>>
>> where "has", "overload", and "method" are tables, possibly with
>> __newindex metamethods.
>>

Now, lua-Coat is fully refactored with this syntax.
But not yet released, see HEAD on http://github.com/fperrad/lua-Coat/

New comment wellcomed

>> I think self.x rather than self:x() tends to be the preferred syntax
>> for object properties in Lua.  This requires a proxy table though.
>>

the attribute setter is : self:x(val)
so the attribute getter must be : val = self:x()
In fact, self.x is the getter/setter function.

François.

>> Here's a few initial comments on the source:
>>
>>
>>> module(..., package.seeall)
>>
>>
>> I recommend avoiding package.seeall since it pollutes your external interface:
>>
>>  require "Coat"
>>  print(Coat.math) --> table: 0x100549c8
>>
>
> Fixed in release 0.2.1
>
>>
>>> basic_type = type
>>> local basic_type = basic_type
>>> local function object_type (obj)
>>>     local t = basic_type(obj)
>>>     if t == 'table' and obj._CLASS then
>>>         return obj._CLASS
>>>     else
>>>         return t
>>>     end
>>> end
>>> _G.type = object_type
>>
>>
>> This breaks type().  Consider:
>>
>
> Fixed in release 0.2.1
>
>>  require "Coat"
>>  require "someothermodule"
>>
>> where someothermodule internally applies type to a read-only table:
>>
>>  local t = setmetatable({x=1}, {__index=function() error'read only' end})
>>  assert(type(t) == 'table')
>>
>> and now fails.
>>
>>
>>> function _G.class (modname)
>>
>>
>> This can then imply that other modules in your program cannot
>> internally use Steve's class.lua module [1].  Consider this:
>>
>
> Yes, there is a conflict between them.
>
>>  -- b.lua
>>  require "class"   -- internally uses class.lua
>>  .....
>>
>> which in turn is used by this:
>>
>>  -- a.lua
>>  require "Coat"
>>  require "b"
>>  class "a" -- opps, invokes class.lua not Coat.lua
>>
>> I've had complaints about the Lua module system in the past [2].
>>
>>
>>> function _G.class (modname)
>>>     checktype('class', 1, modname, 'string')
>>>     if _G[modname] then
>>>         error("name conflict for module '" .. modname .. "'")
>>>     end
>>
>>
>> Is there a way to create anonymous classes? or lexically scoped
>> classes?  For example,
>>
>
> No. In fact, class 'Foo' acts like module 'Foo' (with some OO magic).
>
> My current plan for release 0.3.0 is a support of submodule,
> like class 'MyApp.Foo.Bar'.
>
> Thanks for this great feedback.
>
> François Perrad
>
>>  local class = require "Coat" . class
>>  local T =
>>    class(function()
>>      function method.test() print 'test' end
>>    end)
>>  T():test() --> test
>>
>>
>> [1] http://lua-users.org/wiki/SimpleLuaClasses
>> [2] http://lua-users.org/lists/lua-l/2009-08/msg00297.html
>> [3] http://www.iinteractive.com/moose/
>> [4] http://search.cpan.org/~drolsky/Moose/lib/Moose/Manual/Unsweetened.pod
>>
>>
>