【问题标题】:Using percent sign as part of the name for a prefix operator使用百分号作为前缀运算符名称的一部分
【发布时间】:2017-01-19 23:39:34
【问题描述】:

我认为对于函数名称,%ofpercent-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];
}

【问题讨论】:

    标签: function operators raku


    【解决方案1】:

    使用两个参数调用前缀操作

    左括号只有在函数名之后才被解释为函数调用,而不是在前缀运算符名之后。

    因此,在您的第二个代码 sn-p 中,此表达式确实使用两个参数调用 %of 运算符:

    %of($ok, $total)
    

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

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

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

    当然,这否定了您“可读性和简洁”的目标。

    使用单个参数

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

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

    建议

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

    ++~ 这样的内置前缀运算符有充分的理由将自己限制为一两个非字母符号。 Perl 6 对用户定义的运算符没有同样的限制,但请记住,强大的力量伴随着巨大的责任...... :)

    【讨论】:

    • 非常感谢您告诉我该怎么做......并且告诉我不要这样做。
    【解决方案2】:

    我认为对于函数名称,%of 比 percent-of 更具可读性和简洁性。

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

    我将 %of 读取为称为 of 的哈希值。在阅读 Perl 的一百万年中,我永远不会认为 % 是一个新定义的运算符,意思是像这样前缀的“百分比”。因此,鉴于语言,它不可读。简洁也不是一个很好的理由,它具有更大的认知负荷,因此可读性再次降低。我不完全确定这种批评的平衡是什么?除了可怕和酷之外,你完全可以做到......

    【讨论】:

    • 正是我需要听到的。我100%同意你。我为没有更多地考虑可维护性而感到羞愧。我认为这正是 Larry Wall 所说的使用 Perl 6 我们得到了“足够的绳索来击中我们自己的脚”时的意思。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-12-16
    • 2010-12-02
    • 2011-12-13
    • 1970-01-01
    相关资源
    最近更新 更多