《高阶Perl》——1.6 函数式编程与面向对象式编程

1.6 函数式编程与面向对象式编程

现在停下来看看已经做的。已经有了一个有用的函数,total_size(),它包含了在其他应用中遍历目录结构的有用代码。所以为使total_size()更具普遍意义,把所有与计算大小相关的部分提出来,替换成用户指定的任意函数的调用。结果就是dir_walk()。现在,对于任何需要遍历目录结构并做某事的程序,dir_walk()处理遍历部分,参数函数处理“做某事”部分。通过传递合适的函数对给dir_walk(),可以使它做任何想要它做的事情。已经获得了灵活性与复用dir_walk()的机会,通过提取有用的部分并参数化成两个函数参数。这便是函数式编程风格的核心。

面向对象式(Object Oriented,OO)的编程风格最近受到了更多关注。OO风格的目标和函数式风格的一样:期望通过把软件分割成通用的部分提高它的可复用性。

在一个OO系统中,可以类似地转换total_size(),但是结果看起来会不同。可以把total_size()做成一个目录遍历对象的抽象基类,这些对象有一个方法,dir_walk(),它依次调用两个未定义的虚方法file与directory。 (在C++中,它们称为纯虚方法(pure virtual method)。)这样一个类本身还没有用处,因为缺少file方法与directory方法。为了使用这个类,你要产生一个子类定义file方法与directory方法,然后产生子类的对象。这些对象将全部继承相同的dir_walk方法。

在这个例子中,我认为函数式的风格会带来一个更轻量级和更易用的解决方案,并使参数函数靠近它被使用的地方,而不是陷入一个类文件里。但重要的一点是尽管风格不同,原函数分解成的有用的组成部分却有完全相同的结构。函数式风格使用函数式参数,面向对象式风格使用纯虚方法。虽然本书的剩余部分是关于函数式编程的,但许多技术也将直接适用于面向对象式编程风格。

时间: 2024-10-22 08:02:39

《高阶Perl》——1.6 函数式编程与面向对象式编程的相关文章

《高阶Perl》——导读

前 言 在编程圈子里有一句著名的俗语,一个优秀的Fortran程序员可以用任何语言写Fortran程序.然而,让人悲哀的是,不管他们是否愿意,Fortran程序员用任何语言写Fortran程序.类似地,作为Perl程序员,我们也在用Perl写C程序,不管我们是否愿意.这让人羞愧,因为Perl是一门比C更富有表现力的语言.我们本可以做得更好,以C程序员梦想不到的方式使用Perl,但是我们没有那样做. 怎么会这样呢?Perl的设计初衷是一方面作为C的替代品,另一方面作为UNIX脚本语言(如Bourn

《高阶Perl》——3.8 对象方法里的缓存

3.8 对象方法里的缓存 对象方法,它经常不理解地把缓存的值保存在独立的散列里.考虑一个投资银行写的程序里的Investor对象.该对象表现了银行的一个客户: package Investor; # Compute total amount currently invested sub total { my $self = shift; # ... complex computation performed here ... return $total; } 如果$total不会改变,就可以缓存

《高阶Perl》——3.12 速度的好处

3.12 速度的好处 此刻有个说法比较诱人,那就是记忆术只比手动缓存技术改善了一点,因为它做了同样的事情,仅有的额外的好处是你可以快速启动或者关闭它.但这不完全正确.当工具之间的速度和便利的差别够大,它会改变你思考和使用工具的方式.自动地使一个函数带记忆仅需要消耗手动书写代码的1/100的时间.这和飞机与牛车的速度差别一样.说飞机只是更快的牛车就忽略了本质:量变如此巨大以致它也变成了实质的质变. 例如,有了自动的记忆术,就有可能为函数增加缓存行为而不必预先仔细考虑性能细节.记忆术这么简单以至于可

《高阶Perl》——3.2 内联缓存

3.2 内联缓存 给一个函数添加缓存的最直接的方式就是给函数一个私有的散列.在这个例子里,可以使用一个数组代替散列,因为fib()的参数总是一个非负整数.但是一般需要使用一个散列,那么将会看到: ### Code Library: fib-cached # Compute the number of pairs of rabbits alive in month n { my %cache; sub fib { my ($month) = @_; unless (exists $cache{$m

《高阶Perl》——3.5 MEMOIZE模块

3.5 MEMOIZE模块 本书不是关于Perl模块的内部细节的,而是关于一些Memoize模块内部使用的并和稍后要做的事情有直接联系的技术,所以现在简短地介绍一下. Memoize得到一个函数名(或引用)作为它的参数.它制造一个新的函数,后者维护一个缓存并在其中查找它的参数.如果新的函数在缓存里找到了参数,就返回缓存的值:如果没找到,就调用原始函数,把返回的值保存入缓存,并把它返回给原始的主调者. 制造完这个新的函数,Memoize就把它装入Perl的符号表以代替原始的函数,那样当你认为你在调

《高阶Perl》——3.10 可供选择的记忆术

3.10 可供选择的记忆术 大多数纯函数提供一个缓存的机会.尽管乍一看纯函数很少,它们只以一定频率出现.纯函数特别普遍的地方是在排序中用做比较器函数. Perl内置的sort操作符是通用的,它可以把一列任何种类的数据以程序要求的任何次序排序.默认状态下,它把一列字符串以字母表次序排序,但是程序员可以任意提供一个比较器函数(comparator function),告诉Perl怎样重排sort的参数列表.比较器函数被反复调用,每次带有待排序列表中的两个不同元素,如果两个元素次序正确,就必须返回一个

《高阶Perl》——第2章 分配表 2.1 配置文件处理

第2章 分 配 表 第1章介绍了如何用别的函数参数化函数的行为使函数更加灵活.例如,并没有把每次移动盘子就输出一条消息硬编码到hanoi()函数里,而是让其调用一个从外部传入的辅助函数.通过提供一个合适的辅助函数,可以使hanoi()输出一系列说明,或检查它自己的行动,或生成一个图形显示,而不必重新编写基本的算法.类似地,可以从total_size()函数的计算文件大小的行为中提取出目录遍历行为,得到一个更有价值和普遍适用的dir_walk()函数,它可以做许多不同的事情. 为了从hanoi()

《高阶Perl》——3.7 键的生成

3.7 键的生成 先前的记忆器至少有一个严重的问题.它需要把函数的参数转变成一个散列键,它的做法是使用join: my $key = join ',', @_; 这对只带一个参数的函数有效,也对参数不含逗号的函数有效,包括所有的参数是数字的函数.但是如果函数的参数可能包含逗号,它可能失效,因为以下两个调用却计算出了相同的键: func("x,", "y"); func("x", ",y"); 第一次调用,返回的值将以键&quo

《高阶Perl》——1.2 阶乘

1.2 阶乘 假设有一个有n个不同条目的列表.为了具体点,假设这些条目是字母表的字母.这样一个列表有多少种不同的排列次序呢?显然,因为答案依赖于n,所以它是n的函数.这个函数称为阶乘函数(factorial function).n的阶乘就是n个不同条目的不同的排列次序的数量.通常以一个后缀!标记,这样n的阶乘就是n!.一般不同的次序称为排列(permutation). 下面计算一些阶乘.显然,只有一个条目的列表只有一种排列,所以1!=1.两个条目的列表有两种排列:A-B和B-A.少许笔算可以发现