lua-users home
lua-l archive

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


On Thu, 29 Apr 2010 22:17:45 -0700
Brian Maher <brimworks@gmail.com> wrote:

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

I think this may be my favorite solution thus far.

> 
> 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?).

Good call on the large arrays issue; I'd still like to be able to do
something like this:

local a, b, c = perl_func();

But I think I can add another context function for that.

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

I'd argue that the default context should be list, actually.  If I call
a function that returns a single scalar in scalar context, that works
fine.  But if I call a function that returns a list in scalar context,
it will return the length of the list!  However, in list context,
returning a list obviously works ok, and returning a single scalar
would be equivalent to returning a one-element list.

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

Whoa, good call on that!  I didn't even think of nil vs undef...

Thanks for all the input, Brian!

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

Attachment: signature.asc
Description: PGP signature