lua-users home
lua-l archive

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


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 <<