Perl6:获取 Perl5 模块的数组引用 [英] Perl6: getting array ref for Perl5 Module

查看:49
本文介绍了Perl6:获取 Perl5 模块的数组引用的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

我通过 use Excel::Writer::XLSX:from<Perl5>

使用 Inline::Perl5

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

$worksheet ->write_row(0,0, \@line);

但这会导致错误

<块引用>

要将数组、散列或子传递给 Perl 6 中的函数,只需将其作为是.对于 Perl 5 的 ref 运算符的其他用途,请考虑使用 ::= 绑定反而.如果您打算捕获单个变量.

所以我尝试了advice1:

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

出现错误

<块引用>

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

建议 2:

$worksheet.write_row(0,0, ::=@line);

<块引用>

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

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

它给出了相同的错误.

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

解决方案

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

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

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

从明显的问题为什么 $@foo?"开始,讨论如何成功使用外语适配器,最后解释警告消息无用的原因.

为什么是 $@foo?

编写$@foo 以将@foo 作为数组reference 传递给P5 是对现有P6 功能的简单而自然的使用.

也就是说,用户不需要了解 P6 的这个 $ 特性,也不需要知道 Inline::Perl5 如何使用它,即可完成他们想要做什么(编写 P6 代码,将数组引用传递给 P5 模块中的函数).

所以主要回答为什么 $@foo?"是你这样写并且它有效.\o/

如何知道魔法咒语?

我从 Inline::Perl5 的 README:

<块引用>

HASHARRAY 引用在 Perl 6 对象被容器化时自动进行:

$p5obj.takes-an-array: [];$p5obj.takes-an-array-ref: $[];

(容器化"这个词指的是一个 P6 概念,lizmat 在她的 P6 中的容器 文章.但是容器在技术上实际上与为什么 $@foo 在使用 $@foo 表示 P5 中的数组引用无关code>Inline::Perl5.是的,它有效.不,它不必那样.)

为什么 P6 中的 $@foo 表示 P5 中的数组引用?

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

一个合适的 P6 特性,但它正确要做的事情的原因是niner(的作者Inline::Perl5) 是这样说的.

为什么niner选择$@foo?

大概是因为:

  • 对于新手来说很容易写;

  • 当有人开始了解 P6 时,这将是有意义的;

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

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

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

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

当乐堂 P6 编译器在 use 语句中看到 :from 时,它会隐式调用先前安装的名为 Inline::Perl5 的 P6 模块.

Inline::Perl5 安装编组代码自动将 P6 代码映射到 P5 代码和从 P5 代码映射,因此 P6 和 P5 可以轻松地协同工作.

理想情况下,适配器可以完成它们的工作,您永远不必考虑它们.但是:

  • 虽然将 P6 中的 42 映射到任何和所有外语的显而易见的事情是它们代表整数 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 试图帮助 P5 编码员编写 P6 代码而加剧,并且在使用 Inline::Perl5 时尝试适得其反.问题中的例子就是一个很好的例子:

要将数组、散列或子传递给 Perl 6 中的函数,只需按原样传递即可.

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

对于 Perl 5 的 ref 运算符的其他用途,请考虑使用 ::= 绑定.

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

(顺便说一句,::= 建议肯定没用——因为 ::= 还没有实现!)

括号为 (...) 如果您打算捕获单个变量.

P6 并不认为您正在尝试使 P5 函数与数组引用一起工作.它认为您正在尝试创建 P6 Capture.>

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

它已经警告使用 \@foo 来表示 Capture 正是因为 P5 开发人员可能会认为它会创建一个数组引用来编写它.

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

说了这么多,我想适配器开发人员和核心 P6 开发人员有可能有一天会根据此 SO 提出的可用性问题修改与 P5 相关的警告和错误消息.

I'm trying to write an Excel notebook in Perl6, using Excel::Writer::XLSX.

I'm using Inline::Perl5 via use Excel::Writer::XLSX:from<Perl5>

Specifically, I want to write a row like I did in Perl5:

$worksheet -> write_row(0,0, \@line);

but this gives error

To pass an array, hash or sub to a function in Perl 6, just pass it as is. For other uses of Perl 5's ref operator consider binding with ::= instead. Parenthesize as (...) if you intended a capture of a single variable.

so I try advice1:

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

which gives error

Not an array ref in call to write_row() at -e line 0.

advice2:

$worksheet.write_row(0,0, ::=@line);

Not an array ref in call to write_row() at -e line 0.

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

which gives the same errors.

How can I write an array to a row using Excel::Writer::XLSX in Perl6?

解决方案

The solution is to write $@array instead of \@array:

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

The rest of this answer is a brief guide on writing code using installed foreign language adaptors and dealing with any problems that arise. I intend it to be a general resource, an answer that goes well beyond this specific question.

It starts with the obvious question "Why $@foo?", discusses how to successfully use foreign language adaptors, and closes by explaining why the warning message was unhelpful.

Why $@foo?

Writing $@foo to pass @foo as an array reference to P5 is a simple and natural use of an existing P6 feature.

That said, users don't need to understand this $ feature of P6, nor do they need to know how Inline::Perl5 uses it, to get done what they want done (to write P6 code that passes an array reference to a function from a P5 module).

So the main answer to "why $@foo?" is that you write it that way and it works. \o/

How is one supposed to know magical incantations?

I got the solution for passing an array reference from Inline::Perl5's README:

HASH and ARRAY references are made automatically if the Perl 6 objects are containerized:

$p5obj.takes-an-array:      [<a b c>];
$p5obj.takes-an-array-ref: $[<a b c>];

(The word "containerized" refers to a P6 concept that lizmat explains well for those who know P5 in her Containers in P6 article. But containership is not actually technically relevant to why $@foo means an array ref in P5 when using Inline::Perl5. Yes, it works. No, it didn't have to be that way.)

Why does $@foo in P6 mean an array ref in P5?

The reason that writing $@foo is the correct thing to do isn't because the P6 language or compiler says it is.

It is an appropriate P6 feature, but the reason it's the correct thing to do is that niner (the author of Inline::Perl5) says so.

Why did niner choose $@foo?

Presumably because it:

  • Is easy to write for newbies;

  • Will make sense for this purpose as someone gets to know P6;

  • Is easy for niner to document;

  • Is easy to convert from its P6 meaning (an Array in a Scalar) to the target P5 meaning (a P5 array reference) in a performant manner.

What to expect when using foreign language adaptors

Inline::Perl5 is one of several foreign language adaptors. These adaptors allow P6 code to embed code written in those foreign languages and/or to use modules written in those foreign languages.

When the Rakudo P6 compiler sees the :from<Perl5> in a use statement, it implicitly invokes a previously installed P6 module called Inline::Perl5.

Inline::Perl5 installs marshaling code that automatically maps P6 code to and from P5 code so P6 and P5 can work together with minimal fuss.

Ideally adaptors would just do their job and you would never have to think about them. But:

  • While the obvious thing to map 42 in P6 to in any and all foreign languages is their value representing the integer 42, the mapping isn't always so straight-forward for higher level data structures, functions, references, etc. Sometimes it's amazing what can be done writing P6 code (you can create a P6 class that's a sub-class of a P5 class writing it exactly as you would if it were regular P6 code!) but sometimes you have to follow a rule (as in this case of how to pass a P6 array to P5 as an array reference). See the Adaptor documentation section below.

  • The P6 language and compiler aren't aware that mapping is going on. So any error or warning messages they display can be unhelpful, even misleading. Also, adaptor bugs are separate from bugs in P6, in its compilers, and in the foreign language modules being used. See the Warnings and errors section below.

Making the automatic mapping that foreign language adaptors make happen is far from automatic. Talented devs have to write adaptor code that does all the marshaling of data, exceptions, etc.

Given enough elapsed time (years) an adaptor may be able to close in on the ideal in which you never have to think about the adaptor's existence if you just want to use that language's modules or code in P6. You just use it and it always works just like it does in the foreign language.

One way to close in on that ideal more quickly for you, dear reader, and for all of us, is to use foreign modules via the existing adaptors and write SO questions and file issues when particular features don't seem to work. Thank you @con, niner, and everyone else who makes this happen.

Adaptor documentation

The only way to know for sure what P6 code you're supposed to write to make use of a foreign language module that you've used via :from<...> is to:

  • Read the foreign language module's documentation to see what it expects; and then

  • Read the adaptor's documentation to see how to write the corresponding P6 code that gives the foreign language and the foreign language module what they expect.

In this instance, in which we're talking about use of :from<Perl5>, the adaptor is Inline::Perl5. Its documentation is currently its github project repo README. So to see what you're supposed to write to give P5 and the P5 module what they expect, read that document.

Each adaptor will have its own documentation; see its listing on modules.perl6.org for a link.

Warnings and errors

If anything goes wrong when using a foreign language module in P6 (that doesn't go wrong when using the same code directly in that foreign language) then:

  • Make sure you've read the relevant adaptor's doc;

  • If you get a warning or error message, make sure to refer to the adaptor's documentation and its issues queue to see if it sheds light on that particular message;

  • If you think there's a bug in how things are (or aren't) working in P6 when using a foreign language module that works fine when used directly in that foreign language, refer to the adaptor's issue queue. For example, if you're using :from<Perl5> then refer to Inline::Perl5's issue queue. If you decide to post something, either post here if you're not sure it's a bug or in the adaptor's issue queue if you are.

Because the P6 language and compiler aren't aware that mapping is going on, warning and error messages can be misleading in the context of learning to use any aspects of a foreign language adaptor that involve following rules such as the $@foo rule of this SO.

In the case of P5 issues this can be exacerbated by P6 trying to be helpful to P5 coders writing P6 code, and that attempt backfiring when using Inline::Perl5. The example in the question is a good example:

To pass an array, hash or sub to a function in Perl 6, just pass it as is.

P6 thinks you might be used to writing array references using a prefix \. It's thinking you might be unaware that you don't need to write the slash in P6. It doesn't realize you're trying to insist on getting an array reference that P5 will understand via Inline::Perl5.

For other uses of Perl 5's ref operator consider binding with ::= instead.

P6 thinks you're trying to do what in P5 is typically done with \, not because you want to work with P5 but because you know P5, want to get something done in P6 without involving P5, and are hoping the exact same syntax works.

(Btw, the ::= advice definitely couldn't help -- because ::= is not yet implemented!)

Parenthesize as (...) if you intended a capture of a single variable.

P6 isn't thinking you're trying to make a P5 function work with an array reference. It thinks you're trying to create a P6 Capture.

Its advice is supposed to be interpreted as suggesting you write \(@foo) instead of \@foo to create a Capture containing @foo.

It has warned about use of \@foo to mean a Capture precisely because P5 devs might write it thinking it would create an array reference.

In summary, P6 doesn't know that Inline::Perl5 exists, or that it is going to do anything with your code. Instead, its advice is an attempt to translate P5 syntax and concepts that it thinks you're using, to corresponding syntax and concepts in P6. It's not an attempt to advise how to write P6 code suitable for mapping to P5 via Inline::Perl5.

That all said, I imagine it's possible that adaptor devs and core P6 devs will one day modify P5 related warning and error messages in the light of usability concerns such as have been raised by this SO.

这篇关于Perl6:获取 Perl5 模块的数组引用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆