[Date Prev][Date Next][Thread Prev][Thread Next]
[Date Index]
[Thread Index]
- Subject: Re: Fw: Finding out the number of requested return values for a Lua-Perl bridge
- From: Brian Maher <brimworks@...>
- Date: Thu, 29 Apr 2010 22:17:45 -0700
I just had another thought...
What about doing syntax like this?
local foo = ...some perl function...
local result = (perl.scalar(foo))(args_to_foo)
This seems like the "closest" thing to how it would look like in the
"perl" world. The perl.scalar() function takes a single argument: a
perl function, and returns a single result which is the same perl
function, but with the context set to "scalar".
You could do a similar thing to force array context. When forcing
array context I would suggest *not* using lua's multi-return value
semantics since that depends on the "max stack size" as to how many
results can be returned. I know that a perl function can return an
array of 1,000's of results which would just blow-up the lua program.
So, I would suggest also creating a perl.array() function that takes a
single argument (a perl function) and returns a new function such that
when it is called it forces array context, therefore the results of
this new function is always a lua table that contains the array of
results (or perhaps it just returns a wrapper to that perl array?).
Note that you can also set the perl calling context to "void", so
perhaps a perl.void() function should also be created.
The next big question is "what should be the default context"? I
personally would argue for scalar context being the default since that
is probably the most common use-case. However, it does make the one
"intuitive" function (perl.scalar()) almost useless (unless someone
passed you a perl function and you didn't know what context it was in
and you wanted to be sure it was forced into scalar context).
As a side note, I would be careful about mapping a perl undef to a lua
nil since nil is treated rather specially in lua. In lua, if you set
a tables value to nil, then it deletes the key from the table. This
means that if you take the naive approach of mapping a perl array into
a lua table, then the table "size" (aka return of #table) won't always
match up with the perl array size if there are undef's in the perl
array. This means potential "information loss".
Hope This Helps.
Thanks,
-Brian
On Thu, Apr 29, 2010 at 11:56 AM, Rob Hoelz <rob@hoelzro.net> wrote:
> Forgot to send to lua-l.
>
> Begin forwarded message:
>
> Date: Thu, 29 Apr 2010 13:52:21 -0500
> From: Rob Hoelz <rob@hoelzro.net>
> To: Duncan Cross <duncan.cross@gmail.com>
> Subject: Re: Finding out the number of requested return values for a
> Lua-Perl bridge
>
>
> On Thu, 29 Apr 2010 19:18:54 +0100
> Duncan Cross <duncan.cross@gmail.com> wrote:
>
>> On Thu, Apr 29, 2010 at 6:41 PM, Rob Hoelz <rob@hoelzro.net> wrote:
>> > Duncan-
>> >
>> > Thanks for pointing out my 0-indexing; I must have Perl on the
>> > brain! =P
>> >
>> > The reason I wrote the last example as I did is because if I am
>> > able to detect how many return values my function is expected to
>> > return, I will force scalar context for one return value and list
>> > context for more than one. Here's an example of a function being
>> > called in both contexts, but returning one value:
>> >
>> > my $a = foo;
>> > my ( $a ) = foo;
>> >
>> > -Rob
>> >
>> > On Thu, 29 Apr 2010 18:37:00 +0100
>> > Duncan Cross <duncan.cross@gmail.com> wrote:
>> >
>> >> On Wed, Apr 28, 2010 at 5:21 PM, Rob Hoelz <rob@hoelzro.net> wrote:
>> >> > If I were to call foo in Perl, I could do it several ways:
>> >> >
>> >> > my $a = foo; # $a is 3
>> >> > my @values = foo; # $values[0] is 1, $values[1] is 2
>> >> > my ( $a, $b ) = foo; # $a is 1, $b is two
>> >> > my ( $a ) = foo; # $a is 1, the second return value is discarded
>> >> >
>> >> > The equivalent statements in Lua:
>> >> >
>> >> > local a = foo()
>> >> > local values = { foo() }
>> >> > local a, b = foo()
>> >> > local a = ({ foo() })[0] -- not sure how else to do this,
>> >> > really...
>> >>
>> >> Hi Rob,
>> >>
>> >> I don't know anything about Perl, but I think I can still usefully
>> >> comment on this last equivalent statement, that you're not sure how
>> >> else to do. All you need to do is:
>> >>
>> >> local a = foo()
>> >>
>> >> ...and the second value will be silently discarded. You don't need
>> >> to create a temporary table to do this. (Also, don't forget Lua
>> >> tables index from 1 rather than 0, unless you have patched your
>> >> version of Lua, so ({ foo() })[0] will always evaluate to nil
>> >> anyway.)
>> >>
>> >> -Duncan
>> >
>> >
>>
>> Hi Rob,
>>
>> Ah, okay, I understand now - what you were trying to say in that
>> example is a bit more subtle than I realised. That's what comes from
>> not reading things through properly :) Sorry for the noise.
>>
>> To contribute, how about a changing the bridge to expect a special
>> extra first parameter when calling these functions? true to return a
>> list, false to return a scalar, or one of a set of strings. You could
>> use this directly if that is not too much trouble, or wrap the
>> functions using something like this:
>>
>> function listFunc(func) return function(...) return
>> func(true, ...); end function scalarFunc(func) return
>> function(...) return func(false, ...); end
>>
>> fooList = listFunc(foo)
>> fooScalar = scalarFunc(foo)
>>
>> count = fooScalar()
>> a, b = fooList()
>>
>> It may not be quite as nice syntactically as Brian's suggestion, but
>> possibly easier to do.
>>
>> -Duncan
>
> Another thought: I could do what Pluto does and access Lua's private
> internal state by asking for the Lua headers' location at compile
> time. Not very nice, but it would get the job done.
>
--
Brian Maher >> Glory to God <<