13

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
jubilatious1
  • 1,999
  • 10
  • 18
Joseph Brenner
  • 664
  • 3
  • 14

2 Answers2

11

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


Dealing with the Inlines

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.

raiph
  • 31,607
  • 3
  • 62
  • 111
  • I recommend waiting a day or so before posting an answer to your own question. – Brad Gilbert Aug 01 '19 at 17:20
  • 1
    I appreciate the Perl5 knowledge in this SO Question, and in the 2 (remaining?) answers. But any commentary regarding "answering one's own question" appears moot at this point in time. – jubilatious1 Mar 13 '21 at 03:07
  • 1
    @jubilatious1 Thanks. My bit about answering one's own question was moot when I wrote it too. What I meant was... Nevermind. :) Answer edited. – raiph Mar 16 '21 at 23:04
10

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
  • 12,710
  • 1
  • 41
  • 63
  • 1
    Yes raiph is right, the story is a little more complicated than this: 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 – Joseph Brenner Jul 02 '19 at 23:06
  • Okay, one more time: – Joseph Brenner Jul 02 '19 at 23:07
  • 1
    Yes raiph is right, the story is a little more complicated than this: `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` – Joseph Brenner Jul 02 '19 at 23:08
  • 2
    You know, I find it peculiar that some people don't get why not everyone likes stackoverflow. I'll do another update of my question to get in my code in a readable fashion. – Joseph Brenner Jul 02 '19 at 23:09