Perl6学习笔记Word文档下载推荐.docx
《Perl6学习笔记Word文档下载推荐.docx》由会员分享,可在线阅读,更多相关《Perl6学习笔记Word文档下载推荐.docx(75页珍藏版)》请在冰点文库上搜索。
15%sets{$p2}+=$r2;
#选手2赢得的比赛局数
16
17if$r1>
$r2{#如果每场比赛中,选手1赢的局数多于选手2,则选手1赢得的比赛数+1,反之选手2的+1
18%matches{$p1}++;
19}else{
20%matches{$p2}++;
21}
22}
23
24my@sorted=@names.sort({%sets{$_}}).sort({%matches{$_}}).reverse;
25
26for@sorted->
$n{
27say"
$nhaswon%matches{$n}matchesand%sets{$n}sets"
28}
输出如下:
Anahaswon2matchesand8sets
Davehaswon2matchesand6sets
Charliehaswon1matchesand4sets
Bethhaswon1matchesand4sets
每个Perl6程序应该以usev6;
作为开始,它告诉编译器程序期望的是哪个版本的Perl。
在Perl6中,一个变量名以一个魔符打头,这个魔符是一个非字母数字符号,诸如$,@,%或者&
还有更少见的双冒号:
内置函数open打开了一个名叫scores的文件,并返回一个文件句柄,即一个代表该文件的对象。
赋值符号=将句柄赋值给左边的变量,这意味着$file现在存储着该文件句柄。
my@names=$file.get.words;
上边这句的右侧对存储在$file中的文件句柄调用了get方法,get方法从文件中读取并返回一行,并去掉行的末尾。
.words
也是一个方法,用于从get方法返回的字符串上。
.words方法将它的组件--它操作的字符串,分解成一组单词,这里即意味着不含空格的字符串。
它把单个字符串'
BethAnaCharlieDave'
转换成一组字符串'
Beth'
'
Ana'
Charlie'
Dave'
.最后,这组字符串存储在数组@names中。
1my%matches;
2my%sets;
在比分计数程序中,%matches存储每位选手赢得的比赛数。
%sets存储每位选手赢得的比赛局数。
1for$file.lines->
2...
3}
for循环中$file.lines产生一组从文件scores读取的行,从上次$file.lines离开的地方开始,一直到文件末尾结束。
在第一次循环中,$line会包含字符串AnaDave|3:
0;
在第二次循环中,$line会包含CharlieBeth|3:
1,以此类推。
1my($pairing,$result)=$line.split('
split此处是一个方法,字符串'
|'
是它的参数。
第一次循环结束:
Variable
Contents
$line
'
AnaDave|3:
0'
$pairing
AnaDave'
$result
3:
$p1
$p2
$r1
3'
$r2
1my@sorted=@names.sort({%sets{$_}}).sort({%matches{$_}}).reverse;
这一句是排序,先按比赛局数多少排序,再按赢得的比赛数排序,然后反转。
打印选手名字的时候以胜负次序排序,代码必须使用选手的分数,而非他们的名字来进行排序。
sort方法的参数是一个代码块,用于将数组元素(选手的名字)转换成用于排序的数据。
数组的元素通过变量$_传递到代码块中。
最简单的使用分数排序选手的方法应该是@names.sort({%matches{$_}}),这是通过使用赢得比赛的次数来进行排序。
然而,Ana和Dave都赢了两场比赛。
还需要比较谁赢的的比赛局数多,才能决定比赛的排名。
在双引号括起的字符串中,标量和花括号中的变量能进行变量插值。
1my$names='
things'
2say'
Donotcallme$names'
#Donotcallme$names
3say"
Donotcallme$names"
#Donotcallmethings
花括号中的数组进行插值后会变成用空格分隔的条目。
花括号中的散列插值后每个散列键值对单独成为一行,每行包含一个健,随后是一个tab符号,然后是键值,最后是一个新行符。
TODO:
explain<
...>
quote-words
1say"
Math:
{1+2}"
#Math:
3
2my@people=<
LukeMatthewMark>
Thesynopticsare:
{@people}"
#Thesynopticsare:
LukeMatthewMark
4
5say"
{%sets}"
#Fromthetabletennistournament
6
7#Charlie4
8#Dave6
9#Ana8
10#Beth4
Whenarrayandhashvariablesappeardirectlyinadouble-quotedstring(andnotinside
curlybrackets),theyareonlyinterpolatediftheirnameisfollowedbyapostcircumfix–
abracketingpairthatfollowsastatement.It’salsooktohaveamethodcallbetweenthe
variablenameandthepostcircumfix.
1my@flavours=<
vanillapeach>
wehave@flavours"
#wehave@flavours
4say"
wehave@flavours[0]"
#wehavevanilla
5#so-called"
Zenslice"
6say"
wehave@flavours[]"
#wehavevanillapeach
7
8#methodcallsendinginpostcircumfix
9say"
wehave@flavours.sort()"
#wehavepeachvanilla
10
11#chainedmethodcalls:
12say"
wehave@flavours.sort.join('
)"
13#wehavepeach,vanilla
练习:
例子中的第一行选手的名字是多余的,你可以在参加比赛的选手中找出所有选手的名字!
如果例子中的第一行被省略了,你如何更改程序?
提示:
%hash.keys返回散列%hash中的所有键。
答案:
移除此行:
my@names=$file.get.words;
并且将
my@sorted=@names.sort({%sets{$_}}).sort({%matches{$_}}).reverse;
变成:
my@sorted=%sets.keys.sort({%sets{$_}}).sort({%matches{$_}}).reverse;
2.除了移除冗余,你也可以用它来提醒我们,如果一个选手没有在第一行的名字清单中被提到,例如因为输入错误,你该怎样修改你的程序?
引入另外一个散列,合法选手的名字作为键,当读取选手名字的时候查找该散列:
1
2my@names=$file.get.split('
3my%legitimate-players;
4for@names->
5%legitimate-players{$n}=1;
6}
8...
9
10for$file.lines->
11my($pairing,$result)=$line.split('
12my($p1,$p2)=$pairing.split('
13for$p1,$p2->
$p{
14if!
%legitimate-players{$p}{
15say"
Warning:
$p'
isnotonourlist!
"
16}
17}
18
19...
20}
第三章操作符
usev6;
my@scores='
=>
8,'
6,'
4,'
4;
my$screen-width=30;
my$label-area-width=1+[max]@scores»
.key»
.chars;
my$max-score=[max]@scores»
.value;
my$unit=($screen-width-$label-area-width)/$max-score;
my$format='
%-'
~$label-area-width~"
s%s\n"
for@scores{
printf$format,.key,'
X'
x($unit*.value);
}
在这个例子中,我们计算一下每位选手在竞标赛中赢得比赛的局数。
这一句局包含了三个不同的操作符=和=>
和,
以字符串连接操作符~为例,$string~="
text"
等价于$string=$string~"
.
=>
操作符(大键号)创建了一个键值对对象,一个键值对存储着键和值;
键在=>
操作符的左侧,值在右侧。
这个操作符有一个特殊的特性:
编译器会把=>
操作符左侧的任何裸标识符解释为一个字符串。
你也可以这样写:
my@scores=Ana=>
8,Dave=>
6,Charlie=>
4,Beth=>
最后逗号操作符,构建了一个对象序列,在该情况下,所谓的对象就是键值对。
这三个操作符都是中缀操作符,这意味着它在两个条目之间。
一个项前面可以有0个或多个前缀操作符,所以你可以写比如4+-5。
+号(一个中缀操作符)的后面,编译器期望一个项,为了将-号解释为项5的一个前缀。
»
是一个特殊的符号,打印不出来可以用两个大于号>
>
代替。
中缀操作符max返回两个值中的较大者,所以2max3返回3。
方括号包裹着一个中缀操作符让Perl将该中缀操作符应用到列表中的元素之间。
[max]1,5,3,7和1max5max3max7一样,结果都为7.
同样地,[+]用来计算列表元素的和,[*]用来计算列表元素的积,[<
=]用来检查一个列表的值是否按递增排序。
@scores»
.chars
my@scores=Ana=>
Ana
8Dave
6Charlie
4Beth
4
@scores.key
Method'
key'
notfoundforinvocantofclass'
Array'
@scores>
.key
AnaDaveCharlieBeth
就像@variable.method在@variable上调用一个方法一样,@array»
.method对@array中的每一项调用method方法,并且返回一个返回值的列表。
即@scores>
.key返回一个列表。
.key>
.chars
#每个名字含有几个字符
3474
表达式[max]@scores»
.chars给出(3,4,7,4)中的最大值。
它与下面的表达式相同:
1@scores[0].key.chars
2max@scores[1].key.chars
3max@scores[2].key.chars
4max...
@scores[0]
Ana"
8
@scores[0].key
Ana
1my$format='
2for@scores{
3printf$format,.key,'
4}
定义一个格式,%-表示左对齐,~是字符串连接操作符.for循环中,@scores中的每一项被绑定给特殊变量$_,.key是每项的键,即名字,.value是每项的键值,即得分。
小x是字符串重复操作符。
3.1关于优先级的的一句话
等号右侧产生一个列表(因为逗号,操作符),这个列表由对儿组成(因为=>
),并且结果赋值给数组变量。
在Perl5中会这样解释:
1(my@scores='
)=>
以至于数组@scores中只有一个项,表达式的其余部分被计算后丢弃。
优先级规则控制着编译器如何解释这一行。
Perl6的优先级规则申明中缀操作符=>
比,中缀操作符对于参数的绑定更紧,而逗号操作符比等号赋值操作符绑定的更紧。
实际上有两种不同优先级的赋值操作符。
当赋值操作符右侧是一个标量时,使用较紧优先级的项赋值操作符,否则使用较松优先级的列表赋值操作符。
(如同螺丝的松紧)
比较
$a=1,$b=2和@a=1,2,前者是在一个列表中赋值给两个变量,后者是将含有两个项的一个列表赋值给一个变量。
1say5-7/2;
#5-3.5=1.5
2say(5-7)/2;
#(-2)/2=-1
Perl6中的优先级可以用圆括号改变,但是如果圆括号直接跟在标识符的后面而不加空格的话,则会被解释为参数列表。
例如:
say(5-7)/2;
#-2
只打印出了5-7的值。
优先级表
3.2比较和智能匹配
1my@a=1,2,3;
2my@b=1,2,3;
4say@a===@a;
#Bool:
True
5say@a===@b;
False
7#theseuseidentityforvalue
9say3===3#Bool:
10say'
a'
==='
11
12my$a='
13say$a==='
@b===@a
@aeqv@b
2'
eqv2
只有当两个对象有相同的类型和相同的结构时,eqv操作符才返回True。
在前面定义的例子中,@a
eqv
@b结果为True,因为@a和@b各自包含相同的值,另一方面,'
eqv2返回'
False'
因为一个参数是字符串,另一个是整数,类型不相同。
3.2.1数字比较
使用==中缀操作符查看两个对象是否有相同的数字值。
如果某个对象不是数字,Perl会在比较之前尽力使其数字化。
如果没有更好的方式将对象转换为数字,Perl会使用默认的数字0。
1say1==1.0;
2say1=='
1'
3say1=='
4say3=='
3b'
#fails
跟数字比较相关的还有<
<
=,>
>
=。
如果两个对象的数字值不同,使用!
=会返回True。
如果你将数组或列表作为数字,它会计算列表中项的个数。
1my@colors=<
redbluegreen>
3if@colors==3{
It'
strue,@colorscontains3items"
5}
3.2.2
字符串比较
Perl6中使用eq比较字符串,必要时会将其参数转换为字符串。
1if$greetingeq'
hello'
{
welcome'
Table3.2:
OperatorsandComparisons
数字比较
字符串比较
意思
==
eq
等于
!
=
ne
不等于
<
lt
小于
le
小于或等于
gt
大于
ge
大于或等于
例如,'
lt'
b'
为true,'
aa'
也为true。
!
=是!
==的便捷形式,它实际是!
元操作符加在中缀操作符==之前。
同样地,ne和!
eq是一样的。
三路操作符
三路操作符有两个操作数,如果左侧较小,返回Order:
Increase,两侧相等则返回Order:
Same,如果右侧较小则返回Order:
Decrease。
对于数字使用三路操作符<
对于字符串,使用三路操作符leg(取自lesser,equal,greater)。
中缀操作符cmp是一个对类型敏感的三路操作符,它像<
一样比较数字,像leg一样比较字符串,(举例来说)并且比较键值对儿时,先比较键,如果键相同再比较键值:
1say10<
5;
#+1
2say10leg5;
#because'
5'
3say'
ab'
leg'
#+1,lexicographiccomparison
三路操作符的典型用处就是用在排序中。
列表中的.sort方法能使用一个含有两个值的块或一个函数,比较它们,并返回一个小于,等于或大于0的值。
sort
方法根据该返回值进行排序:
1say~<
abstractConcrete>
.sort;
2#output:
Concreteabstract
4say~<
.sort:
->
$a,$b{uc($a)leguc($b)};
5
#output:
abstractConcrete
默认的,比较是大小写敏感的,通过比较它们的大写变形,而不是比较它们的值,这个例子使用了大小写敏感排序。
3.2.3智能匹配
使用~~做正确的事情。
1if$pints-drunk~~8{
2say"
Gohome,you'
vehadenough!
5if$country~~'
Sweden'
Meatballswithlingonb