首页 | 新闻 | 新品 | 文库 | 方案 | 视频 | 下载 | 商城 | 开发板 | 数据中心 | 座谈新版 | 培训 | 工具 | 博客 | 论坛 | 百科 | GEC | 活动 | 主题月 | 电子展
返回列表 回复 发帖

更佳编程之路 第三章 循环、整洁代码和 Perl 语言习惯用法 -2

更佳编程之路 第三章 循环、整洁代码和 Perl 语言习惯用法 -2

If、else、elsif,unless,或者,如何逗一只猫一般对程序员而言,很少有事情象理解和使用逻辑条件和布尔代数(Booleanalgebra)那样重要。编写一个不带逻辑分支的程序是完全不可能的(如果您不相信我,可以去问任何一位计算机科学教授)。Perl的逻辑运算符与 C 十分类似。有关运算符语法的详细信息,请参考 perldoc perlop 页面。
然而,有几点是不同的。对于以前使用 C/C++/Java 的人来说,首先一点是::Perl 通常不允许使用表达式作为 if 或 else 块 ―它们必须是块,而不是表达式。换句话说:
清单 5. if 或 else 块
1
2
3
4
5
6
7
if (something) dothis();                # does NOT work
if (something)                          # usually works great
{
dothis();
}
dothis() if (something);                # my favorite, but see 3.1
                                        # (it should be documented)




unless() 语句极其有用。请使用它。如果在编写一个 if()语句的过程中发现必须在检查其状态之前反转条件,那么您差不多肯定要使用 unless() 来进行替代。常见的例外情况是:需要一个elseif() 分支,控制循环的逻辑语句过于复杂,或者您不善于使用经常困扰您的反转 Boolean 语句。
与 Monty Python 的“如何逗一只猫(How to confuse a cat)”短剧十分类似,Perl 的 unless()分支逻辑一开始也令人迷惑。unless() 的概念并非来自 Perl,但是大多数 Perl 新手以前没有使用过具有 unless()的语言。新手可能会被 unless() 的强大所吓倒。毕竟,大学的计算机科学课程没有象教 if() 那样教 unless() ― 因此,有时人们把unless() 看成是流浪汉(在最好的情况下),有时看成是管闲事的人(在最坏的情况下)。其实不是那样。unless()语句是一种不同的思考方式。它将基础控制结构从笨拙的反转形式更改成一种自然的形式。请比较以下示例:
清单 6. if 和 unless,但是请学习基本的布尔代数
1
2
3
4
if (!eof()) ...
unless(eof()) ...
if (!clear && !ready) ...
unless(clear || ready) ...




唯一的窍门是从内到外反转逻辑语句 ― 在逻辑上否定每一个条件,还要反转 Boolean运算符。很容易学会基本的布尔代数(请参阅本文稍后的 ),而修复逻辑错误既不简单也不有趣。请花一些时间学习布尔代数的基本知识,您的所有代码都将从中获益。      
整洁之路(无需浴帽)如果怀念 gcc 中 lint 工具和“-Wall -pedantic”编译开关的光辉日子,那么还有希望。
使用“-W”标志告诉 Perl 解释器打开警告开关(类似于 C编译器中的“-Wall”选项,但是在运行时也被应用,而不只是在编译阶段被应用)。要那样做,您可以将“-w”开关添加到解释器调用行(在UNIX环境中通常是第一行脚本),而在其它环境中则添加一个命令行开关。一些程序员觉得只有开发人员才需要警告,而最终产品不应该再有警告。
首先,在编程领域中没有最终产品。正如 Jack Cohen 的一句名言所说:稳定即意味着死亡(a special word for stable isdead)。
第二,警告将通知用户可能有问题发生,应该预先采取行动。
第三,仅在开发周期使用警告就象使用真正的灭火器来进行防火演习而使用纸杯来扑灭真正的火一样。在产品开发周期中的任意时刻去除安全保障简直毫无意义。
“use strict”编译参数(请参阅“perldoc strict”和“perldoc perlmodlib”帮助页面)与 C编译器的“-pedantic”开关有些类似。“perldoc strict”命令将告诉您有关该编译参数的更多信息。关于“usestrict”编译参数最重要的事情是:它要求在使用变量之前定义所有变量。下例演示了“use strict”希望避免的情况:
清单 7.“use strict”要避免的错误
1
2
3
4
5
6
$this_variable_name_is_too_long = 1;
while (
)
{
$this_variabel_name_is_too_long++;
}




在它成为“臭虫(bug)”被发现之前,人们永远不会注意到这个错误。而通过使用“usestrict”,将永远不会编译上面的代码。相反,下面这段代码将必须写入:
清单 8. 清单 7 的修复版
1
2
3
4
5
6
my $this_variable_name_is_too_long = 1;
while (
)
{
$this_variable_name_is_too_long++;
}




使用长变量名的至理名言其实就是 ... 算了 ... 我们要说:假设您要输入一个长度超过 15个字符的变量名,那么您可能正在做错误的事。
不要使用函数来定义常量。虽然那曾经在 Perl 中很有必要,但是现在通过“useconstant”编译参数来完成。在下例中,请注意注释的风格和箭头的对齐。这段代码看起来很舒服,这说明作者细心编排了每一行代码。一些编辑器(例如Emacs)可以自动做这种对齐工作。
清单 9. 要定义约束的“use constant”
1
2
3
use constant CHILDREN => 3;             # 3 children per process
use constant PI       => 3.14;          # 2 digits of precision
use constant MESSAGE  => "Hello";       # a message




在调用函数之前先制订函数原型。制订函数原型很容易。“perldocperlsub”帮助页面将帮助您更好地理解原型。制订原型对于任何程序员来说都是个好习惯,因为它可以显示出预想(forethought)并在特定情况下帮助您避免编译器错误。在函数更改时更改原型可能令人乏味,但是这里的问题在于在一开始就没有定义好函数。在编码之先制订计划,在制订计划之前先思考。每隔10 分钟思考一下代码将采取的途径将为您节省 1 小时的编码和调试时间。
Perl 自动在字符串和数字之间转换。不能也没有必要关闭这项特性,但是 Perl程序员新手可能在几小时内就会产生出新的让人感到意外的错误。请阅读 Perl FAQ(请参阅 )、        Programming Perl或        Learning Perl 书籍,当然还有“perldocperldata”帮助页面(“Scalar values”部分)。      
练习
  • 编写一个从 1 数到 100 的循环,并且
    • 打印所有偶数
    • 打印所有奇数
    • 打印所有以 1、2 或 7 结尾的数字
  • 编写一个从 100 向后数到 1 的循环
  • 编写一个程序,该程序读取标准输入并打印以“hello”(大写、小写或大小写混合均可)开始的所有行。提示:请查看“perldocperlrun”帮助页面,尝试使用 Perl 的内置开关,而不要编写自己的循环。
  • 编写一个逻辑条件,该条件将检查一个标量是否已定义、是否是非零、回文(向前读和向后读都一样)或者是数字234.98。分别使用和不使用 Perl 解释器的“-w”标志和“usestrict”编译器编译参数各测试一次。如果生成了警告信息,您是否理解这些警告信息?
  • 以通常(不带后缀)的表示法编写以下代码,如果可以,则简化它们:
    • print if $debug;
    • $i++ unless $i > 10;
    • unless ($j && !$i) { $j += $i while <> };
    • next while <>;
返回列表