Popularity contest

classic Classic list List threaded Threaded
21 messages Options
12
Reply | Threaded
Open this post in threaded view
|

Popularity contest

Dirk Laurie
<disclaimer> I am not a crypto-Rubyist.  I'll confess to being an apostate
  from Python, but I never have used Ruby, and probably never will.
</disclaimer>

A recurrent theme on this list is wishful thinking about what might
be in the next Lua, and the answer, often after unnecessary acrimony,
is usually one that no bright hopeful wants to hear: write your core
patch or add-on module and put it on a page reachable from
http://lua-users.org/wiki/LuaAddons.

I've just visited http://lua-users.org/wiki/LuaPowerPatches (in search
of a readline-enabled version of file:read) and I can understand why
people feel p*ssed off when told to that.  Imagine telling your child
who has just glued together a toy plane: "That's nice.  Now go and put
it away in the loft."  Heck, some stuff in there was last updated in 2004
(download patch for Lua 5.0.X).  Your shiny new Haskell syntax patch
for Lua 5.2 will look great among those, OK?

Now suppose that the same page had just this: a "Like" button, and with
each item: "xxx people liked this".  As in Facebook.

And another button that quickly scans the page for you (whether in Perl
or in Lua) and displays a table of contents of Lua power patches sorted
top to bottom by popularity.  

Dirk


Reply | Threaded
Open this post in threaded view
|

Re: Popularity contest

steve donovan
On Sat, Sep 24, 2011 at 8:27 AM, Dirk Laurie <[hidden email]> wrote:
> And another button that quickly scans the page for you (whether in Perl
> or in Lua) and displays a table of contents of Lua power patches sorted
> top to bottom by popularity.

I don't think the problem is necessarily technical here. This sort of
thing can be done by Sputnik, Orbit or (dare I say) a combination of
several technologies. But who is going to feed it?  Wikis are
certainly not self-organizing; any order in the Lua Wiki is due to the
invisible labour of people like David Manura.  The whole web 2.0 thing
is that the users will do this, but there's a lot of capture and
categorization involved.

Also (at the risk of reigniting an old thread) there are license
issues if there is no clear attribution or owner of a patch. Which is
why with the snippets site (which grew out of a similar need) does
require each snippet to have an explicit license.

Patches by their nature are against specific code bases so that's
another thing that has to be made very explicit.

steve d.

Reply | Threaded
Open this post in threaded view
|

Re: Popularity contest

steve donovan
In reply to this post by Dirk Laurie
On Sat, Sep 24, 2011 at 8:27 AM, Dirk Laurie <[hidden email]> wrote:
> A recurrent theme on this list is wishful thinking about what might
> be in the next Lua,

Well, we haven't had that one for a while, so here are some ideas,
based on the observed trajectory so far.

There has been a tendency for global functions to get wrapped in
tables, and then to provide a suitable default metatable for
convenience:

  4.0  strfind(s,arg)
  5.0 string.find(s,arg)
  5.1 s:find(arg)

So it would be logical to expect collectgarbage -> gc.collect(),
gc.start(), etc.  It would be convenient if thread objects had a
default MT so that t:resume() can be used.

There is also a move away from excessive dependency on the global
table, which may lead to the following optional restricted mode: any
global access is a compiler error. You have to say __ENV.print;  this
becomes very tedious, so a useful bit of sugar would be:

import print,table,io

which makes suitable locals available.  Can also say 'import sin, cos
from math' of course. A little extra explicitness, and many anxieties
about global misspellings go away.

A little consistency: we know that f:method has no meaning as an
expression. It has been suggested that it can be given a consistent
meaning as function(...) return f:method(...) end, that is, it is a
closure over the self parameter. This is convenient for the common
case of providing callbacks which are methods of some object.

Now here's a concrete suggestion: people have often expressed a need
for deterministic finalizers that are called when a function goes out
of scope.  Perhaps something like Go's defer construct?

local f = open_connection()
finalize(function(e)
   f:close()
end)

that is, however we exit from this function, the finalizer will be
called.  As an error unwinds the stack, these finalizers are called
(pretty much the 'panic' mechanism of Go).  The difference is that
there is an error object which will be set if the finalizer was called
due to an uncaught error.

With the 'little consistency' above, it gets as simple as

finalize(f:close)

steve d.

Reply | Threaded
Open this post in threaded view
|

Re: Popularity contest

Dirk Laurie
On Mon, Sep 26, 2011 at 09:06:05AM +0200, steve donovan wrote:
> a useful bit of sugar would be:
>
> import print,table,io
>
> which makes suitable locals available.  Can also say 'import sin, cos
> from math' of course.

I find in a file called `dplutils.lua`, this:

~~~~
function util.import(from,items,to)
-- import(from,nil,to) copies everything; can be used as shallow table copy
-- import(from,items,_ENV) copies items to current environment
-- import(from,items) copies items to global environment
-- import(from) copies everything to global environment
-- import(from,foo) replaces foo by a new table if foo is not a table
-- import("name") copies from require "name"
-- if `items` has only one item, it need not be put into a table
-- all versions return the table `to`
    to = to or _G or getfenv()  -- specified or Lua 5.2 or Lua 5.1
-- FAQ: Why make _G the default, not _ENV?  
-- Ans: Otherwise in interactive mode nothing happens past the current line.
    if type(from)=='string' then from=require(from) end
    if type(to)~='table' then to={} end
    if type(items)=='string' then items={items} end
    if items
        then for i=1,#items do to[items[i]] = from[items[i]] end
        else for k,v in pairs(from) do to[k]=v end
        end
    return to
    end
~~~~

I'm sure most of you have something of the kind, probably a little
more sophisticated.

Sure, I start every program with

    util = import "dplutils"
    util.import(util)

but is the proposed 'import sin,cos from math' really so much more
convenient than 'import(math,{"sin","cos"})' as to justify two new
keywords?  (As I have confessed before, I'm a Python _apostate_).

Dirk


Reply | Threaded
Open this post in threaded view
|

Re: Popularity contest

liam mail
In reply to this post by steve donovan
On 26 September 2011 08:06, steve donovan <[hidden email]> wrote:
>
> There is also a move away from excessive dependency on the global
> table, which may lead to the following optional restricted mode: any
> global access is a compiler error. You have to say __ENV.print;  this
> becomes very tedious, so a useful bit of sugar would be:
>
>
> steve d.
>

By this do you mean the removing of _ENV (or a replacement) from being
set as an upvalue and upvalue table via modifying the core? If so why
would someone do this?

Liam

Reply | Threaded
Open this post in threaded view
|

Re: Popularity contest

steve donovan
On Mon, Sep 26, 2011 at 11:28 AM, liam mail <[hidden email]> wrote:
> By this do you mean the removing of _ENV (or a replacement) from being
> set as an upvalue and upvalue table via modifying the core?

_ENV stays the same in every way; but there would be a 'strict
compile' option which requires all variable access to be local.
Assuming then that _ENV always exists as an upvalue, then _ENV.print
is an explicit way to access a 'global'.

steve d,

Reply | Threaded
Open this post in threaded view
|

Re: Popularity contest

steve donovan
In reply to this post by Dirk Laurie
On Mon, Sep 26, 2011 at 10:52 AM, Dirk Laurie <[hidden email]> wrote:
> but is the proposed 'import sin,cos from math' really so much more
> convenient than 'import(math,{"sin","cos"})' as to justify two new
> keywords?  (As I have confessed before, I'm a Python _apostate_).

Ah, but note the difference

import sin, cos from math  => local sin, cos = math.sin, math.cos

the idea is to get away from globals.  Now this kind of thing can be
done with macros or whatnot, but can't be done with table magic.

steve d.

Reply | Threaded
Open this post in threaded view
|

Re: Popularity contest

steve donovan
In reply to this post by steve donovan
On Mon, Sep 26, 2011 at 12:05 PM, steve donovan
<[hidden email]> wrote:
> Assuming then that _ENV always exists as an upvalue, then _ENV.print
> is an explicit way to access a 'global'.

This is of course typical Monday morning nonsense; precisely because
_ENV can be redefined. So _G is what I mean here.

Except that in strict mode _G is an upvalue for any script, and any
access to 'globals' has to go through it. So you have to say

local print,io = _G.print, _G.io

up front.  (The import suggestion is merely sugar for this pattern)

steve d.

Reply | Threaded
Open this post in threaded view
|

Re: Popularity contest

Egil Hjelmeland
In reply to this post by steve donovan
Den 2011-09-26 12:07, skrev steve donovan:

> On Mon, Sep 26, 2011 at 10:52 AM, Dirk Laurie<[hidden email]>  wrote:
>> but is the proposed 'import sin,cos from math' really so much more
>> convenient than 'import(math,{"sin","cos"})' as to justify two new
>> keywords?  (As I have confessed before, I'm a Python _apostate_).
> Ah, but note the difference
>
> import sin, cos from math  =>  local sin, cos = math.sin, math.cos
>
> the idea is to get away from globals.  Now this kind of thing can be
> done with macros or whatnot, but can't be done with table magic.
>
> steve d.
>
>
Even more generic:

   local a,b,c from t

being equivalent to

   local a,b,c = t.a, t.b, t.c

Then the import can be written as

local sin, cos from require 'math'

But I not competent to assess the impact on the Lua grammar and
implementation..
Egil







Reply | Threaded
Open this post in threaded view
|

Re: Popularity contest

Dirk Laurie
In reply to this post by steve donovan
On Mon, Sep 26, 2011 at 12:07:25PM +0200, steve donovan wrote:

> On Mon, Sep 26, 2011 at 10:52 AM, Dirk Laurie <[hidden email]> wrote:
> > but is the proposed 'import sin,cos from math' really so much more
> > convenient than 'import(math,{"sin","cos"})' as to justify two new
> > keywords?  (As I have confessed before, I'm a Python _apostate_).
>
> Ah, but note the difference
>
> import sin, cos from math  => local sin, cos = math.sin, math.cos
>
> the idea is to get away from globals.  Now this kind of thing can be
> done with macros or whatnot, but can't be done with table magic.

OK, I'll rephrase my objection.

    Is the proposed 'import sin,cos from math' really so much more
    convenient than 'local sin,cos = math.sin,math.cos' as to justify
    two new keywords?

Personally I don't think it is clean and clever to make war veterans
like `sin` and `cos` local, but let's not cloud the syntax issue.

Dirk

Reply | Threaded
Open this post in threaded view
|

Re: Popularity contest

steve donovan
On Mon, Sep 26, 2011 at 2:04 PM, Dirk Laurie <[hidden email]> wrote:
> Personally I don't think it is clean and clever to make war veterans
> like `sin` and `cos` local, but let's not cloud the syntax issue.

It's a question of scope - if this is in a function, then this kind of
alias is readable, unambiguous, and faster to boot!

(for stock Lua that is, I think LuaJIT optimizes these cases by
hoisting out the reference of loops)

steve d.

Reply | Threaded
Open this post in threaded view
|

Re: Popularity contest

liam mail
In reply to this post by steve donovan
On 26 September 2011 11:31, steve donovan <[hidden email]> wrote:

> On Mon, Sep 26, 2011 at 12:05 PM, steve donovan
> <[hidden email]> wrote:
>> Assuming then that _ENV always exists as an upvalue, then _ENV.print
>> is an explicit way to access a 'global'.
>
> This is of course typical Monday morning nonsense; precisely because
> _ENV can be redefined. So _G is what I mean here.
>
> Except that in strict mode _G is an upvalue for any script, and any
> access to 'globals' has to go through it. So you have to say
>
> local print,io = _G.print, _G.io
>
> up front.  (The import suggestion is merely sugar for this pattern)
>
> steve d.
>
>

_G is normally an alais for _ENV is 5.2 or an alais for the value set
unless I am misunderstanding something and there are no global lookups
so to speak anymore (ie GETGLOBAL vm instructions now use a new
instruction GET/SETTABUP), so I still do not understand why
_ENV/_G.print would be needed unless there is a print in local scope.

Sorry maybe the Monday afternoon nonsense is the time it effects me :p

Liam

Reply | Threaded
Open this post in threaded view
|

Re: Popularity contest

steve donovan
On Mon, Sep 26, 2011 at 4:33 PM, liam mail <[hidden email]> wrote:
> unless I am misunderstanding something and there are no global lookups
> so to speak anymore (ie GETGLOBAL vm instructions now use a new
> instruction GET/SETTABUP),

This is true, but _in effect_ the _ENV mechanism gives you globals. As
I understand it, if a variable cannot be resolved to a local then it's
assumed to be a lookup on the upvalue _ENV.  (_G remains but isn't
special)

I still think it's useful to have a mode where uncontrolled global
access is verboten and a compile-time error.  The current workarounds
are not so elegant, often involving a custom build step that e.g. for
Lua 5.1 checks out any GETGLOBAL instructions.

steve d.

Reply | Threaded
Open this post in threaded view
|

Re: Popularity contest

Luiz Henrique de Figueiredo
> I still think it's useful to have a mode where uncontrolled global
> access is verboten and a compile-time error.  The current workarounds
> are not so elegant, often involving a custom build step that e.g. for
> Lua 5.1 checks out any GETGLOBAL instructions.

In both 5.1 and 5.2, the place to start patching is at singlevar in lparser.c,
right after the call to singlevaraux. See for instance
        http://lua-users.org/lists/lua-l/2006-10/msg00206.html

See also
        http://lua-users.org/lists/lua-l/2011-06/msg00091.html


Reply | Threaded
Open this post in threaded view
|

Re: Popularity contest

Mark Hamburg
In reply to this post by steve donovan
On Sep 26, 2011, at 12:06 AM, steve donovan wrote:

> A little consistency: we know that f:method has no meaning as an
> expression. It has been suggested that it can be given a consistent
> meaning as function(...) return f:method(...) end, that is, it is a
> closure over the self parameter. This is convenient for the common
> case of providing callbacks which are methods of some object.

Definitely convenient.

The other thing I find myself wanting is:

        obj:[ method_expr ]( ... )

as syntax for obj[ method_expr ]( obj, ... ).

This is useful when you need to compute the method to invoke. It has the benefit of avoiding the need to make sure you stick obj into a local variable to avoid double-evaluation. It also opens up the possibility that at some point in the future, colon might become a "real" operator and not just syntactic sugar.

This is actually easier to implement than obj:method as a way to create a closure since it mostly just takes as I recall some small parser revisions and a slight revision to OP_SELF.

Mark


Reply | Threaded
Open this post in threaded view
|

Re: Popularity contest

steve donovan
In reply to this post by Luiz Henrique de Figueiredo
On Mon, Sep 26, 2011 at 6:26 PM, Luiz Henrique de Figueiredo
<[hidden email]> wrote:
>> I still think it's useful to have a mode where uncontrolled global
> In both 5.1 and 5.2, the place to start patching is at singlevar in lparser.c,
> right after the call to singlevaraux.

Thanks, Luiz. I think such a patch could be very useful in developing
large code bases while remaining compatible with standard Lua

steve d.

Reply | Threaded
Open this post in threaded view
|

Re: Popularity contest

steve donovan
In reply to this post by steve donovan
On Mon, Sep 26, 2011 at 9:06 AM, steve donovan
<[hidden email]> wrote:
> local f = open_connection()
> finalize(function(e)
>   f:close()
> end)

Any feelings/opinions about finalizers? My feeling is that it could be
done fairly efficiently, although of course the devil is in the
details:  the guiding principle is "don't pay for what you don't use".

This can already be done with pcall all over the place, but it's messy
(and inefficient to create all those closures).

What it does provide is support for RAII and thus guarantees that
resources will be properly closed under all circumstances. For
instance, if you allocated a big temporary object then you do not have
to wait for the next GC cycle to have its memory reclaimed.

It's not the only finalization proposal, see

http://lua-users.org/lists/lua-l/2008-02/msg00243.html

steve d.

Reply | Threaded
Open this post in threaded view
|

Re: Popularity contest

Dirk Laurie
On Tue, Sep 27, 2011 at 11:08:45AM +0200, steve donovan wrote:

> On Mon, Sep 26, 2011 at 9:06 AM, steve donovan
> <[hidden email]> wrote:
> > local f = open_connection()
> > finalize(function(e)
> >   f:close()
> > end)
>
> Any feelings/opinions about finalizers? My feeling is that it could be
> done fairly efficiently, although of course the devil is in the
> details:  the guiding principle is "don't pay for what you don't use".
>

Suppose we had coroutine.kill(), would that be enough to implement
whatever the finalizer is needed for?

Dirk

Reply | Threaded
Open this post in threaded view
|

Re: Popularity contest

Tony Finch
In reply to this post by Mark Hamburg
Mark Hamburg <[hidden email]> wrote:

>
> The other thing I find myself wanting is:
>
> obj:[ method_expr ]( ... )
>
> as syntax for obj[ method_expr ]( obj, ... ).
>
> This is actually easier to implement than obj:method as a way to create
> a closure since it mostly just takes as I recall some small parser
> revisions and a slight revision to OP_SELF.

Here's one I prepared earlier...

--- a/src/lcode.c
+++ b/src/lcode.c
@@ -500,16 +500,16 @@ void luaK_storevar (FuncState *fs, expdesc *var, expdesc *ex) {
 }


-void luaK_self (FuncState *fs, expdesc *e, expdesc *key) {
-  int func;
+void luaK_self1 (FuncState *fs, expdesc *e) {
   luaK_exp2anyreg(fs, e);
   freeexp(fs, e);
-  func = fs->freereg;
   luaK_reserveregs(fs, 2);
-  luaK_codeABC(fs, OP_SELF, func, e->u.s.info, luaK_exp2RK(fs, key));
+}
+
+
+void luaK_self2 (FuncState *fs, expdesc *e, expdesc *key) {
+  luaK_codeABC(fs, OP_SELF, e->u.s.info, e->u.s.info, luaK_exp2RK(fs, key));
   freeexp(fs, key);
-  e->u.s.info = func;
-  e->k = VNONRELOC;
 }


--- a/src/lcode.h
+++ b/src/lcode.h
@@ -55,7 +55,8 @@ LUAI_FUNC int luaK_exp2anyreg (FuncState *fs, expdesc *e);
 LUAI_FUNC void luaK_exp2nextreg (FuncState *fs, expdesc *e);
 LUAI_FUNC void luaK_exp2val (FuncState *fs, expdesc *e);
 LUAI_FUNC int luaK_exp2RK (FuncState *fs, expdesc *e);
-LUAI_FUNC void luaK_self (FuncState *fs, expdesc *e, expdesc *key);
+LUAI_FUNC void luaK_self1 (FuncState *fs, expdesc *e);
+LUAI_FUNC void luaK_self2 (FuncState *fs, expdesc *e, expdesc *key);
 LUAI_FUNC void luaK_indexed (FuncState *fs, expdesc *t, expdesc *k);
 LUAI_FUNC void luaK_goiftrue (FuncState *fs, expdesc *e);
 LUAI_FUNC void luaK_storevar (FuncState *fs, expdesc *var, expdesc *e);
--- a/src/lparser.c
+++ b/src/lparser.c
@@ -780,8 +780,12 @@ static void primaryexp (LexState *ls, expdesc *v) {
       case ':': {  /* `:' NAME funcargs */
         expdesc key;
         luaX_next(ls);
-        checkname(ls, &key);
-        luaK_self(fs, v, &key);
+        luaK_self1(fs, v);
+        if (ls->t.token == '[')
+          yindex(ls, &key);
+        else
+          checkname(ls, &key);
+        luaK_self2(fs, v, &key);
         funcargs(ls, v);
         break;
       }

Tony.
--
f.anthony.n.finch  <[hidden email]>  http://dotat.at/
West FitzRoy, West Sole: Southerly 4 or 5, increasing 6 or 7, perhaps gale 8
later. Moderate or rough. Rain or showers. Good, occasionally poor.

Reply | Threaded
Open this post in threaded view
|

Re: Popularity contest

Pierre Chapuis
In reply to this post by steve donovan
On Tue, 27 Sep 2011 11:08:45 +0200, steve donovan wrote:
> On Mon, Sep 26, 2011 at 9:06 AM, steve donovan
> <[hidden email]> wrote:
>> local f = open_connection()
>> finalize(function(e)
>>   f:close()
>> end)
>
> Any feelings/opinions about finalizers?

I like them, but I like your "little consistency" even more
since I keep writing pcall(t:f) instead of pcall(t.f,f)...

--
Pierre Chapuis

12