Some simple Inline::Perl5 code returns a list, but it seems to return the count of the items rather than the actual list.
Changing the number of items involved changes the count.
use Inline::Perl5;
my $p5 = Inline::Perl5.new;
my $perl5_code = q:to/END/;
sub p5_data {
my @monsters = qw( godzilla blob tingler kong dorisday );
return @monsters;
}
p5_data();
END
my @stuff = $p5.run: $perl5_code;
say @stuff; # [5]
I thought I'd get the list of strings stored in the array, but instead it acts like something is switching it to scalar context.
Update:
ikeami points out that it works better to return the reference to the array:
return \@monsters;
Though, then you end up with an array in the first element of the @stuff array when you do this:
my @stuff = $p5.run: $perl5_code;
An alternate approach (from reading the Inline::Perl5 docs), is after doing a $p5.run
to define the perl5 sub, to call it from perl6:
my @stuff = $p5.call('p5_data');
Then the list return (return @monsters;
) gets loaded into the
array as I expected:
[godzilla blob tingler kong dorisday]
This is a recently installed Inline::Perl5 of version 0.40, on "Rakudo Star version 2019.03.1 built on MoarVM version 2019.03 implementing Perl 6.d".
Update2: So, it seems that "run" implies a scalar context and "call" is a list context.
use Inline::Perl5;
my $p5 = Inline::Perl5.new;
my $perl5_defsub = q:to/END/;
sub whadaya_want {
wantarray() ? 'LIST' : 'SCALAR';
}
END
$p5.run: $perl5_defsub;
my $run_context = $p5.run( 'whadaya_want' );
my $call_context = $p5.call( 'whadaya_want' );
say "run: ", $run_context;
say "call: ", $call_context;
# run: SCALAR
# call: LIST
Perl5::Inline
puts return values into scalar context.
As background, in Perl 5, context flows inwards into routines, so a routine always knows which context it's in.
In Perl 6, context flows outwards, so a routine returns an object that can behave differently in different context.
This impedance mismatch between Perl 5 and Perl 6 means that Inline::Perl5
has to decide to call Perl 5 routines in one context, and that's scalar.
As ikegami pointed out, the proper solution is to return a proper scalar, aka reference (in Perl 5 speak). Limitations in Inline::Perl5
might mean you need to explicitly dereference on the Perl 6 side.
Moritz's answer is excellent and explains IP5's dilemma. But niner is ingenious, so IP5 provides all the variations one needs:
Call a Perl sub in list context:
Inline::Perl5.new.call: 'subname', arg1, arg2 ...
See IP5: Call a Perl function.
Call a Perl sub in scalar context:
Inline::Perl5.new.run: 'subname arg1, arg2 ...'
or
EVAL 'subname arg1, arg2 ...', :lang<Perl5>
See IP5: Run arbitrary Perl code.
Call a Perl method in list context:
Use regular Raku syntax:
$perl-object .foo: arg1, arg2 ...
to call the foo
method on a Perl object held in $perl-object
passing it arg1
and arg2
as its first two arguments (ignoring the invocant).
See IP5: Invoke a method on a Perl object.
Call a Perl method in scalar context:
Use regular Raku syntax but insert Scalar
as the first positional argument (ignoring the invocant):
$perl-object .foo: Scalar, arg1, arg2 ...
to call the foo
method on a Perl object held in $perl-object
passing it arg1
and arg2
as its first two arguments.
IP5 removes the Scalar
before calling the Perl method.
See IP5: Invoking a method in scalar context.
I think Moritz's answer was a solid resolution of the question, and that mine has rounded it out.
But what if you're reading this and are interested in, or dealing with, other Inline issues?
The sections starting at What to expect when using foreign language adaptors of my answer to Raku: getting array ref for Perl Module are an attempt to outline a mini generic guide on what to expect, and how to deal with problems, relative to Raku's Inlines.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With