Perl 6 Weekly(一)

1、在 Perl 6 中怎样检查文件的时间戳属性?

在 Perl 6 中怎样检查文件的时间戳属性? 在 Perl 5 中是使用文件测试操作符 file test operators , 在 Perl 6 中是使用来自于 IO::FileTestable role 的方法 (e.g. .modified, .accessed and .changed) 。

例如:

my $filename = "sample.txt";
my $seconds_since_epoch = $filename.IO.accessed;
my $readable_timestamp  = DateTime.new($filename.IO.accessed);

say "File '$filename' was last accessed at '$readable_timestamp', which is {$seconds_since_epoch.Num} seconds since the epoch";

2、我正尝试生成包含 10 个随机随机序列的 FASTQ 文件, 序列由随机品质分数构成。我原来是使用下面的代码,它工作良好:

my @seq  = (rand_fa_seq() for ^10);
my @qual = (rand_qual()   for ^10);

@seq.perl.say;
@qual.perl.say;

sub rand_fa_seq
{
    return join("", roll(20,"ACGT".comb));

}

sub rand_qual
{
    return join("", roll(20,"EFGHIJ".comb))
}

等价于:

sub rand-fa-seq($n = 20) { <A C G T>.roll($n).join }
sub rand-qual($n = 20)   { <E F G H I J>.roll($n).join }

my @seq  = rand-fa-seq() xx 10;
my @qual = rand-qual() xx 10;

3、在 Perl 6 中使用 "列表解析” 生成非平方数列表

在 Perl 6 中我怎样使用 "列表解析" 创建一组非平方数? 我在 Rosetta Code 那儿看到了如何打印一组非平方数的代码:

sub nth_term (Int $n) { $n + round sqrt $n }

say nth_term $_ for 1 .. 22;

目前为止我看到的最接近的东西是使用 for 关键字。 但是因为这实际上仅仅是一个内联(inline)循环,我认为这从技术上来讲并不是列表解析,尽管它看起来相似:

my @y = ($_**2 + 1 for 1 .. 10);

但是,我真正想知道是否有一种 “列表解析 “ 的方法来创建可在数学上描述的诸如非平方数的列表。这儿有一个我用来创建一组非平方数的方法(直到 30):

my @non_squares = grep {sqrt($_) != floor(sqrt($_))}, 1 .. 30;

我怎样用列表解析来实现它呢?

实际上, 你的例子 my @y = ($_**2 + 1 for 1 .. 10); 是 Perl 6 方式写成的列表解析。你还可以添加一个条件测试, 就像 Perl 6 design document S04 中建议的那样:

为了轻松地书写列表解析, 循环语句修饰符允许包含单个条件语句修饰符:

sub odd(Int $n) {return $n % 2}
@evens = ($_ * 2 if .&odd for 0..100);

这个就是怎样写一个 Perl 6 列表解析的非平方数(直到 30):

my @non_squares = ($_ if .sqrt != .sqrt.Int for 1 .. 30);

一丢丢解释:在每次 for 循环迭代中, 从 1 到 30 这个范围中的当前数字会被赋值给默认变量 $_(等价于 it)。没有调用者的方法调用会默认在 “it" 身上调用(例如 .sqrt 等价于 $_.sqrt)。 所以,对于 1到30中的每一个数字,它的平方根被检查以查看它是否有非整数平方根。 如果是真, 那它就被包含在列表中。

4、Perl 6 中的 Print 函数和冒号

我想知道在 Perl 6 中冒号与方法和函数调用有什么关系。

我在 Perl6 spec test (S32-io) 中看到了这个(我添加了注释):

$fh.print: "0123456789A";   # prints '0123456789A' to the file

据我所知,这等价于:

$fh.print("0123456789A");   # prints '0123456789A' to the file

这两种方式看起来都接收多个参数而且展平列表也没问题:

$fh.print: "012", "345", "6789A";   # prints '0123456789A' to the file
$fh.print("012", "345", "6789A");   # prints '0123456789A' to the file

my @a = <012 345 6789A>;

$fh.print(@a);   # prints '0123456789A' to the file
$fh.print: @a;   # prints '0123456789A' to the file

存在这两种语法一定有某种原因。 使用这种或另一种语法有某种理由吗?

我还注意到,当作为方法使用时, 我们不得不使用带有 :()的 print:

$fh.print(@a);   # Works
$fh.print: @a;   # Works!
$fh.print @a;    # ERROR!

当使用带冒号的 print 函数时,还有一些有意思的行为。 在这种情况下, : 和 () 不等价:

print @a;  # Prints '0123456789A' (no newline, just like Perl 5)
print(@a); # Ditto
print: @a; # Prints '012 345 6789A' followed by a newline (at least in REPL)

print  @a, @a; # Error (Two terms in a row)
print: @a, @a; # Prints '012 345 6789A 012 345 6789A' followed by a newline (in REPL)

然后我尝试在脚本文件中使用print。这对于打印到标准输出有效:

print @a;

然而, 这不会打印到标准输出:

print: @a, @a;

但是方法版本的工作良好:

$fh.print: @a, @a; # Prints '0123456789A0123456789A' to the file

我感觉我已经理解了这个, 但是不能用语言表达出来。有人可以解释下使用 print 的这些变化吗。 还有, 这些行为会因为 Great List Refactor 而改变吗?


Answer:

使用冒号代替圆括号的一个主要原因是通过移除一组圆括号,它能使代码更清晰。在其它方面它们真的一样。

当你使用 print: @a , 那你真正在做的就是在行上放置一个标签, 并让 @a 落进去(fall-through)。这在 REPL 中会调用带有值的 say 方法。

如果你没有在方法调用中使用括号或冒号,, 那么方法会以无参数方式调用。


你可以交换方法的顺序,还有调用者,如果你使用冒号的话。

say $*ERR: 'hello world'; # $*ERR.say('hello world')
我刚刚确认了, 就像你说的, print: @a 就是 label: @a, label 可以是任何东西. – Christopher Bottoms Jun 26 at 14:12
换句话说,冒号能代替方法调用的圆括号,但不能代替子例程调用。 – Christopher Bottoms Jun 26 at 14:12

5、排序散列键值对儿

my %hash =
    two   => 2,
    three => 3,
    one   => 1,
;

for %hash.sort(*.key)».kv -> ($key, $value) {
    say "'$key' => '$value'";
}

%hash.sort({.key})».kv 和上面的 sort 等价吗?

为什么这个 sort 没有 hyper » 提示就不会工作?


这个 sort方法返回一个 Pairs 的列表。

因为在列表身上调用 .kv 会返回一个索引, Pair 列表, 这不是你想要的; 你不能单单在列表身上调用 .kv 。所以你必须通过在每个 Pair 身上调用 .kv 方法分别从列表中的 Pair 中取出键和值, 这正是 ».kv 所做的。

你还可以使用 .map(*.kv) 代替。

».kv 语法允许把工作展开到多个线程中执行, 如果那样做有意义的话。

(当前的 Rakudo仅以半随机的顺序工, 以防止人们错误地使用该特性 )


通过在签名中使用副词以提取属性, 这是另一种 loop 写法:

for %hash.sort -> (:$key, :$value) {
  say "'$key' => '$value'";
}

for %hash.sort -> $pair (:$key, :$value) {
  say $pair;
  say $key === $pair.key and $value === $pair.value; # True

}

# :$key is short for :key($key)
for %hash.sort -> (:key($k), :value($v)) {
  say "'$k' => '$v'";
}

这对其它没有方法创建一组它们公用属性的对象有用:

class C { has $.a; has $.b; has $.c; has $!private-value }
my $c = 5;
my $obj = C.new(:a<A>,:b(1),:$c);

given $obj -> ( :$a, :b($b), :$c) ) {
  say "$a $b $c";   # A 1 5
}

# ignore $.a by using an unnamed scalar
given $obj -> ( :a($), :$b, :$c ) { ... }

# places any unspecified public attributes in %others
given $obj -> ( :$a, :$b, *%others ) {
  .say for keys %others; # c

}

# 忽略任何未指定的属性
# useful to allow subclasses to add more attributes
# 或仅仅丢弃掉任何你不关心的值
given $obj -> ( :$a, :$b, *% ) { ... }

# 失败,因为它没有处理公用的 c 属性
# in the sub-signature
given $obj -> ( :$a, :$b ) { ... }

关于签名能做什么,那只是开始。

所有下面的,在子例程和方法签名中都是被允许的,非强制性的, 对于这个例子杀伤力过大。这在 multi subs 和 multi methods 中对于限制可能的候选者真的很有用。

for 'one' => 1, 1/3
->
  # Type is an alias to the object type
  ::Type Any $_ # Any is the default type requirement

  # the public attributes of the object
  (
    ::A-Type Any :key(   :numerator(   $a ) ),
    ::B-Type Any :value( :denominator( $b ) ) where $b >= 1,
  )
{
  my Type $obj = $_; # new variable declared as having the same type
  my A-Type $new-a = $a;
  my B-Type $new-b = $b;

  # could have used $_.^name or .^name instead of Type.^name
  # so you don't actually have to add the alias to the signature
  # to get the name of the arguments type
  say Type.^name, ' ', $_;
  say '  ', A-Type.^name, ' ', $a;
  say '  ', B-Type.^name, ' ', $b;
}

Pair one => 1
  Str one
  Int 1
Rat 0.333333
  Int 1
  Int 3

至于使用 .sort({.key}), 恩, 那从根本上来说是同一个东西, 因为 sort 在那儿接受任何 Callable

我要指出, 你甚至不需要为 sort 提供参数, 因为它默认比你给它的东西智能。

Perl 6 有很多创建和访问 Callable 东西的方式。所以任何下面一种都可以工作:

*.key
{ .key } # { $_.key }
-> $_ { .key } # basically what the previous line turns into
{ $^placeholder-var.key }
sub ($_) { .key }
&a-subroutine-reference # you would have to create the subroutine though

还有, 因为所有普通的操作符实际上都是子例程,你可以在需要 Callable 的其它地方使用它们:

&infix:<+> # the subroutines responsible for the numeric addition operator
&[+] # ditto

&prefix:<++>
&postfix:<++>

# etc
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,590评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 86,808评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,151评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,779评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,773评论 5 367
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,656评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,022评论 3 398
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,678评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 41,038评论 1 299
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,659评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,756评论 1 330
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,411评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,005评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,973评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,203评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,053评论 2 350
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,495评论 2 343

推荐阅读更多精彩内容