Perl6学习笔记.docx

上传人:b****1 文档编号:270555 上传时间:2023-04-28 格式:DOCX 页数:75 大小:448.37KB
下载 相关 举报
Perl6学习笔记.docx_第1页
第1页 / 共75页
Perl6学习笔记.docx_第2页
第2页 / 共75页
Perl6学习笔记.docx_第3页
第3页 / 共75页
Perl6学习笔记.docx_第4页
第4页 / 共75页
Perl6学习笔记.docx_第5页
第5页 / 共75页
Perl6学习笔记.docx_第6页
第6页 / 共75页
Perl6学习笔记.docx_第7页
第7页 / 共75页
Perl6学习笔记.docx_第8页
第8页 / 共75页
Perl6学习笔记.docx_第9页
第9页 / 共75页
Perl6学习笔记.docx_第10页
第10页 / 共75页
Perl6学习笔记.docx_第11页
第11页 / 共75页
Perl6学习笔记.docx_第12页
第12页 / 共75页
Perl6学习笔记.docx_第13页
第13页 / 共75页
Perl6学习笔记.docx_第14页
第14页 / 共75页
Perl6学习笔记.docx_第15页
第15页 / 共75页
Perl6学习笔记.docx_第16页
第16页 / 共75页
Perl6学习笔记.docx_第17页
第17页 / 共75页
Perl6学习笔记.docx_第18页
第18页 / 共75页
Perl6学习笔记.docx_第19页
第19页 / 共75页
Perl6学习笔记.docx_第20页
第20页 / 共75页
亲,该文档总共75页,到这儿已超出免费预览范围,如果喜欢就下载吧!
下载资源
资源描述

Perl6学习笔记.docx

《Perl6学习笔记.docx》由会员分享,可在线阅读,更多相关《Perl6学习笔记.docx(75页珍藏版)》请在冰点文库上搜索。

Perl6学习笔记.docx

Perl6学习笔记

 

 

 

                  

          

                                                                                   

 第二章基础

 

假设有一场乒乓球比赛,比赛结果以这种格式记录:

Player1Player2|3:

2

这意味着选手1与选手2的比分为3:

2, 你需要一个脚本算出每位选手赢了几场比赛并且胜了几局。

输入数据(存储在一个叫做scores的文件中)像下面这样:

 

1BethAnaCharlieDave

2AnaDave|3:

0

3CharlieBeth|3:

1

4AnaBeth|2:

3

5DaveCharlie|3:

0

6AnaCharlie|3:

1

7BethDave|0:

3

第一行是选手清单。

随后每一行记录着比赛结果。

 

这里使用Perl6给出一种解决方案:

1usev6;

2

3my$file=open'scores';

4my@names=$file.get.words; #get方法读入一行

5

6my%matches;#赢得比赛次数

7my%sets;#赢得比赛局数

8

9for$file.lines->$line{

10my($pairing,$result)=$line.split('|');#对剩下的每一行调用split操作

11my($p1,$p2)=$pairing.words;#提取选手1和选手2的名字

12my($r1,$r2)=$result.split(':

');#提取比赛比分

13

14%sets{$p1}+=$r1;#选手1赢得的比赛局数

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->$line{

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:

0'

$p1              'Ana'

$p2             'Dave'

$r1             '3'

$r2            '0'

 

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=;

3say"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=;

2

3say"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->$n{

5%legitimate-players{$n}=1;

6}

7

8...

9

10for$file.lines->$line{

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='Ana'=>8,'Dave'=>6,'Charlie'=>4,'Beth'=>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);

}

 

在这个例子中,我们计算一下每位选手在竞标赛中赢得比赛的局数。

my@scores='Ana'=>8,'Dave'=>6,'Charlie'=>4,'Beth'=>4; 这一句局包含了三个不同的操作符=和=>和,

以字符串连接操作符~为例,$string~="text"等价于$string=$string~"text".

 

=>操作符(大键号)创建了一个键值对对象,一个键值对存储着键和值;键在=>操作符的左侧,值在右侧。

这个操作符有一个特殊的特性:

编译器会把=>操作符左侧的任何裸标识符解释为一个字符串。

你也可以这样写:

 

my@scores=Ana=>8,Dave=>6,Charlie=>4,Beth=>4;

 

最后逗号操作符,构建了一个对象序列,在该情况下,所谓的对象就是键值对。

 

这三个操作符都是中缀操作符,这意味着它在两个条目之间。

 

一个项前面可以有0个或多个前缀操作符,所以你可以写比如4+-5。

+号(一个中缀操作符)的后面,编译器期望一个项,为了将-号解释为项5的一个前缀。

 

my$label-area-width=1+[max]@scores».key».chars;

 

»是一个特殊的符号,打印不出来可以用两个大于号>>代替。

中缀操作符max返回两个值中的较大者,所以2max3返回3。

方括号包裹着一个中缀操作符让Perl将该中缀操作符应用到列表中的元素之间。

[max]1,5,3,7和1max5max3max7一样,结果都为7.

 

同样地,[+]用来计算列表元素的和,[*]用来计算列表元素的积,[<=]用来检查一个列表的值是否按递增排序。

 

@scores».key».chars

 

>my@scores=Ana=>8,Dave=>6,Charlie=>4,Beth=>4;

Ana    8Dave 6Charlie      4Beth 4

>@scores.key

Method'key'notfoundforinvocantofclass'Array'

>@scores>>.key

AnaDaveCharlieBeth

就像@variable.method在@variable上调用一个方法一样,@array».method对@array中的每一项调用method方法,并且返回一个返回值的列表。

即@scores>>.key返回一个列表。

 

>@scores>>.key>>.chars #每个名字含有几个字符

3474

 

表达式[max]@scores».key».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='%-'~$label-area-width~"s%s\n";

2for@scores{

3printf$format,.key,'X'x($unit*.value);

4}

 

定义一个格式,%-表示左对齐,~是字符串连接操作符.for循环中,@scores中的每一项被绑定给特殊变量$_,.key是每项的键,即名字,.value是每项的键值,即得分。

小x是字符串重复操作符。

 

3.1关于优先级的的一句话

 

my@scores='Ana'=>8,'Dave'=>6,'Charlie'=>4,'Beth'=>4;

 

等号右侧产生一个列表(因为逗号,操作符),这个列表由对儿组成(因为=>),并且结果赋值给数组变量。

在Perl5中会这样解释:

1(my@scores='Ana')=>8,'Dave'=>6,'Charlie'=>4,'Beth'=>4;

以至于数组@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;

3

4say@a===@a;#Bool:

:

True

5say@a===@b;#Bool:

:

False

6

7#theseuseidentityforvalue

8

9say3===3#Bool:

:

True

10say'a'==='a';#Bool:

:

True

11

12my$a='a';

13say$a==='a';#Bool:

:

True

>@b===@a

False

>@aeqv@b

True

>'2'eqv2

False

 

只有当两个对象有相同的类型和相同的结构时,eqv操作符才返回True。

在前面定义的例子中,@a eqv @b结果为True,因为@a和@b各自包含相同的值,另一方面,'2'eqv2返回'False',因为一个参数是字符串,另一个是整数,类型不相同。

 

3.2.1数字比较

 

使用==中缀操作符查看两个对象是否有相同的数字值。

如果某个对象不是数字,Perl会在比较之前尽力使其数字化。

如果没有更好的方式将对象转换为数字,Perl会使用默认的数字0。

 

1say1==1.0;#Bool:

:

True

2say1=='1';#Bool:

:

True

3say1=='2';#Bool:

:

False

4say3=='3b';#fails

 

跟数字比较相关的还有<,<=,>,>=。

如果两个对象的数字值不同,使用!

=会返回True。

 

如果你将数组或列表作为数字,它会计算列表中项的个数。

1my@colors=;

2

3if@colors==3{

4say"It'strue,@colorscontains3items";

5}

 

3.2.2 字符串比较

Perl6中使用eq比较字符串,必要时会将其参数转换为字符串。

1if$greetingeq'hello'{

2say'welcome';

3}

 

Table3.2:

OperatorsandComparisons

数字比较

字符串比较

意思

==

eq

等于

!

=

ne

不等于

!

==

!

eq

不等于

<

lt

小于

<=

le

小于或等于

>

gt

大于

>=

ge

大于或等于

 

例如,'a'lt'b'为true,'a'lt'aa'也为true。

!

=是!

==的便捷形式,它实际是!

元操作符加在中缀操作符==之前。

同样地,ne和!

eq是一样的。

 

三路操作符

 

三路操作符有两个操作数,如果左侧较小,返回Order:

:

Increase,两侧相等则返回Order:

:

Same,如果右侧较小则返回Order:

:

Decrease。

对于数字使用三路操作符<=>,对于字符串,使用三路操作符leg(取自lesser,equal,greater)。

中缀操作符cmp是一个对类型敏感的三路操作符,它像<=>一样比较数字,像leg一样比较字符串,(举例来说)并且比较键值对儿时,先比较键,如果键相同再比较键值:

 

1say10<=>5;#+1

2say10leg5;#because'1'lt'5'

3say'ab'leg'a';#+1,lexicographiccomparison

 

三路操作符的典型用处就是用在排序中。

列表中的.sort方法能使用一个含有两个值的块或一个函数,比较它们,并返回一个小于,等于或大于0的值。

sort 方法根据该返回值进行排序:

 

1say~.sort;

2#output:

Concreteabstract

3

4say~.sort:

 ->$a,$b{uc($a)leguc($b)};

5 #output:

abstractConcrete

 

默认的,比较是大小写敏感的,通过比较它们的大写变形,而不是比较它们的值,这个例子使用了大小写敏感排序。

 

3.2.3智能匹配

 

使用~~做正确的事情。

 

1if$pints-drunk~~8{

2say"Gohome,you'vehadenough!

";

3}

4

5if$country~~'Sweden'{

6say"Meatballswithlingonb

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 自然科学 > 物理

copyright@ 2008-2023 冰点文库 网站版权所有

经营许可证编号:鄂ICP备19020893号-2