使用百分号作为前缀运算符名称的一部分

Using percent sign as part of the name for a prefix operator

我认为 %of 对于函数名来说比 percent-of 更具可读性和简洁性。这是使用较长名称的工作代码。

#!/bin/env perl6

# Quick stats from gene_exp.diff file

sub percent-of
{
    return sprintf('%.1f', (100 * $^a/ $^b).round(0.1));
}

my $total = first-word-from("wc -l       gene_exp.diff ") -1;  # subtract one for the header
my $ok    = first-word-from "grep -c OK  gene_exp.diff";
my $yes   = first-word-from "grep -c yes gene_exp.diff";

put '| total |    OK | OK % |   yes | yes % | yes / OK |';
put "| $total | $ok | { percent-of $ok, $total } | $yes | { percent-of $yes,$total } | { percent-of $yes, $ok } |";



sub first-word-from ( $command )
{
    return ( qqx{ $command } ).words[0];
}

因为我将子例程名称放在它的参数之前,所以我认为这将是一个前缀运算符。所以这是我认为可以使更短的名称起作用的方法(即使用 sub prefix:<%of> 来声明函数):

#!/bin/env perl6

# Quick stats from gene_exp.diff file

sub prefix:<%of>
{
    return sprintf('%.1f', (100 * $^a/ $^b).round(0.1));
}

my $total = first-word-from("wc -l       gene_exp.diff ") -1;  # subtract one for the header
my $ok    = first-word-from "grep -c OK  gene_exp.diff";
my $yes   = first-word-from "grep -c yes gene_exp.diff";

put '| total |    OK | OK % |   yes | yes % | yes / OK |';
put "| $total | $ok | { %of($ok, $total) } | $yes | { %of($yes,$total) } | { %of($yes,$ok) } |";

sub first-word-from ( $command )
{
    return ( qqx{ $command } ).words[0];
}

但是我得到以下错误:

| total |    OK | OK % |   yes | yes % | yes / OK |
Too few positionals passed; expected 2 arguments but got 1
  in sub prefix:<%of> at /home/bottomsc/bin/gene_exp_stats line 6
  in block <unit> at /home/bottomsc/bin/gene_exp_stats line 15

我确信像我正在尝试的那样的事情是可能的。我见过比这更疯狂的函数,比如中缀 I don't care operator ¯\(°_o)/¯。我究竟做错了什么?在尝试调用带括号和不带括号的 %of 时,我得到了完全相同的错误,所以这不是问题所在。

当我输入这个问题时,我刚刚意识到我应该尝试遵循 example just cited 并将其作为中缀运算符进行操作并且它起作用了。但是,我仍然很好奇为什么我的前缀运算符代码不起作用。这可能是我忽略的非常基本的东西。


更新:

这是作为中缀运算符完成时的工作代码。但是我还是很好奇我做错了什么前缀版本:

#!/bin/env perl6

# Quick stats from gene_exp.diff file

sub infix:<%of>
{
    return sprintf('%.1f', (100 * $^a/ $^b).round(0.1));
}

my $total = first-word-from("wc -l       gene_exp.diff ") -1;  # subtract one for the header
my $ok    = first-word-from "grep -c OK  gene_exp.diff";
my $yes   = first-word-from "grep -c yes gene_exp.diff";

put '| total |    OK | OK % |   yes | yes % | yes / OK |';
put "| $total | $ok | { $ok %of $total } | $yes | { $yes %of $total } | { $yes %of $ok } |";

sub first-word-from ( $command )
{
    return ( qqx{ $command } ).words[0];
}

使用两个参数调用前缀运算符

仅当左括号跟在函数名称之后时才将其解释为函数调用,而不是当它跟在前缀运算符名称之后时。

所以在你的第二个代码片段中,这个表达式 not 调用带有两个参数的 %of 运算符:

%of($ok, $total)

相反,它创建了一个包含两个元素的 List 值,然后将 %of 运算符应用于该单个 List 值 - 因此出现错误消息“expected 2 arguments but got 1" .

为了将多个参数传递给前缀运算符,您必须调用其完全限定名称:

prefix:<%of>($ok, $total);

当然,这会否定您 "readable and concise" 的目标。

使用单个参数

如果你真的想为此使用前缀运算符,你可以让它接受一个 List 参数,并在签名中将其解压缩为两个值,方法是使用 [ ]子签名:

sub prefix:<%of> ([$a, $b]) {
    sprintf '%.1f', (100 * $a / $b).round(0.1);
}

say %of(42, 50);  # 84.0

建议

请注意,声明一个看起来像散列变量的运算符可能会使下一个必须维护您的代码的人感到困惑(甚至可能是您自己,当您在几周后回来时)。

++~ 等内置前缀运算符有充分的理由将自己限制为一个或两个非字母符号。 Perl 6 没有对用户定义的运算符施加相同的限制,但请记住,能力越大,责任越大...:)

I thought that %of would be more readable and concise than percent-of for a function name.

强烈反对,因为这看起来就像一个哈希印记。如果我和你一起工作,如果我遇到这个,我会发疯的。 percent-of 作为中缀有什么问题? 5 percent-of 100 返回 0.05 或什么?

我将 %of 读作 hash called of。在阅读 Perl 的一百万年里,我都不会认为 % 是一个新定义的运算符,意思是 'percent' 这样的前缀。因此,鉴于该语言,它不可读。简洁也不是一个很好的理由,它具有更大的认知负担,因此可读性也较差。我不完全确定这种批评的平衡是什么?除了它的可怕和酷你完全可以做到...