Inline:Perl5的列表返回给出项目数,而不是列表

时间:2019-07-02 02:02:59

标签: perl perl6

一些简单的Inline :: Perl5代码返回一个列表,但它似乎返回的是项目数而不是实际的列表。

更改所涉及的项目数会更改计数。

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]                                              

我以为我会得到存储在数组中的字符串列表,但是相反,它的行为就像是将其切换到标量上下文一样。

更新:

ikeami指出,将引用返回给 数组:

return \@monsters;

尽管如此,然后您在数组的第一个元素中得到一个数组 @stuff数组,当您这样做时:

my @stuff = $p5.run: $perl5_code;                              

另一种方法(通过阅读Inline :: Perl5文档)是在执行$p5.run来定义perl5子之后,然后从perl6调用它:

my @stuff = $p5.call('p5_data');  

然后将列表返回(return @monsters;)加载到 数组符合我的预期:

[godzilla blob tingler kong dorisday]

这是最近安装的Inline :: Perl5版本0.40,位于 “基于MoarVM版本2019.03构建的Rakudo Star版本2019.03.1 Perl 6.d”。

Update2:因此,似乎“运行”表示标量上下文,而“调用”则是列表上下文。

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

2 个答案:

答案 0 :(得分:6)

Perl5::Inline将返回值放入标量上下文中。

作为背景,在Perl 5中,上下文向内流入例程,因此例程始终知道它在哪个上下文中。

在Perl 6中,上下文向外流动,因此例程返回的对象在不同上下文中的行为可能不同。

Perl 5和Perl 6之间的阻抗不匹配意味着Inline::Perl5必须决定在一个上下文中调用Perl 5例程,这就是标量。

正如ikegami所指出的那样,正确的解决方案是返回正确的标量,又称引用(在Perl 5中讲)。 Inline::Perl5中的限制可能意味着您需要在Perl 6端显式取消引用。

答案 1 :(得分:6)

Moritz的回答解释了IP5的困境,但是,aiui却低估了niner的独创性。 :)

根据我对一段时间前与niner进行的交流,当前的IP5自述文件以及约瑟夫答案中的更新的了解,IP5提供了四个选项。


  

列表上下文中呼叫P5 sub

Inline::Perl5.new.call( 'subname', arg1, arg2 ... )

请参见IP5: Call a Perl 5 function


  

标量上下文中调用P5 sub

Inline::Perl5.new.run( 'subname arg1, arg2 ...' )

EVAL 'subname arg1, arg2 ...', :lang<Perl5>

请参见IP5: Run arbitrary Perl 5 code


  

列表上下文中调用P5 方法

使用常规P6语法:

$p5object.method( arg1, arg2 ... )

调用method中保存的Perl 5对象的$p5object方法,并将其arg1arg2作为其前两个参数。

请参见IP5: Invoke a method on a Perl 5 object


  

标量上下文中调用P5 方法

使用常规P6语法,但还要插入Scalar作为额外的第一个位置参数:

$p5object.method( Scalar, arg1, arg2 ... )

调用method中保存的Perl 5对象的$p5object方法,并将其arg1arg2作为其前两个参数。

IP5在调用Perl 5方法之前先删除Scalar

请参见IP5: Invoking a method in scalar context


处理内联的问题

Imo SO帖子是围绕Inline与P6一起使用开发知识库的理想方法。以下内容绝不妨碍发布帖子。确实,如果您没有解决问题而未发布有关此问题的解决方案,请考虑到此处发布一个问题和答案对以进行记录。

(SO文化通常完全支持这样的发布,即同一个人发布问题和答案并接受他们的答案,但是我认为[perl6]标记尤其合适,对于相关的问题和已解决的问题则尤其适用。到内联。)

借助上述方法,另请参见以my answer to Perl6: getting array ref for Perl5 Module使用外语适配器的预期内容开头的部分,以尝试获得有关处理类似问题的小型通用指南与P6内联。这只是第一次尝试,我很想获得反馈,尤其是有关它的问题,因此,如果您阅读了它,请考虑在其中任何指南在任何方面似乎都太多,太少或太困惑时,在此处进行评论。 TIA。