基本上这两种风格,就像阴阳。一个是有组织的,一个是混乱的。在某些情况下,函数式编程是显而易见的选择,而在其他情况下,过程式编程是更好的选择。这就是为什么至少有两种语言最近推出了一个新版本,包含两种编程风格。 (Perl 6 和 D 2)
#程序:#
- 例程的输出并不总是与输入直接相关。
- 一切都按特定顺序完成。
- 执行例程可能会产生副作用。
- 倾向于强调以线性方式实施解决方案。
##Perl 6##
sub factorial ( UInt:D $n is copy ) returns UInt {
# modify "outside" state
state $call-count++;
# in this case it is rather pointless as
# it can't even be accessed from outside
my $result = 1;
loop ( ; $n > 0 ; $n-- ){
$result *= $n;
}
return $result;
}
##D 2##
int factorial( int n ){
int result = 1;
for( ; n > 0 ; n-- ){
result *= n;
}
return result;
}
#Functional:#
- 通常是递归的。
- 对于给定的输入总是返回相同的输出。
- 评估顺序通常是未定义的。
- 必须是无国籍的。即任何操作都不会产生副作用。
- 非常适合并行执行
- 倾向于强调分而治之的方法。
- 可能具有惰性求值功能。
##Haskell##
(复制自Wikipedia);
fac :: Integer -> Integer
fac 0 = 1
fac n | n > 0 = n * fac (n-1)
或一行:
fac n = if n > 0 then n * fac (n-1) else 1
##Perl 6##
proto sub factorial ( UInt:D $n ) returns UInt {*}
multi sub factorial ( 0 ) { 1 }
multi sub factorial ( $n ) { $n * samewith $n-1 } # { $n * factorial $n-1 }
##D 2##
pure int factorial( invariant int n ){
if( n <= 1 ){
return 1;
}else{
return n * factorial( n-1 );
}
}
#旁注:#
Factorial 实际上是一个常见的例子,它展示了在 Perl 6 中创建新运算符是多么容易,就像创建子例程一样。这个特性在 Perl 6 中根深蒂固,以至于 Rakudo 实现中的大多数运算符都是这样定义的。它还允许您将自己的多候选人添加到现有的运营商。
sub postfix:< ! > ( UInt:D $n --> UInt )
is tighter(&infix:<*>)
{ [*] 2 .. $n }
say 5!; # 120
此示例还显示了范围创建 (2..$n) 和列表归约元运算符 ([ OPERATOR ] LIST) 与数字中缀乘法运算符的结合。 (*)
它还表明您可以将--> UInt 放在签名中而不是returns UInt 之后。
(您可以不使用以2 开头的范围,因为在不带任何参数的情况下调用乘法“运算符”将返回1)