我评论了上面关于 lambda 的 rkj 的回答。此代码演示了您要求的示例;
def abs(n); (n < 0) ? -n : n; end
def square(n); n * n; end
def average(x, y); (x + y) / 2; end
def fixed_point(x, point, process, test)
return point if test.call(x, point)
fixed_point(x, process.call(x, point), process, test)
end
def sqrt(n)
process = lambda {|n,g| average g, (n/g) }
test = lambda {|n,g| abs(square(g) - n) < 0.001}
fixed_point(n, 1.0, process, test)
end
首先要注意的一点是,该fixed_point
方法处理的一般思想是逐步将过程应用于某些数据,直到它通过某个测试。该sqrt
函数定义了求平方根的过程和确定何时满足的测试。然后像任何其他形式的数据一样传递这些“程序”,这样就fixed_point
可以发挥它的魔力。
而不是临时存储过程和测试整个事情可以是匿名的。我们可以重写sqrt
为;
def sqrt(n)
fixed_point( n, 1.0,
lambda {|n,g| average g, (n/g)},
lambda {|n,g| abs(square(g) - n) < 0.001} )
end
如果没有这种能力,我将不得不将流程和测试都定义为单独的函数,并创建一个特殊的sqrt_fixed_point
函数来调用它们。据我所知,Java 可以使用 Functor 做类似的事情,但我不知道如何评论。我在博客或类似文章中看到的共识是,Java 使这变得非常复杂,以至于您尝试一下就会流鼻血。
当然,Ruby 提供的另一个选择是元编程。我可以重写sqrt
,以便它fixed_point
使用正确的过程和测试(即时)重写,但这可能是对该功能的滥用:-)
附言。发布的 JoelOnSoftware 链接值得重复;http://www.joelonsoftware.com/items/2006/08/01.html