首页 文章

如何在函数式语言中使用闭包

提问于
浏览
3

出于某种原因,我倾向于将闭包与函数语言相关联。我相信这主要是因为我所看到的关于闭包的讨论几乎总是在一个专注于函数式编程的环境中。话虽这么说,我能想到的闭包的实际用途本质上都是 non-functional。

在函数式语言中是否存在闭包的实际用法,或者在我的脑海中是否存在关联,主要是因为闭包用于以函数式编程语言(一流函数,currying 等)常见的样式编程?

编辑:我应该澄清一下,我指的是实际的函数式语言,这意味着我正在寻找保持参照透明度的用法(对于相同的输入,你得到相同的输出)。

编辑:添加到目前为止发布内容的摘要:

  • 闭包用于实现部分评估。具体来说,对于带有两个参数的函数,可以使用一个参数调用它,这会导致它返回一个带有一个参数的函数。通常,该第二函数“存储”传递给它的第一个值的方法是闭包。

  • 可以使用闭包来实现对象。返回一个关闭了许多变量的函数,然后可以像对象属性一样使用它们。函数本身可以返回更多方法,这些方法充当对象方法,也可以访问这些变量。假设未修改变量,则保持参照透明度。

4 回答

  • 3

    闭包的一个很好的用途是构建决策树之类的东西。您返回一个 classify()函数,该函数测试是否向左或向下树,然后根据输入数据调用其 leftClassify()或 rightClassify()函数。叶函数只返回一个类标签。我以前用 Python 和 D 实际上实现了决策树。

  • 6

    我在 Javascript 代码中使用了大量的闭包(这是一种非常实用的语言 - 我开玩笑说它是带有 C 服装的 Scheme)。它们提供了对函数私有的数据封装。

    最无处不在的例子:

    var generateId = function() {
        var id = 0;
        return function() {
            return id++;
        }
    }();
    window.alert(generateId());
    window.alert(generateId());
    

    但那是 Javascript 关闭的问候世界。然而,还有更多的实际用途。

    最近,在我的工作中,我需要用滑块编写一个简单的照片库。它做的事情如下:

    var slide = function() {
        var photoSize = ...
        var ... // lots of calculations of sizes, distances to scroll, etc
        var scroll = function(direction, amout) {
            // here we use some of the variables defined just above
            // (it will be returned, therefore it is a closure)
        };
        return {
            up: function() { scroll(1, photoSize); },
            down: function() { scroll(-1, photoSize); }
        }
    }();
    
    slide.up();
    // actually the line above would have to be associated to some
    // event handler to be useful
    

    在这种情况下,我使用闭包来隐藏所有向上和向下滚动逻辑,并且有一个非常语义的代码:在 Javascript 中,“向上滑动”你会写slide.up()

  • 3

    它们被用于很多事情。以功能组成为例:

    let compose f g = fun x -> f (g x)
    

    这将返回一个闭包,该闭包使用创建它的函数环境中的参数。像 OCaml 和 Haskell 这样的函数语言实际上隐含地使用了闭包。例如:

    let flip f a b = f b a
    

    通常,这将被称为类似let minusOne = flip (-) 1的东西,以创建一个将从其参数中减去 1 的函数。这种“部分应用”功能实际上与执行此操作相同:

    let flip f a = fun b -> f b a
    

    它返回一个闭包,它记住你传入的两个参数并获取它自己的另一个参数。

  • 1

    闭包可用于模拟可响应消息并维护其自身本地状态的对象。这是 Scheme 中的一个简单的计数器对象:

    ;; counter.ss
    ;; A simple counter that can respond to the messages
    ;; 'next and 'reset.  
    
    (define (create-counter start-from)
      (let ((value start-from))
        (lambda (message)
          (case message
        ((next) (set! value (add1 value)) value)
        ((reset) (set! value start-from))
        (else (error "Invalid message!"))))))
    

    样品用法:

    > (load "counter.ss")
    > (define count-from-5 (create-counter 5))
    > (define count-from-0 (create-counter 0))
    > (count-from-5 'next)
    6
    > (count-from-5 'next)
    7
    > (count-from-0 'next)
    1
    > (count-from-0 'next)
    2
    > (count-from-0 'reset)
    > (count-from-0 'next)
    1
    

相关问题