特殊封闭用例:为什么要使用封口?

时间:2010-10-18 23:37:07

标签: binding closures environment use-case

更新

我正在设计一种实验性编程语言,问题是包含闭包还是只使用一流函数。为了确定这一点,我需要真实的用例/示例来展示闭包对一等函数的好处。我知道您可以使用两个中的一个实现所有 ,但是有几个用例例如:代码更容易阅读的第一类函数(例如更短或不分成几个类)。 E.g:

红宝石:

[1,5,7].map{|x| x*x }
[1,'test',3].select{|x| x.kind_of? Integer}.map{|x| x.to_s }
big_array.each{ |item| puts item }

如果没有第一类函数,这些示例将会更冗长,因为您必须使用for循环或类似的东西。

现在,哪些用例显示了闭包的用处?即使我经常使用一流的功能,但我真的无法为闭包提供良好的用例。你有什么好的闭包用例吗?

原帖

我不明白为什么闭包绑定到变量而不仅仅是,例如:

红宝石:

x = 5
l = lambda { x }
l.call #=> 5
x = 100
l.call #=> 100

什么是在引用变量时使用,而不仅仅是在闭包定义点引用存储在变量中的值?就像在这个例子中一样:

红宝石:

x = 5
l = lambda { x }
l.call #=> 5
x = 100
l.call #=> 5, not 100

是否有必要在闭包定义时引用变量而不仅仅是那些变量的的好用例?

2 个答案:

答案 0 :(得分:1)

关闭的全部意义在于封闭状态可以改变。可以说,关闭不能(或不能)改变的东西是不好的形式,因为你隐藏了一个参数。

在C#中采用以下人为设想的例子:

var sb=new StringBuilder();
int counter = 0;
var Append=(int a, string s)=>
            sb.Append(a*a + counter++, SomethingElse(s, "some constant"));

Append关闭了StringBuilder和计数器,这样我就可以通过我的代码来调用它,而不必每次都通过SomethingElsesb.Append仪式。如果封闭内部的状态无法改变,那么封闭对于这种事情就不那么有用了。

答案 1 :(得分:0)

根据我的理解(有人请帮我解决,如果我错了)使用lambda表达式中的变量将变量(例如“Foo as Widget”)更改为New Holder(Of Widget),定义如下所示,并将对Foo的所有引用更改为对Foo.Value的引用。然后将关闭变量的持有者作为参数传递给代表工厂。

Class Holder(Of T)
  Public Value As T

  Sub New(NewValue As T)
    Value = NewValue
  End Sub
End Class

我不太确定额外的包装层是否真的有用。我认为更常见的是,人们希望按值获取局部变量。在我自己的代码中,在我升级到支持lambdas的VB版本之前,我使用了委托工厂,例如。

  Sub SetText(ByVal St As String)
    Text = St
  End Sub

  ... elsewhere
    MyControl.BeginInvoke(NewInv(AddressOf SetText, someExpression))

请注意,执行BeginInvoke本身时将评估 someExpression ,而不是在实际执行延迟操作时。另请注意,我的NewInv()函数系列支持1-4个参数的泛型覆盖,如果需要Action(Of T)而不是MethodInvoker,我有一个通用静态类,其中包含另一个函数族。 / p>

这种方法的一个优点是,顺便说一下:它适用于编辑/继续。