Using Perl6 第二章:The Basics

2: The Basics

Table of Contents

1 about

github地址:https://github.com/gaorongchao/Perl6/tree/master/Using_perl6

如果发现任何错误和翻译不当的地方,请告知,非常感谢。

2 第二章:基础

Perl起源于一个致力于从文本文件中收集整理信息的编程语言。 现在Perl在文本处理方面仍然强大,Perl 5 是一个一般意义上的强力编程语言。 但是Perl 6更为杰出。

假设你举办了一个乒乓球联赛。 裁判告诉你比赛结果的格式:选手1 选手2 | 3:2,这意味着,选手1赢了3局,选手2赢了2局。 你需要一个脚本来,来统计选手赢了几场比赛,赢了多少局,并以此决定最终冠军的归属。

输入文件格式如下(储存在一个名为“scores”的文件中):

Beth Ana Charlie Dave 
Ana Dave            |  3:0
Charlie Beth        |  3:1
Ana Beth            |  2:3
Dave Charlie        |  3:0
Ana Charlie         |  3:1
Beth Dave           |  0:3

第一行是所有选手的名字,后面跟着的是每场比赛的结果。 这里有一个解决此问题的Perl 6 脚本:perl-1-1:

 1:  use v6;
 2:  
 3:   my $file = open 'scores';
 4:   my @names = $file.get.words;
 5:  
 6:   my %matches;
 7:   my %sets;
 8:  
 9:   for $file.lines -> $line {
10:   my ($pairing, $result) = $line.split(' | ');
11:   my ($p1, $p2) = $pairing.words;
12:   my ($r1, $r2) = $result.split(':');
13:  
14:   %sets{$p1} += $r1;
15:   %sets{$p2} += $r2;
16:  
17:   if $r1 > $r2 {
18:   %matches{$p1}++;
19:   } else {
20:   %matches{$p2}++;
21:   }
22:   }
23:  
24:   my @sorted = @names.sort({ %sets{$_} }).sort({ %matches{$_} }).reverse;
25:  
26:   for @sorted -> $n {
27:   say "$n has won %matches{$n} matches and %sets{$n} sets";
28:   }

输出文件:

Ana has won 2 matches and 8 sets
Dave has won 2 matches and 6 sets
Charlie has won 1 matches and 4 sets
Beth has won 1 matches and 4 sets

每一个Perl6程序都需要以 “use v6”; 开始。这一行告诉编译器Perl代码的版本。 如果,你不小心用Perl5来运行这个程序,你将得到错误信息。

一个Perl6程序包含0行或者更多的语句。每一个语句以分号结尾,或者以大括号结尾:

1:  my $file = open 'scores';

"my"声明一个词法变量。词法变量只在当前代码块可用,从声明开始到代码块的结束。 如果一个代码块始终没有闭合,那么该变量可以在剩下的所有地方使用。代码块的定义是: 一段在花括号\{\}之间的代码。

一个变量名称以“魔符”开始,魔符是指那些非字母,非数字的符号,比如:$,@,% 或者&- 或者有时出现的双冒号“::”也是。 魔符指明了变量的结构类型,比如:它应该被当作一个值,还是多个值,还是一个子程序,等等。 跟在“魔符”后面的是“标识符”,标识符可以包含字母,数字和下划线。在字母与字母之间, 你可以用短横线“-”或者撇号“'”。所以“isn't”和“double-click”都是合法的变量标识符。

魔符“$”表明变量是一个数值变量,指明这个变量只存储了一个值。

内建函数“open”打开了一个名为“scores”的文件,然后返回一个文件句柄, 文件句柄是一个代表该文件的对象。 赋值符号“=”,把文件句柄赋值给左边的变量,这也就是意味着变量$file现在存储着文件句柄。

“scores”是字符串文本(string literal)。字符串(string)是一段纯文本。 字符串文本(string literal)是直接出现在程序中的字符串。 在这一行中,它是提供给open函数的参数。

1:  my @names = $file.get.words;

上面语句的右侧调用了一种“方法”(一个命名的一系列行为的集合体)获取存储在$file变量中的句柄。 被命名为get的这一方法从文件中读取并返回一行,去掉末尾的换行符。word同样是一个方法,调用从 get中返回的一行文本。word这一方法,分解它的invocant(它要操作的字符串)成一系列的单词。 这里单词的意思是不包含空格的字符串。它把字符串“Beth Ana Charlie Dave”分解成多个字符串 “Beth”,“Ana”,“Charlie”,“Dave”。

最后,这一字符串列表存储到数组@names中。魔符@表明所声明的变量是一个数组。数组存储的是有序列表。

1:  my %matches;
2:  my %sets;

这两行代码声明了两个哈希。魔符“%”把变量标记为哈希。哈希又称为散列:是无序的键-值对的集合。 在其他语言中又称为“哈希表”,“字典”或者“(map)图” 你可以通过“键 $key”利用“%hash{$key}”来查询在哈希表中的值。

在上述计分程序中,%matches记录了每一位运动员赢的次数。%sets记录了每一位运动员赢的局数。

魔符指出了默认访问变量的方法。数组变量@是通过位置来访问, 哈希变量%是通过“键”来访问。 数值变量$表示一个大箩筐,这里可以盛任何东西,也可以用任何方式来访问。 一个数值变量可以包含一个复杂对象(compound object),比如:数组或者哈希; 魔符$表明它应该被当作一个单独的值,尽管有可能它包含众多的值(像一个数组或者哈希)。

1:  for $file.lines ->$line{
2:  ...
3:  }

“for”产生了一个由花括号界定运行范围的循环,循环会遍历列表中的每一个值。 $file.lines 从scores文件中读取了很多行,除掉前面$file.get读取的那一行以外,到最后一行。 循环依次将每一行的值赋予$line变量。

第一次迭代$line将包含字符串 “Ana Dave | 3:0”;第二次迭代$line将包含字符串“Charlie Beth | 3:1”,等等。

1:  my ($pairing,$result) = $line.split('|');

“my”可以同时声明多个变量。在赋值符号(=)的右侧调用了一个名为“split”的方法,它把“|”当作参数。

split把他作用的内容以|为分割点,分割成一系列的字符串。所以如果你用“|”作为粘合符号,把这些字符串粘合。 那么你将得到原始字符串。

$pairing 得到返回列表的第一个元素,$result 得到第二个。

当处理完第一行以后,$pairing 包含“Ana Dave”这个字符串,$result包含“3:0”。

下面两行是同样的模式:

1:  my ($p1,$p2) = $pairing.words;
2:  my ($r1,$r2) = $result.split(':');

第一行代码提取并保存两位运动员的姓名到$p1和$p2这两个变量中。

第二行提取每一位运动员的比赛结果,并且分别保存到$r1和$r2中。

上面程序运行以后,下面列出每一个变量包含的值:

Table2.1:Contents of Variables

1:  Variable  Contents               
2:  $line     'Ana Dave    | 3:0' 
3:  $pairing  'Ana Dave'              
4:  $result   '3:0'                   
5:  $p1       'Ana'                   
6:  $p2       'Dave'                  
7:  $r1       '3'                     
8:  $r2       '0'                     

程序接下来统计了每一位运动员赢的局数:

1:  %sets{$p1} += $r1;
2:  %sets{$p2} += $r2;

这是下面的简写:

1:  %sets{$p1} = %sets{$p1}+$r1;
2:  %sets{$p2} = %sets{$p2}+$r2;

+= $r1 的含义是:把左侧的变量加上$r1. 在第一次迭代的时候%sets{$p1}还没有设置类型, 所以默认为一个称为“Any”的特殊值。 加法和递增操作符作为一个数字操作符,把Any当作一个值为0的数字。 所以这个字符串自动转换为数字。

在这两行代码执行以前,%sets 是空的。 在hash中添加一个完全不存在的元素,将会使这个元素立马在哈希中存在。 并且赋予初始值为0.(这被称为autovivification)。 当这两行第一次运行以后,%sets包含“ 'Ana'=> 3,'Dave'=>0”。 (胖箭头=>把键值对分开)

1:  if $r1>$r2{
2:      %matches{$p1}++;
3:  } else {
4:      %matches{$p2}++;
5:  }

如果$r1 的值大于$r2的值,那么%matches{$p1}增加1。 如果$r1 的值小于$r2的值,那么%matches{$p2}增加1。 和前面的+=的例子一样,如果哈希中没有存在这个值, 那么这个哈希值将会因为自增符号而自动生成。

$thing++ 是$thing +=1的缩写。 需要注意的一点是,$thing++这个表达式返回的$thing的值是没有增加前的值。 而不是增加以后的。在其他很多的编程语言中你可以把++前置。这样得到的增加 以后的返回值。my $x=1; say ++$x 输出2。

1:  my @sorted = @names.sort({ %sets{$_} }).sort({ %matches{$_} }).reverse;

这一行代码包含三个独立的过程。首先调用数组的sort方法。 但是默认的排序方法是按照内容排序的。为了按照赢得多少的顺序输出运动员的姓名, 我们的程序必须按照运动员的成绩来排序,而不是用他们的名字。 sort方法的参数一个代码块,用来把数组元素(运动员的名字)转化为用来排序的数据。 数组元素是通过“$_”变量来传递的。

你在前面已经看到过代码块:不论是“for loop-> {…}”还是在代码块中的if语句。 代码块是:一个独立的带有 signature(the ->$line 的部分)Perl6代码。 更多内容请参照sec::signatures。

按照运动员成绩排序的最简单的方法是@names.sort({ %matches{$_} }), 这是按照运动员赢的次数决定的。但是问题是,Ana 和Dave都赢了2次。 最简单的排序方式并没有考虑到每个人赢的局数,而这个正是决定谁赢的循环赛的第二个评判标准。

如果两个数组元素拥有相同的值, sort按照发现他们的先后顺序放置他们。 计算机科学家们称之为:稳定排序。 这个程序充分利用了Perl6排序的相关特性来利用两次排序来实现目标: 第一次按照赢取局数的多少排序(也就是次要的冠军评判标准),然后按照赢取的次数来排序。

在第一次排序以后,运动员的名字顺序是这样的:Beth Charlie Dave Ana。 在第二次排序以后,顺序依然一样。因为没有人赢了更少的次数,但是赢了更多的局数。 这种情况是很正常的,特别是在大型的循环赛中。

sort是按照升序来排序,也就是从小到大排序。 但这与我们的期望是相反的。所以,我们的程序在第二次排序以后,又调用了.reverse方法。 最后把结果存入到@sorted数组中。

1:  for @sorted -> $n {
2:      say "$n has won %matches{$n} matches and %sets{$n} sets";
3:  }

为了输出运动员的名字和他们的成绩,我们对@sorted数组进行循环。 依次将运动员名字赋值给$n。我们可以这样来读代码“对数组sorted中的每一个元素, 赋值给$n,然后执行下面的代码块”。 然后用say 进行标准输出(也就是输出到屏幕)。 然后后面自动加上换行符。 如果你不想在最后加上换行符,那就用print函数。

当你运行本程序的时候,你会发现,say并不会逐字的输出所有内容。 在$n的位置上,它将会打印变量$n的内容:也就是存储在$n中的运动员的名字。 这种自动替换被称为“interpolation(变量内插)” 这种变量内插只会发生在双引号内,而不会发生在单引号内。

1:  my $names = 'things';
2:  say 'Do not call me $name'; # Do not call me $names
3:  say "Do not call me $name"; # Do not call me things

在Perl6中,双引号不仅能够内插魔符$的变量,同时也可以内插在花括号内的代码块。 因为任意的Perl代码都可以通过花括号出现,所以可以通过把数组和哈希放在花括号内 实现内插的效果。

数组放在花括号内插以后,两个元素之间会插入一个空格。 哈希放在花括号内插以后,以多行的形式显示,每一行包括一个键,然后跟着一个制表符。 然后紧跟这键对应的值,最后加上换行符。

1:  say "Math: {1+2}";                  # Match: 3
2:  my @people = <Luke Mattew Mark>;
3:  say "The synoptics are: {@people}"; # The synoptics are :Luck Matthew Mark
4:  say "{%sets}";                      # 接前面网球循环赛
5:  # Charlie 4
6:  # Dave    6
7:  # Ana     8
8:  # Beth    4

当数组和哈希变量直接出现在双引号之间的时候(并没有在花括号之间),那么只有在它们的名字 后面紧跟方括号的时候才会变量内插。当然你也可以在变量名和postcircumfix之间调用一种 方法来实现变量内插。

 1:  my @flavours = <vanilla peach>;
 2:  say "we have @flavours";          # we have @flavours
 3:  say "we have @flavours[0]"        # we have vanilla
 4:  # so-called "Zen slice"
 5:  say "we have @flavours[]";        # we have Vanilla peach 
 6:  
 7:  # method calls ending in postcircumfix
 8:  say "we have @flavours.sort()";   # we have peach  vanilla
 9:  
10:  # chained method calls:
11:  say "we have @flavours.sort.join(',')"; # we have peach ,vanilla

Date: 2014-03-23T10:53+0800

Author: GRC(扬眉剑)

Org version 7.9.3f with Emacs version 24

Validate XHTML 1.0
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 《C语言入门之旅:基础知识》是一本以C语言为主题的书籍,旨在帮助读者快速掌握C语言的基本知识。以下是对该书的回答: 《C语言入门之旅:基础知识》这本书重点介绍了C语言的基本概念、语法特性以及常见用法。它适合那些想要学习C语言编程,但没有任何编程经验的读者。该书从简单易懂的角度出发,循序渐进地引导读者入门C语言。 首先,《C语言入门之旅:基础知识》详细介绍了C语言的起源和发展历程,帮助读者了解C语言的背景和重要性。接着,书中从最基本的数据类型开始,逐步介绍了C语言的各类数据类型、变量和常量的定义与使用方法。读者通过实例代码的学习和练习,可以更好地理解这些概念。 该书还介绍了C语言的运算符和表达式,包括算术运算符、关系运算符、逻辑运算符等。通过这部分的学习,读者能够掌握基本的运算和表达式求值的方法。 另外,书中还涵盖了C语言的流程控制语句,例如条件语句(if-else语句)、循环语句(for循环、while循环等)和跳转语句(break语句、continue语句等)。读者可以学习如何使用这些语句来实现程序的控制流。 此外,该书还介绍了C语言中的数组和字符串,以及如何使用它们进行数据的存储和处理。同时,它还包含了C语言的函数创建与调用、指针的使用方法等重要内容。 总之,《C语言入门之旅:基础知识》通过简单易懂的语言,系统全面地介绍了C语言的基础知识。无论是初学者还是有一定编程基础的读者,都可以通过这本书快速入门C语言编程,打下坚实的基础。 ### 回答2: " C语言基础之旅" 是一次让您了解C语言基础知识的旅程。C语言是一种广泛应用于系统编程和嵌入式设备的高级编程语言,也是许多计算机科学专业学习中的必修课程。 首先,我们将介绍C语言的历史和起源,以及它为什么成为一种如此重要的编程语言。接着,我们将深入了解C语言的基本语法和语义,包括变量、数据类型、运算符、控制结构和函数定义等。这些基础知识将为您构建和理解C语言程序打下坚实的基础。 在旅程的下一站,我们将探索C语言的输入和输出,包括如何从键盘接收输入和将数据输出到屏幕或文件中。我们还将介绍如何使用C语言的库函数来进行字符串处理、数学运算和内存管理等。 然后,我们将进一步深入研究C语言的数组和指针,这是C语言中一个非常重要也最具挑战性的概念。我们将学习如何声明、初始化和操作数组,以及如何使用指针来访问和操作内存中的数据。这些概念将帮助我们提高代码的效率和灵活性。 在最后的旅程中,我们将介绍C语言的结构体和文件操作。通过学习如何定义和使用结构体,我们可以创建自定义的数据类型来组织和管理数据。而文件操作将使我们能够读取和写入文件,使我们的程序能够与外部系统进行交互。 通过这次"C语言基础之旅",您将全面了解C语言的基础知识和概念,为进一步深入学习编程和开发复杂的应用程序奠定坚实的基础。无论是寻求职业发展还是追求计算机科学的真正爱好者,掌握C语言将成为您的重要优势。让我们一起开始这次旅程吧! ### 回答3: 《C语言基础教程》是一本针对初学者的C语言入门指南。C语言是一种通用的编程语言,广泛应用于软件程序的开发。该书通过一个实例化的游览项目,带领读者逐步了解C语言的基本概念和技巧。 首先,该书介绍了C语言的历史和发展,并解释了为什么学习C语言对于软件开发人员至关重要。它探讨了C语言与其他编程语言的区别,以及C的主要特征和优势。 接下来,书中详细解释了如何设置C语言的开发环境。读者将学会如何安装和配置C语言的编译器,以及如何使用集成开发环境(IDE)进行编程。此外,该书还介绍了用于编写C代码的文本编辑器和调试器,并提供了一些常见问题的解决方案。 在了解了开发环境之后,书中引导读者学习C语言的基本语法和语义。读者将了解如何声明和使用变量、编写基本的控制结构(如条件语句和循环),以及如何定义和调用函数。通过大量的示例代码和练习题,读者可以逐步巩固所学内容。 此外,《C语言基础教程》还介绍了C语言中常用的数据类型、运算符和数组等。读者将学会如何使用这些概念来解决实际问题,并掌握一些常见的编程技巧和最佳实践。 尽管《C语言基础教程》只是C语言学习的一个入门指南,但它提供了足够的基础知识,让读者能够理解和编写简单的C程序。通过学习这本书,读者可以为进一步深入学习C语言奠定坚实的基础,并为未来的软件开发之旅做好准备。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值