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

发布于 2024-08-17 20:55:20 字数 498 浏览 4 评论 0原文

出于某种原因,我倾向于将闭包与函数式语言联系起来。我相信这主要是因为我所看到的有关闭包的讨论几乎总是在围绕函数式编程的环境中进行。话虽这么说,我能想到的闭包的实际实际用途本质上都是非功能性的。

函数式语言中是否有闭包的实际用途,或者我认为这种关联主要是因为闭包用于以函数式编程语言(一等函数、柯里化等)也常见的风格进行编程?

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

编辑:添加迄今为止已发布内容的摘要:

  1. 闭包用于实现部分评估。具体来说,对于采用两个参数的函数,可以使用一个参数调用它,这会导致它返回一个采用一个参数的函数。一般来说,第二个函数“存储”传递给它的第一个值的方法是闭包。
  2. 对象可以使用闭包来实现。返回一个函数,该函数封闭了许多变量,然后可以像对象属性一样使用它们。函数本身可能会返回更多方法,这些方法充当对象方法,也可以访问这些变量。假设变量没有被修改,引用透明度就得以保持。

For some reason, I tend to associate closures with functional languages. I believe this is mostly because the discussions I've seen concerning closures is almost always in an environment that is focused around functional programming. That being said, the actual practical uses of closures that I can think are are all non-functional in nature.

Are there practical uses of closures in functional languages, or is the association in my mind mostly because closures are used to program in a style that's also common to functional programming languages (first class functions, currying, etc)?

Edit: I should clarify that I refering to actual functional languages, meaning I was looking for uses that preserve referential transparency (for the same input you get the same output).

Edit: Adding a summary of what's been posted so far:

  1. Closures are used to implement partial evaluation. Specifically, for a function that takes two arguments, it can be called with one argument which results in it returning a function that takes one argument. Generally, the method by which this second function "stores" the first value passed into it is a closure.
  2. Objects can be implemented using closures. A function is returned that has closes around a number of variables, and can then use them like object attributes. The function itself may return more methods, which act as object methods, which also have access to these variables. Assuming the variables aren't modified, referential transparency is maintained.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

撩动你心 2024-08-24 20:55:20

我在 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()

I use lots of closures in Javascript code (which is a pretty functional language -- I joke that it is Scheme with C clothing). They provide encapsulation of data that is private to a function.

The most ubiquitous example:

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

But that's the hello, world of Javascript closures. However there are many more practical uses.

Recently, in my job, I needed to code a simple photo gallery with sliders. It does something like:

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

In this case I've used closures to hide all the up and down scrolling logic, and have a code which is very semantic: in Javascript, "slide up" you will write slide.up().

染墨丶若流云 2024-08-24 20:55:20

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

One nice use for closures is building things like decision trees. You return a classify() function that tests whether to go down the left or right tree, and then calls either its leftClassify() or rightClassify() function depending on the input data. The leaf functions simply return a class label. I've actually implemented decision trees in Python and D this way before.

Oo萌小芽oO 2024-08-24 20:55:20

它们用于很多事情。以函数组合为例:

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

它返回一个闭包,该闭包会记住您传入的两个参数并采用自己的另一个参数。

They're used for a lot of things. Take, for example, function composition:

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

This returns a closure that uses the arguments from the function environment where it was created. Functional languages like OCaml and Haskell actually use closures implicitly all over the place. For example:

let flip f a b = f b a

Usually, this will be called as something like let minusOne = flip (-) 1 to create a function that will subtract 1 from its argument. This "partially applied" function is effectively the same as doing this:

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

It returns a closure that remembers the two arguments you passed in and takes another argument of its own.

落在眉间の轻吻 2024-08-24 20:55:20

闭包可用于模拟可以响应消息并维护自己的本地状态的对象。这是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

Closures can be used to simulate objects that can respond to messages and maintain their own local state. Here is a simple counter object in 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!"))))))

Sample usage:

> (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
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文