Proposal: lua_pushfoo() should return 1

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

Proposal: lua_pushfoo() should return 1

Rena
More accurately, it should return the number of values it pushed,
which for most push functions will always be 1.

That would simplify returning a value slightly:

return lua_pushinteger(L, 42);

instead of:
lua_pushinteger(L, 42);
return 1;

--
Sent from my Game Boy.

Reply | Threaded
Open this post in threaded view
|

Re: Proposal: lua_pushfoo() should return 1

Luiz Henrique de Figueiredo
> More accurately, it should return the number of values it pushed,
> which for most push functions will always be 1.

lua_pushlstring and friends already return the pushed string,
and that is useful.

Reply | Threaded
Open this post in threaded view
|

Re: Proposal: lua_pushfoo() should return 1

Hao Wu
In reply to this post by Rena


On Monday, September 1, 2014, Rena <[hidden email]> wrote:
More accurately, it should return the number of values it pushed,
which for most push functions will always be 1.

That would simplify returning a value slightly:

return lua_pushinteger(L, 42);

instead of:
lua_pushinteger(L, 42);
return 1;

How about

return (lua_pusxx(), 1)
 

--
Sent from my Game Boy.

Reply | Threaded
Open this post in threaded view
|

Re: Proposal: lua_pushfoo() should return 1

Coda Highland
On Mon, Sep 1, 2014 at 5:29 PM, Hao Wu <[hidden email]> wrote:

>
>
> On Monday, September 1, 2014, Rena <[hidden email]> wrote:
>>
>> More accurately, it should return the number of values it pushed,
>> which for most push functions will always be 1.
>>
>> That would simplify returning a value slightly:
>>
>> return lua_pushinteger(L, 42);
>>
>> instead of:
>> lua_pushinteger(L, 42);
>> return 1;
>
>
> How about
>
> return (lua_pusxx(), 1)

A clever hack, but there's a high likelihood of confusion since the
language being interfaced with supports multiple return values,
whereas comma operator hacks in C are considered bad form.

/s/ Adam

Reply | Threaded
Open this post in threaded view
|

Re: Proposal: lua_pushfoo() should return 1

Tim Hill

On Sep 1, 2014, at 7:11 PM, Coda Highland <[hidden email]> wrote:

On Mon, Sep 1, 2014 at 5:29 PM, Hao Wu <[hidden email]> wrote:


On Monday, September 1, 2014, Rena <[hidden email]> wrote:

More accurately, it should return the number of values it pushed,
which for most push functions will always be 1.

That would simplify returning a value slightly:

return lua_pushinteger(L, 42);

instead of:
lua_pushinteger(L, 42);
return 1;


How about

return (lua_pusxx(), 1)

A clever hack, but there's a high likelihood of confusion since the
language being interfaced with supports multiple return values,
whereas comma operator hacks in C are considered bad form.

/s/ Adam

With the odd special exception (for example, it’s nearly impossible to write a decent assert() macro without it).

—Tim

Reply | Threaded
Open this post in threaded view
|

Re: Proposal: lua_pushfoo() should return 1

Coda Highland
On Mon, Sep 1, 2014 at 7:40 PM, Tim Hill <[hidden email]> wrote:

>
> On Sep 1, 2014, at 7:11 PM, Coda Highland <[hidden email]> wrote:
>
> On Mon, Sep 1, 2014 at 5:29 PM, Hao Wu <[hidden email]> wrote:
>
>
>
> On Monday, September 1, 2014, Rena <[hidden email]> wrote:
>
>
> More accurately, it should return the number of values it pushed,
> which for most push functions will always be 1.
>
> That would simplify returning a value slightly:
>
> return lua_pushinteger(L, 42);
>
> instead of:
> lua_pushinteger(L, 42);
> return 1;
>
>
>
> How about
>
> return (lua_pusxx(), 1)
>
>
> A clever hack, but there's a high likelihood of confusion since the
> language being interfaced with supports multiple return values,
> whereas comma operator hacks in C are considered bad form.
>
> /s/ Adam
>
>
> With the odd special exception (for example, it’s nearly impossible to write
> a decent assert() macro without it).

Sure, of course, there's always a legitimizing use (or else it wouldn't exist).

/s/ Adam

Reply | Threaded
Open this post in threaded view
|

Re: Proposal: lua_pushfoo() should return 1

Dirk Laurie-2
In reply to this post by Rena
2014-09-02 1:58 GMT+02:00 Rena <[hidden email]>:

> That would simplify returning a value slightly:
>
> return lua_pushinteger(L, 42);
>
> instead of:
> lua_pushinteger(L, 42);
> return 1;

It saves two non-whitespace characters, sometimes a pair
of braces too, at the expense of making life harder for the
person who reads the code. "return 1" is highly likely to be
in a function exported to Lua, "return <expresion>" often
is in a local function.

Reply | Threaded
Open this post in threaded view
|

Re: Proposal: lua_pushfoo() should return 1

Hao Wu
In reply to this post by Tim Hill
On Mon, Sep 1, 2014 at 7:40 PM, Tim Hill <[hidden email]> wrote:

>
> On Sep 1, 2014, at 7:11 PM, Coda Highland <[hidden email]> wrote:
>
> On Mon, Sep 1, 2014 at 5:29 PM, Hao Wu <[hidden email]> wrote:
>
>
>
> On Monday, September 1, 2014, Rena <[hidden email]> wrote:
>
>
> More accurately, it should return the number of values it pushed,
> which for most push functions will always be 1.
>
> That would simplify returning a value slightly:
>
> return lua_pushinteger(L, 42);
>
> instead of:
> lua_pushinteger(L, 42);
> return 1;
>
>
>
> How about
>
> return (lua_pusxx(), 1)
>
>
> A clever hack, but there's a high likelihood of confusion since the
> language being interfaced with supports multiple return values,
> whereas comma operator hacks in C are considered bad form.
>
> /s/ Adam
>
>
> With the odd special exception (for example, it’s nearly impossible to write
> a decent assert() macro without it).

curious what the use case here is? mind to explain?

>
> —Tim
>

Reply | Threaded
Open this post in threaded view
|

Re: Proposal: lua_pushfoo() should return 1

Tim Hill

On Sep 1, 2014, at 11:07 PM, Hao Wu <[hidden email]> wrote:




With the odd special exception (for example, it’s nearly impossible to write
a decent assert() macro without it).

curious what the use case here is? mind to explain?


—Tim

In non-debug builds, assert() should typically compile to nothing, so it introduces no run-time overhead for non-debug builds. For debug builds, assert(e) should do nothing if e is true, or abort with an error if e is false. However, assert() really needs to be an expression so it can be placed anywhere an expression is expected.

So, how to code assert()? It cannot be an “if” statement, since this is not an expression. Enclosing the “if” in braces also fails, since that can cause problems with nested “if” statements and if..else constructs. So you end up with something like this…

#if defined(DEBUG) || defined(_DEBUG)
#define assert(e) ( (void) ((e) ? g_nAssertPassCount++ : (PANIC("assert failed: '" #e "'"), 0)) )
#else
#define assert(e) ( (void) 0 )
#endif

The comma operator here is necessary to discard the result of evaluating the asserted expression.

You can do better of course  if the compiler allows inline functions.

—Tim

Reply | Threaded
Open this post in threaded view
|

Re: Proposal: lua_pushfoo() should return 1

Hao Wu
On Mon, Sep 1, 2014 at 11:22 PM, Tim Hill <[hidden email]> wrote:

>
> On Sep 1, 2014, at 11:07 PM, Hao Wu <[hidden email]> wrote:
>
>
>
>
> With the odd special exception (for example, it’s nearly impossible to write
> a decent assert() macro without it).
>
>
> curious what the use case here is? mind to explain?
>
>
> —Tim
>
>
> In non-debug builds, assert() should typically compile to nothing, so it
> introduces no run-time overhead for non-debug builds. For debug builds,
> assert(e) should do nothing if e is true, or abort with an error if e is
> false. However, assert() really needs to be an expression so it can be
> placed anywhere an expression is expected.
>
> So, how to code assert()? It cannot be an “if” statement, since this is not
> an expression. Enclosing the “if” in braces also fails, since that can cause
> problems with nested “if” statements and if..else constructs. So you end up
> with something like this…
>
> #if defined(DEBUG) || defined(_DEBUG)
> #define assert(e) ( (void) ((e) ? g_nAssertPassCount++ : (PANIC("assert
> failed: '" #e "'"), 0)) )
> #else
> #define assert(e) ( (void) 0 )
> #endif
>
> The comma operator here is necessary to discard the result of evaluating the
> asserted expression.
>
> You can do better of course  if the compiler allows inline functions.

Thanks, very elaborative!

>
> —Tim
>

Reply | Threaded
Open this post in threaded view
|

Re: Proposal: lua_pushfoo() should return 1

Dirk Zoller-2
In reply to this post by Rena
On 09/02/2014 01:58 AM, Rena wrote:

> More accurately, it should return the number of values it pushed,
> which for most push functions will always be 1.
>
> That would simplify returning a value slightly:
>
> return lua_pushinteger(L, 42);
>
> instead of:
> lua_pushinteger(L, 42);
> return 1;


Besides the small simplification for the writer of the code,
this would allow the C-compiler to do tail call optimization.

    lua_pushx (L, xxx);
    return 1;

compiles to

    call lua_pushx
    mov 1, register
    return

where if lua_pushx would return 1, the then possible source code

    return lua_pushx (L, xxx)

often times would be compiled to just:

    jump lua_pushx


So there would actually be a small technical benefit.



Reply | Threaded
Open this post in threaded view
|

Re: Proposal: lua_pushfoo() should return 1

Roberto Ierusalimschy
>    [...]
>
> where if lua_pushx would return 1, the then possible source code
>
>    return lua_pushx (L, xxx)
>
> often times would be compiled to just:
>
>    jump lua_pushx
>
>
> So there would actually be a small technical benefit.

If you really want to go to this level (which I think is pure
speculation), you should consider also the cost of all useless
"mov $1, %eax" inside those 'lua_pushinteger' not used in returns
(paid by all compilers) :-)

-- Roberto

Reply | Threaded
Open this post in threaded view
|

Re: Proposal: lua_pushfoo() should return 1

Dirk Zoller-2
On 09/02/2014 01:57 PM, Roberto Ierusalimschy wrote:

>>     [...]
>>
>> where if lua_pushx would return 1, the then possible source code
>>
>>     return lua_pushx (L, xxx)
>>
>> often times would be compiled to just:
>>
>>     jump lua_pushx
>>
>>
>> So there would actually be a small technical benefit.
>
> If you really want to go to this level (which I think is pure
> speculation), you should consider also the cost of all useless
> "mov $1, %eax" inside those 'lua_pushinteger' not used in returns
> (paid by all compilers) :-)

Did you try or do you speculate I'm just speculating?

This would go along with establishing the "return lua_pushsomething(..."
as an idiom in order reap these benefits.

They are of at least the same significance as those that at one point
made you start writing

    return luaL_error(...)

http://lua-users.org/lists/lua-l/2013-02/msg00463.html


Reply | Threaded
Open this post in threaded view
|

Re: Proposal: lua_pushfoo() should return 1

Patrick Donnelly
In reply to this post by Coda Highland
On Mon, Sep 1, 2014 at 10:11 PM, Coda Highland <[hidden email]> wrote:

> On Mon, Sep 1, 2014 at 5:29 PM, Hao Wu <[hidden email]> wrote:
>>
>>
>> On Monday, September 1, 2014, Rena <[hidden email]> wrote:
>>>
>>> More accurately, it should return the number of values it pushed,
>>> which for most push functions will always be 1.
>>>
>>> That would simplify returning a value slightly:
>>>
>>> return lua_pushinteger(L, 42);
>>>
>>> instead of:
>>> lua_pushinteger(L, 42);
>>> return 1;
>>
>>
>> How about
>>
>> return (lua_pusxx(), 1)
>
> A clever hack, but there's a high likelihood of confusion since the
> language being interfaced with supports multiple return values,
> whereas comma operator hacks in C are considered bad form.

Huh? Comma operators are rather common, just perhaps not understood
well. Hell, this return idiom is easy to find:

return (errno = EFOO, -1);

I don't see any issue with:

return (lua_pushnil(L), lua_pushstring(L, "error"), 2);

which could easily be defined as a macro. Sure does make life easier
for the C programmer.

--
Patrick Donnelly

Reply | Threaded
Open this post in threaded view
|

Re: Proposal: lua_pushfoo() should return 1

Rena
In reply to this post by Luiz Henrique de Figueiredo
On Mon, Sep 1, 2014 at 8:13 PM, Luiz Henrique de Figueiredo
<[hidden email]> wrote:
>> More accurately, it should return the number of values it pushed,
>> which for most push functions will always be 1.
>
> lua_pushlstring and friends already return the pushed string,
> and that is useful.
>

Well, that definitely trumps my idea then. I guess I'll just go back
to writing "return 1" a lot. ;-)

--
Sent from my Game Boy.

Reply | Threaded
Open this post in threaded view
|

Re: Proposal: lua_pushfoo() should return 1

Steven Degutis
Fwiw, I like writing "return 1" a lot. It's clear and consise. It
makes it easier for me to read my own code. :)

On Tue, Sep 2, 2014 at 10:40 AM, Rena <[hidden email]> wrote:

> On Mon, Sep 1, 2014 at 8:13 PM, Luiz Henrique de Figueiredo
> <[hidden email]> wrote:
>>> More accurately, it should return the number of values it pushed,
>>> which for most push functions will always be 1.
>>
>> lua_pushlstring and friends already return the pushed string,
>> and that is useful.
>>
>
> Well, that definitely trumps my idea then. I guess I'll just go back
> to writing "return 1" a lot. ;-)
>
> --
> Sent from my Game Boy.
>

Reply | Threaded
Open this post in threaded view
|

Re: Proposal: lua_pushfoo() should return 1

Tim Hill

On Sep 2, 2014, at 8:53 AM, Steven Degutis <[hidden email]> wrote:

> Fwiw, I like writing "return 1" a lot. It's clear and consise. It
> makes it easier for me to read my own code. :)
>
> On Tue, Sep 2, 2014 at 10:40 AM, Rena <[hidden email]> wrote:
>> On Mon, Sep 1, 2014 at 8:13 PM, Luiz Henrique de Figueiredo
>> <[hidden email]> wrote:
>>>> More accurately, it should return the number of values it pushed,
>>>> which for most push functions will always be 1.
>>>
>>> lua_pushlstring and friends already return the pushed string,
>>> and that is useful.
>>>
>>
>> Well, that definitely trumps my idea then. I guess I'll just go back
>> to writing "return 1" a lot. ;-)
>>
>> --
>> Sent from my Game Boy.
>>
>

+1


Reply | Threaded
Open this post in threaded view
|

Re: Proposal: lua_pushfoo() should return 1

Dirk Zoller-2
In reply to this post by Roberto Ierusalimschy
On 02.09.2014 13:57, Roberto Ierusalimschy wrote:

>>    [...]
>>
>> where if lua_pushx would return 1, the then possible source code
>>
>>    return lua_pushx (L, xxx)
>>
>> often times would be compiled to just:
>>
>>    jump lua_pushx
>>
>>
>> So there would actually be a small technical benefit.

Seeing my compilers do this all the time, I was curious how
common it actually is and how much it helps. The lua_pushnumber()
is an ideal case for studying this.

Compilers that do tail call elimination as described are:

  All modern compilers on Linux/unix-amd64: GCC, Sun, Intel, CLang.
  GCC for Arm 32 bits.

Compilers that miss out this opportunity to emit smarter code:

  All I tried for 32 bits Intel including MS.
  GCC for Windows 64 bits.
  GCC for sparc.

And what does it save?

Test with a tiny function adding two numbers returning the sum.
It takes around 45 nsec on my box:

    return lua_pushnumber1(L,lua_tonumber(L,1)+lua_tonumber(L,2))

The 1-returning pushnumber used to allow for tail call elimination
reduces the runtime of this test by measly 1-2 nsec vs. the standard
prodedure. Just enough to see a small improvement.

The time of this simple test is mostly spent in lua_tonumber.

Other interesting point learned: This tiny function to add
two numbers in C is not slower than a Lua function returning
the sum of two numbers. I was always wondering if all those
lua_tothis(), lua_pushthat() weren't quite slow. I think
lua_tonumber() is slow but Lua functions pay that same price.


The idea of changing the return value of lua_pushfoo() is of course
anyway dead because pushstring already does something different.



> If you really want to go to this level (which I think is pure
> speculation), you should consider also the cost of all useless
> "mov $1, %eax" inside those 'lua_pushinteger' not used in returns
> (paid by all compilers) :-)
>
> -- Roberto

Reply | Threaded
Open this post in threaded view
|

Re: Proposal: lua_pushfoo() should return 1

Tim Hill

On Sep 2, 2014, at 11:45 PM, duz <[hidden email]> wrote:

> On 02.09.2014 13:57, Roberto Ierusalimschy wrote:
>>>   [...]
>>> where if lua_pushx would return 1, the then possible source code
>>>   return lua_pushx (L, xxx)
>>> often times would be compiled to just:
>>>   jump lua_pushx
>>> So there would actually be a small technical benefit.
>

There are two advantages to tail-calls: the first is a small performance improvement which collapses a call/ret into a jump. The much bigger (potential) advantage is that it doesn’t use stack space, and this means that recursive functions that can take advantage of this do not run the risk of stack overflows.

—Tim


Reply | Threaded
Open this post in threaded view
|

Re: Proposal: lua_pushfoo() should return 1

Chris Emerson
On Wed, Sep 03, 2014 at 12:45:51AM -0700, Tim Hill wrote:
> There are two advantages to tail-calls: the first is a small performance
> improvement which collapses a call/ret into a jump.  The much bigger
> (potential) advantage is that it doesn’t use stack space, and this means
> that recursive functions that can take advantage of this do not run the
> risk of stack overflows.

Of course you can't actually portably take advantage of that in C, as the
standard doesn't guarantee anything, unlike in Scheme etc.  So it's more of
a nice-to-have optimisation.

Chris

12