跳至主要内容

YOW 2014 集锦 (未完成)

> 刚结束的 YOW 2014 墨尔本会议,听了整整两天,各种主题演讲人的水平参差不齐—— > 口若悬河者有之;平淡无奇者亦有之。简单整理几个比较有趣的几个话题。 Andrei Alexandrescu 这次放下了 C++ 委员会成员的身份,来宣讲他自己在“非死不可”主持发展的 D language。号称在系统编程领域超过 C 和 C++,而且语法支持各种高级语言的特性。在讨论时下流行的函数式编程的时候,他举的例子是 factorial (阶乘)函数—— // version 1 - functional style, but not tail currying ulong factorial(uint n) { return n <= 1 ? 1 : n * factorial(n - 1); } AA 说这个版本的实现是作为 FB 面试开发的时候的一道考题,问说大家是否看出来问题在哪里。显然这个版本没有任何 side effect,是个颇为“完美的”function。不过由于没有实现尾递归,运行时只要 `n` 的值稍微大一些就要 Stack Overflow 了。显然这个实现是有很大问题的(AA 称之为 bankrupt)。 // version 2 - tail recursion function ulong factorial(uint n) { ulong crunch(uint n, ulong p) { return n <= 1 ? p : crunch(n - 1, n * p) } return crunch(n, 1) } 这个版本定义了一个内部函数来携带求积的中间结果,由此实现了 tail recursion。对于 Function Programming 的铁杆粉丝来说显然是极好的。 ulong factorial(uint n) { ulong result = 1; for (uint i = 1; i <= n; i++) { result = result * i; } return result; } 不过 AA 又给出了 iterative style 的实现,意味深长地问大家哪一个版本更好?他的意见是纯粹的函数式实现过于复杂,效率也未必比 iterative style 来的高。 这时候台下有人说 iterative 中使用了赋值语句导致 side effect,违背了纯粹性。AA 引入了一个“弱化的”概念—— *What does the purity really mean?* 如果一个函数在给定的输入条件下稳定地给出同样的输出,而且它内部没有调用其它的 non-pure function (如数据库写入这样的 I/O 操作等),那么即便它的实现使用了 local variable (non-static) 并对其进行赋值修改,都可以归入 functional 的范围。他甚至打了个比方——如果仅仅在脑子里想想干坏事,但是并没有实行,那么这个人对于社会而言还算是纯洁无害的吗? 更进一步,他还指出如果一个函数的签名返回类型是 `void`,接受一个数组并对其进行排序,将排好序的元素重新写回到数组中。由于函数的契约规定输入和输出都是同一个数组,in-a-agreed-way,他指出这种类型的函数也被归入 functional 的范围。AA 强调在引入了弱函数概念之后,在不少情况下可以提高程序的性能。

评论