Perl 6中是否有字节数组的等效类型?

10

让我们以Java的byte[] data为例。在Perl的方法签名中,我可以使用method myMethod($data),但这是一种有用的动态类型形式。

然而,我希望操作字节数组 - 那么是否有一种首选的方式将数据类型转换为字节数组或类似的东西?

我已经看过了一些资料,并看到了这里的代码,可以将源数据转换为字节数组:

my $arr =  Buf.new('mystring'.encode('utf-8')); 
say $arr;
这只是我将用于操作 Buf 的方法(们)中的首选输入,通过 $data 方法变量进行操作?

我很难理解你的问题。你是指像这样的东西吗:sub foo ($data) { $data[1] = 0x99 }; my $bar = Buf.new: 'mystring'.encode: 'utf-8'; say $bar; #\[Buf:0x<6d 79 73 74 72 69 6e 67>]; foo $bar; say $bar; #`[Buf:0x<6d 99 73 74 72 69 6e 67>]`? - raiph
@raiph 我也这么认为,我打算执行像 $data[offset + x] & 0xff 这样的操作。 - madcrazydrumma
1
好的,我想你指的是+&,所以 $data[offset + x] +& 0xff,没错,这样就可以了。如果你想要加强类型检查,可以在签名中添加 Buf 类型:sub foo (Buf $data) ...。也许你可以尝试一下这些方法,然后自己回答你的问题(这在 SO 上是合法的)。我要去睡觉了。 :) - raiph
2个回答

6

不确定问题是什么,但这是否是你要找的内容?

my int8 @a = ^10;         # a native array of 8-bit signed bytes
sub frobnicate(int8 @b) { # a sub taking a native 8-bit array
    dd @b;
}
frobnicate @a;
# array[int8].new(0, 1, 2, 3, 4, 5, 6, 7, 8, 9)

6
也许这很有帮助:
my \buffer = Buf.new: 'mystring'.encode: 'utf-8';
my \offset = 3;
my \mask   = 0x03;

sub mask-buffer-from-to (\mask,
                         \buffer,
                         \from = 0,
                         \to = buffer.end) {
  buffer[from..to]».&{ $_ +&= mask }
}
mask-buffer-from-to mask, buffer, offset;
say buffer; # Buf:0x<6d 79 73 00 02 01 02 03>

我删去了符号(在变量声明中使用\而不是$等)。 希望这样可以减少混乱(删去符号意味着它们在声明后被省略),我的目的是使其更易读。 如果这对您有用或实际上使阅读更加困难,请告诉我。

子例程签名中的= 0= buffer.end位是默认值。

如果您对P6比较熟悉,那么».&{ $_ +&= mask }表达式的含义显然。但由于您并不熟悉,所以我会解释一下。

用英语阅读,它的意思是,给定左侧缓冲区元素的范围,在每个元素上迭代(如果编译器愿意并行执行),将每个元素与mask进行逐位逻辑与运算。

计算机术语的阅读方式如下:

»

这是SPMD的P6精简版,用于超级运算符

»迭代其左侧操作数(左操作数对应SPMD的MD位),并在每次迭代时对其右侧操作数(对应SPMD的SP位)应用操作。

仅当SP和MD操作数是SPMD安全的时才使用»,即单个操作不会相互干扰。(如果您不确定,请使用像for循环或map之类的内容。)在这种情况下,您可以明显看出该操作(使用掩码进行逐位与操作)是SPMD安全的。

为了记住这种使用 » 的方式,只需记住它是一个SPMD操作或者注意到它显示了两个并行的 > (提醒您它假定并行语义,即编译器可以并行化它),左侧大于右侧(提醒您左操作数是复数,即它可以并且通常有多个元素,而右操作数始终只是单个操作)。
.

这是方法调用运算符。它在左侧的调用者的基础上,在右侧给定的方法上进行调用。
&

在一个 . 后面紧跟着一个 &,会强制右侧表达式被解释为一个例程。
{ ... }

.&之后的大括号代码被解释为闭包(例程)。在闭包内,$_(可以读作“这个”)被赋予左侧».&操作数迭代产生的每个元素的别名。
$_ +&= mask

这行代码的形式为LHS op= RHS。这种形式是LHS = LHS op RHS的简写。因此,闭包中的代码简写为:

$_ = $_ +& mask

即“这个通过位运算与掩码相与后变成了这个”。对于觉得这个答案有些困惑的读者,我感到抱歉;请在下方留言,我会做出相应的反应,或许会写一个完全不同、更简单、新的答案。我希望@madcrazydrumma觉得这个答案有趣且有帮助。

1
为什么对于学习该语言的人来说要使用斜杠样式?对于类似常量/枚举的东西,我可以理解为什么你可能想要使用它。但是在这个例子中,混乱既相同,逻辑上也更加晦涩和误导。如果我遇到一些完全像这样的Perl 6,我会非常不满意地维护它。Sigils是语言中不可避免的一部分,如果有人不喜欢它们,他们需要找到另一种语言来使用。没有任何原因就避免它们是很奇怪的。 - Matt Oates
你怎么看,@madcrazydrumma?1 我不同意关于混乱的观点。符号可以带来清晰度。但是当它们没有起到作用时,删减它们会减少视觉和认知上的混乱。2 我发现 buffer[from..to]».&{ $_ +&= mask }$buffer[$from..$to]».&{ $_ +&= $mask } 更易读,我认为 OP 也会这样认为。3 我认为 Java 风格的标识符对 OP 更友好。4 如果符号是噪音,我发现在代码中推理时如果符号是显著的,它会更加简单明了。5 我认为后者,而不是符号本身,是 P6 的优势。 - raiph
@MattOates,我正在等待你对我的回复和madcrazy的反馈做出回应,然后再决定如何编辑我的答案以尝试融入你的观点。我认为向那些学习P6的人暴露符号切割很重要,但是接受它在这个答案中的特定用法可能是不合适的。对我来说,重要的是你理解我的5个要点,或者至少在读者可以查看的评论中记录下努力去理解它们的过程。否则,我倾向于保留我的答案。当然,你可能不在意我是否进行了编辑,但我仍然希望得到开放的反馈。 - raiph
我刚刚写了一个回复 https://gist.github.com/MattOates/3bb818947552ed3917eb3739fdd02c12 ,它比原文多了889个字符。但是可以说,我对你的观点几乎都持有不同意见。但这是你的答案,我不会改变它。我的评论作为另一种观点的附言,我的意图并不是要逼迫你修改你的答案。多元化的声音肯定更好。 - Matt Oates
谢谢,这很有帮助。我不感到压力。我心态开放。我喜欢接受不同的观点,并将其融入我们未来的工作中。我会阅读你写的内容,在主题页面上回复并好好考虑一下。@madcrazydrumma,如果你看到了这条信息,你有什么想法? - raiph

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接