Perl6:为Perl5模块获取数组引用

con*_*con 6 perl6

我正在尝试使用Excel :: Writer :: XLSX在Perl6中编写Excel笔记本.

我正在使用Inline :: Perl5 via use Excel::Writer::XLSX:from<Perl5>

具体来说,我想像在Perl5中那样写一行:

$worksheet -> write_row(0,0, \@line);
Run Code Online (Sandbox Code Playgroud)

但这会给出错误

要将数组,散列或子传递给Perl 6中的函数,只需按原样传递即可.对于Perl 5的ref运算符的其他用途,请考虑使用:: =进行绑定.如果您打算捕获单个变量,则将括号括起为(...).

所以我试试建议1:

$worksheet.write_row(0,0, @line)

这给出了错误

在-e第0行调用write_row()时不是数组引用.

advice2:

$worksheet.write_row(0,0, ::=@line);
Run Code Online (Sandbox Code Playgroud)

在-e第0行调用write_row()时不是数组引用.

$worksheet.write_row(0,0, (@line));
Run Code Online (Sandbox Code Playgroud)

这给出了同样的错误.

如何在Perl6中使用Excel :: Writer :: XLSX将数组写入一行?

rai*_*iph 8

解决方案是编写$@array而不是\@array:

$worksheet.write_row(0,0, $@line)
Run Code Online (Sandbox Code Playgroud)

本答案的其余部分是使用已安装的外语适配器编写代码并处理出现的任何问题的简要指南.我打算将它作为一般资源,这个答案远远超出了这个具体问题.

它从明显的问题"为什么$@foo?"开始,讨论如何成功使用外语适配器,并通过解释为什么警告消息无益而关闭.

为什么$@foo

写入$@foo到通过@foo作为数组引用到P5是一种简单而自然的使用现有的P6功能.

也就是说,用户不需要了解$P6的这个功能,也不需要知道如何Inline::Perl5使用它来完成他们想要的工作(编写P6代码,将数组引用从P5模块传递给函数) .

所以"为什么$@foo?" 的主要答案 是你用那种方式写它并且它有效.\ O /

一个人怎么会知道神奇的咒语?

我得到了从Inline :: Perl5的README传递数组引用的解决方案:

HASHARRAY引用是自动进行的,如果Perl 6的对象是集装箱:

$p5obj.takes-an-array:      [<a b c>];
$p5obj.takes-an-array-ref: $[<a b c>];
Run Code Online (Sandbox Code Playgroud)

("容器化"一词指的是P6概念,lizmat很好地解释了那些在P6文章中的容器中知道P5的人.但是容器在技术上并不是为什么 $@foo在使用时意味着P5中的数组引用Inline::Perl5.是的,它有效.不,它不一定是这样.)

为什么$@foo在P6中意味着P5中的数组ref?

写作$@foo正确的事情的原因不是因为P6语言或编译器说它是.

一个合适的 P6功能,但正确的做法是niner(作者Inline::Perl5)这样说.

为什么niner选择$@foo

大概是因为它:

  • 很容易为新手写作;

  • 当有人了解P6时,为此目的是有意义的;

  • 对于niner来说很容易记录;

  • 很容易以高性能的方式将其P6含义(一个Array在a中Scalar)转换为目标P5含义(一个P5数组引用).

使用外语适配器时会发生什么

Inline::Perl5是几种外语适配器之一.这些适配器允许P6代码嵌入用这些外语编写的代码和/或使用用这些外语编写的模块.

当Rakudo P6编译器:from<Perl5>use语句中看到它时,它隐式调用先前安装的P6模块Inline::Perl5.

Inline::Perl5安装编组代码,自动将P6代码映射到P5代码和从P5代码映射,这样P6和P5可以一起工作,而且操作简单.

理想情况下,适配器只会完成它们的工作而你永远不必考虑它们.但:

  • 虽然42在P6中映射到任何和所有外语的显而易见的事情是它们表示整数的值42,但对于更高级别的数据结构,函数,引用等,映射并不总是那么直截了当.有时令人惊讶的是它可以是什么写完P6代码(你可以创建一个P6类,它是P5类的一个子类,就像它是普通的P6代码一样!)但有时你必须遵循一个规则(如本例中的如何将P6数组传递给P5作为数组引用).请参阅下面的适配器文档部分.

  • P6语言和编译器不知道映射正在进行.因此,他们显示的任何错误或警告信息都可能无益,甚至误导.此外,适配器错误与P6中的错误,编译器和正在使用的外语模块中的错误是分开的.请参阅下面的警告和错误部分.

使外语适配器发生的自动映射远非自动化.有才能的开发人员必须编写适配器代码来执行所有数据,异常等的编组.

给定足够的经过时间(年),如果您只想在P6中使用该语言的模块或代码,那么适配器可能能够接近理想状态,您无需考虑适配器的存在.你只是使用它,它总是像在外语中一样工作.

亲爱的读者和我们所有人,通过现有的适配器使用外部模块,并在特定功能似乎不起作用时编写SO问题和文件问题,这种方式可以更快地为您提供理想.谢谢@con,niner以及其他所有实现这一目标的人.

适配器文档

唯一能够确定您应该编写什么P6代码才能使用您使用的外语模块的方法:from<...>是:

  • 阅读外语模块的文档,看看它的期望; 然后

  • 阅读适配器的文档,了解如何编写相应的P6代码,该代码为外语和外语模块提供了他们所期望的内容.

在这个例子中,我们讨论的是使用:from<Perl5>适配器Inline::Perl5.它的文档目前是其github项目repo README.因此,要了解您应该编写什么来为P5和P5模块提供他们期望的内容,请阅读该文档.

每个适配器都有自己的文档; 请参阅modules.perl6.org上的列表以获取链接.

警告和错误

如果在P6中使用外语模块时出现任何问题(直接在该外语中使用相同的代码时出错),那么:

  • 确保您已阅读相关适配器的文档;

  • 如果收到警告或错误消息,请确保参考适配器的文档及其问题队列,以查看它是否显示该特定消息;

  • 如果您认为在使用外语模块时在P6中工作(或不工作)的方式存在错误,该模块在直接使用该外语时工作正常,请参阅适配器的问题队列.例如,如果您正在使用,:from<Perl5>那么请参阅Inline::Perl5问题队列.如果您决定发布某些内容,请在此处发布,如果您不确定它是错误,或者在适配器的问题队列中发布.

由于P6语言和编译器不知道正在进行映射,因此警告和错误消息在学习使用涉及遵循以下规则(例如$@foo此SO 的规则)的外语适配器的任何方面的上下文中可能会产生误导.

在P5问题的情况下,P6试图帮助编写P6代码的P5编码器以及在使用时尝试回火可能会加剧这种情况Inline::Perl5.问题中的例子就是一个很好的例子:

To pass an array, hash or sub to a function in Perl 6, just pass it as is.
Run Code Online (Sandbox Code Playgroud)

P6认为您可能习惯使用前缀编写数组引用\.它认为您可能不知道您不需要在P6中编写斜杠.它没有意识到你试图坚持获得P5将通过的数组引用Inline::Perl5.

For other uses of Perl 5's ref operator consider binding with ::= instead.
Run Code Online (Sandbox Code Playgroud)

P6认为你正在尝试做P5通常做的事情\,不是因为你想要使用P5而是因为你知道P5,想要在不涉及P5的情况下在P6中完成某些事情,并且希望完全相同的语法有效.

(顺便说一句,这个::=建议肯定无济于事 - 因为::=还没有实现!)

Parenthesize as (...) if you intended a capture of a single variable.
Run Code Online (Sandbox Code Playgroud)

P6并不认为你试图让P5功能与数组引用一起工作.它认为你正在尝试创造一个P6 Capture.

它的建议应该被解释为建议你写\(@foo)而不是\@foo创建一个Capture包含@foo.

它已经警告过使用\@foo意味着Capture正是因为P5开发人员可能会认为它会创建一个数组引用.

总之,P6不知道Inline::Perl5存在,或者它会对您的代码做任何事情.相反,它的建议是尝试将P5语法和它认为正在使用的概念转换为P6中相应的语法和概念.这是不是要告诉我如何写适合用于映射到P5 P6码企图通过Inline::Perl5.

这一切都说,我想有可能适配器开发者和核心P6开发者有一天会根据可用性问题来修改P5相关的警告和错误消息,例如已经由SO提出.