[Date Prev][Date Next][Thread Prev][Thread Next]
- Subject: Re: [ANN] Microlight (was Re: paving cowpaths with libraries)
- From: steve donovan <steve.j.donovan@...>
- Date: Thu, 16 Feb 2012 10:34:18 +0200
On Wed, Feb 15, 2012 at 10:14 PM, Renato Maia <email@example.com> wrote:
> Here goes a view of such functions from a very *personal* perspective:
In Lua, all perspectives are personal ;)
> split -> I rather use 'string.gmatch'.
That's often enough, but you have to think carefully about the pattern
in general. I can't claim this one is battle-tested, but it matches
the reference implementation, which is Python's split.
> expand -> I've only needed such thing in stand-alone applications, mainly to support internationalization of user messages.
This function is a simple answer to the question: "can I do string
interpolation in Lua?". The operative word is 'simple'; saves having
to type some line noise for the captures, otherwise all the power of
gsub is available.
> readfile -> I rather use 'io.open'/'file:read("*a")' and get proper error messages from the 'io' library.
Oh, readfile will give you all the error messages. It's just often
easier to pull not-so-big files directly into a string and process
> exists -> I rarely need to only check for the existence of a file,
Well, exists is not just a predicate - it returns the path if it
exists. So chains like 'exists 'foo' or exists 'foo' or exists
'foo.txt'' will return the first existing variant.
> splitpath, splitext -> interesting, but what types of paths does it support? Unix and Windows?
The implementation is not the obvious one (constructing patterns that
match anything). For Windows, both \ and / are considered path
separators, for Unix only /. They scan backwards from the end so
should be hard to confuse.
> tstring -> I think this is really complicated. My solution for this is a parametric algorithm that I customize differently for every use
I like the idea of parameterized stringifiers, but the idea was
something basic and robust, not pretty. However, the temptation to
add some flags is strong (pretty-printing with indentation.) It's
intended for debugging so serialization is less important.
> update -> if I understand what this function is supposed to do, what I use instead is:
Ah, using rawset is an interesting touch - but allowing general
indexing is both faster and more general. 'update' is for _adding_
key-value pairs to the destination from the source. I think it makes
more sense to call it 'import'.
> All other table funcs -> these are very common indeed, but I rather use the basic Lua constructs that are more efficient and express their precise semantics better than a function name.
The array-like functions are about as efficient as they can be (e.g.
avoid ipairs if you want to be fast!). It's often a Good Name that
makes such a thing useful.
I'm tending to think that tfilter and tmap are not so common. If tmap
survives it should operate on both the keys and values.
> throw/safe -> I rather use 'assert(f(...))'/'pcall(f, ...)', or write specific wrapper functions that adjust the function contract to the model of the code I'm writing (e.g. converting string errors to structured exceptions).
It's not my personal style, but Jay mentioned them ;) I'm not married to them.
> bind1, compose -> I never felt the need to use such thing.
I use them to scratch my functional itch ;) They can be useful when
you have a function which is almost right, for instance you need to
pass a method call as a callback; that would be bind1(obj.method,obj).
> class -> This one I use a lot (see LOOP and OiL), but it may be more problematic than the functions above in the sense of obscure semantics for people not familiar with it.
I have tried to make it very simple; it's metatable-chain inheritance.
The class may have a constructor _init; if it doesn't and the base
has, then base's _init is called. Base ctor can be called as
self:super(...), which is short for the clumsy
self._base._init(self,...). Only __tostring is implicitly inherited.
(Personally I prefer 'fat metatable' inheritance which doesn't
penalize long inheritance chains and can implicitly pull in all
> is_a -> I guess this is only a natural consequence of adopting a class model with inheritance.
Yes, I rarely think like that these days. The more natural way is to
'check capabilities'; does this object have a read() method? I'm
tending towards Animal.class_of(cat) which cuts down my global
function count ;)