我不同意 WReach 的回答。让我们稍微解构他的答案,看看分歧来自哪里。
首先,他的代码:
function allOdd(words) {
var result = true;
for (var i = 0; i < length(words); ++i) {
var len = length(words[i]);
if (!odd(len)) {
result = false;
break;
}
}
return result;
}
和
function allOdd(words) {
return apply(and, map(compose(odd, length), words));
}
首先要注意的是,他正在混为一谈:
编程,并且缺少迭代式编程比典型的函数式编程具有更明确的控制流的能力。
让我们快速谈谈这些。
以表达为中心的风格是事物尽可能地评估事物的风格。尽管函数式语言因其对表达式的热爱而闻名,但实际上有可能拥有一种没有可组合表达式的函数式语言。我要编一个,没有表达,只有陈述。
lengths: map words length
each_odd: map lengths odd
all_odd: reduce each_odd and
这与之前给出的几乎相同,除了函数纯粹通过语句链和绑定链接。
Python 可能采用以迭代器为中心的编程风格。让我们使用纯迭代的、以迭代器为中心的风格:
def all_odd(words):
lengths = (len(word) for word in words)
each_odd = (odd(length) for length in lengths)
return all(each_odd)
这不起作用,因为每个子句都是一个迭代过程,并且它们通过堆栈帧的显式暂停和恢复绑定在一起。语法可能部分受到函数式语言的启发,但它适用于它的完全迭代实施例。
当然,你可以压缩这个:
def all_odd(words):
return all(odd(len(word)) for word in words)
现在命令式看起来并不那么糟糕,是吗?:)
最后一点是关于更明确的控制流。让我们重写原始代码以利用它:
function allOdd(words) {
for (var i = 0; i < length(words); ++i) {
if (!odd(length(words[i]))) {
return false;
}
}
return true;
}
使用迭代器,您可以:
function allOdd(words) {
for (word : words) { if (!odd(length(word))) { return false; } }
return true;
}
那么,如果两者之间存在差异,那么函数式语言的意义何在:
return all(odd(len(word)) for word in words)
return apply(and, map(compose(odd, length), words))
for (word : words) { if (!odd(length(word))) { return false; } }
return true;
函数式编程语言的主要决定性特征是它消除了作为典型编程模型一部分的变异。人们通常认为这意味着函数式编程语言没有语句或使用表达式,但这些都是简化。函数式语言用行为声明代替显式计算,然后语言对其进行归约。
将自己限制在这个功能子集可以让您对程序的行为有更多的保证,这使您可以更自由地组合它们。
当您拥有一种函数式语言时,创建新函数通常就像编写密切相关的函数一样简单。
all = partial(apply, and)
如果您没有显式控制函数的全局依赖关系,这并不简单,或者甚至不可能。函数式编程的最佳特性是您可以始终如一地创建更通用的抽象并相信它们可以组合成一个更大的整体。