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

I thought that %of would be more readable and concise than percent-of for the function name. Here is the working code using a longer name.

 #!/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]; } 

Since I put the name of the subroutine before its arguments, I would think that it would be a prefix operator. So here is what I would think in order to work with a shorter name (i.e. Using sub prefix:<%of> to declare a function):

 #!/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]; } 

But I get the following error:

 | 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'm sure something like what I'm trying is possible. I saw much more crazy functions than this, for example infix. I do not need the operator Β―\(Β°_o)/Β― . What am I doing wrong? I get the same error when trying to call %of with and without parentheses, so this is not a problem.

As I typed this question, I just realized that I should try to follow the example and do it as an infix operator, and it worked. However, I'm still curious why my prefix code code is not working. This is probably something very basic that I am missing.


UPDATE:

Here is the working code made as an infix operator. But I'm still wondering what I'm doing wrong with the prefix version:

 #!/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]; } 
+5
source share
2 answers

I thought that% of would be more readable and concise than percentages for the function name.

Strongly disagree, given that it looks exactly like a hash sigil. If I worked with you, I would go crazy if I came across this. What happened to percent-of as an infix? 5 percent-of 100 returns 0.05 or something?

I read% on behalf of the hash. Never in a million years, when I read Perl, I think that% as a new operator, meaning "percent", is the prefix. Therefore, it is not readable taking into account the language. This short one is not really a big excuse, it has a much greater cognitive load, so it becomes less readable. I'm not quite sure what is the balance of this criticism? Besides being scary and cool, you can do it at all ...

+5
source

Call op prefix with two arguments

The opening bracket is only interpreted as a function call when it follows the function name, and not when the name of the prefix operator is called.

So, in the second code snippet, this expression does not call the %of operator with two arguments:

 %of($ok, $total) 

Instead, it creates a List value with two elements and then applies the %of operator to this single List value - hence the error message " expected 2 arguments but got 1" .

To pass multiple arguments to the prefix operator, you must call its full name:

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

Of course, this denies your goal of "read and concise."

Using one argument

If you really want to use the prefix operator for this, you can force it to accept a single List parameter and unpack it into two values ​​directly in the signature using the [ ] sub-signal:

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

Tip

Note that declaring a statement that looks like a hash variable is likely to confuse the next person who should support your code (maybe even you when you get back to it in a few weeks).

Built-in prefix operators like ++ or ~ limited to one or two non-letter characters for a good reason. Perl 6 does not set the same restrictions for user statements, but remember that with great power comes great responsibility ... :)

+6
source

All Articles