- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
所以从我个人的研究来看,闭包/柯里化(Currying)似乎或多或少是完全相同的东西,这不可能是明显正确的。那么区别在哪里呢?
所以这是一个 Racket 中的闭包示例:
(define (make-an-adder x)
(lambda (y)
(+ y x)))
(define add3 (make-an-adder 3))
(add3 5)
会回馈
8
那么柯里化(Currying)的区别在哪里呢?因为如果我查找文档和其他示例,它们似乎与我为闭包展示的完全相同?
先谢谢大家了!
最佳答案
所以它们是不同的概念,但都与嵌套的 lambda 相关。
闭包可以由引用在自身外部定义的变量的 lambda 创建,并且当 lambda 从定义外部变量的上下文中转义时最为重要。闭包的工作是确保在 lambda 转义上下文时保留变量。
Curried 函数是一种可以在多个步骤或多个不同的函数应用程序中获取其参数的函数。这通常意味着 lambda 嵌套在 lambda 中。
大多数有用的柯里化(Currying)函数都需要使用闭包,但如果内部 lambda 忽略外部参数,它们就不是闭包。一个简单的例子:
(define (curried-ignore-first ignored)
(lambda (y) y))
这不是闭包,因为内部 lambda (lambda (y) y)
已经关闭:它不引用自身以外的任何变量。
柯里化(Currying)函数并不总是需要忽略外部参数...它只需要在返回内部 lambda 之前处理它们,这样内部 lambda 就不会引用外部参数。一个简单的例子是柯里化(Currying)的 choose
函数。 choose
的“正常”定义确实使用了闭包:
(define (choose b)
(lambda (x y)
(if b x y))) ; inner lambda refers to `b`, so it needs a closure
但是,如果 if b
放在外层 lambda 之外,我们就可以避免闭包:
(define (choose b)
(if b
(lambda (x y) x) ; not closures, just nested lambdas
(lambda (x y) y)))
当内部 lambda 引用外部上下文中的变量并可能转义该上下文时,需要闭包。外部上下文通常是函数或 lambda,但不一定是。它可以是一个让:
(define closure-with-let
(let ([outer "outer"])
(lambda (ignored) outer))) ; closure because it refers to `outer`
这是一个闭包,但不是柯里化(Currying)的例子。
原题中的例子是产生闭包的柯里化(Currying)函数
(define (make-an-adder x)
(lambda (y)
(+ y x)))
如果你想制作一个仍然是具有相同行为的柯里化(Currying)函数的版本,但在某些特殊情况下不需要对 x
进行闭包,你可以在 lambda 之前分支:
(define (make-an-adder x)
(match x
[0 identity]
[1 add1]
[-1 sub1]
[2 (lambda (y) (+ y 2))]
[3 (lambda (y) (+ y 3))]
[_ (lambda (y) (+ y x))]))
这避免了为 x
是一个精确的整数 -1 到 3 的情况产生一个闭包,但仍然在 x
的所有其他情况下产生一个闭包。如果您将 x
的域限制为一个有限集,您可以将它变成一个不需要闭包的函数,只需枚举所有情况即可。
如果您不想对 x
进行闭包,但对其他事情进行闭包也无妨,您可以使用递归和组合来构造一个不会对结束进行闭包的输出函数x
:
(define (make-an-adder x)
(cond [(zero? x) identity]
[(positive-integer? x)
(compose add1 (make-an-adder (sub1 x)))]
[(negative-integer? x)
(compose sub1 (make-an-adder (add1 x)))]))
请注意,这仍然会产生闭包(因为 compose
在其参数上创建闭包),但它产生的函数不会在 x
上关闭。一旦这个版本的 make-an-adder
产生了它的结果,它就“完成”了处理 x
并且不需要再关闭它。
关于functional-programming - Racket - Closure/Currying,区别在哪里?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62499789/
export const postMoviePopular = url = dispatch => { const data = axios.get(url); dispatch(sa
我一直在学习 Haskell 中的柯里化(Currying),现在尝试以柯里化(Currying)形式编写函数的 Haskell 类型签名,其非柯里化(Currying)形式有一个 (x, y) 类型
在许多列表处理语言(以及其他语言)中,它们都有一个名为 curry 的函数,它可以完成一些巧妙的事情。我的问题是为什么他们称之为 curry ?这个名字从何而来?我唯一的猜测是来自世界各国的美味 cu
当前的 curry 函数采用接受 2 个元素的元组的函数,并允许对结果函数进行 curry 或部分应用。 let x = curry (\(x, y) -> x + y) x 1 2 -- 3 是否可
假设我有 library(functional) f = function(x, p) { x^p } f2 = Curry(f, p=2) 有没有办法找出仅给定 f2 的 p 被设置为什么? 最佳答
我试图了解柯里化(Currying)相对于 Scala 中部分应用程序的优势。请考虑以下代码: def sum(f: Int => Int) = (a: Int, b: Int) => f(a)
我有一个函数,我必须包装另一个函数(如果它存在)或替换它(如果它不存在)。这意味着参数的数量会根据情况而变化。 这就是我的意思- 列列表: const myColumns = [ {name:
我不明白为什么在无类型的 lambda 演算中允许以下 beta 减少: (λx.x y) (u v) -> ((u v) y) 具体来说,我无法理解如何传递两个参数 u和 v到单个参数 x在 λx.
Ruby 1.9's built in support of currying支持两种处理带有任意数量参数的过程的方法: my_proc = proc {|*x| x.max } 1) curry 没
根据下面的代码片段,example-func-A 和 example-func-B 之间是否存在任何有意义的区别? #lang racket/base (require (only-in racket
我是 JavaScript 的新手,试图理解 Oreilly JavaScript Cookbook 中有关柯里化(Currying)的教程。 谁能用通俗易懂的语言逐步详细解释这个程序。请务必解释在程
所以我知道你可以: > f = map (+1) > f [1,2,3] [2,3,4] 但是,如果您这样做会怎样: > g = map (+) [1,2,3] > :t g g :: Num a =
我在多篇文章和博客中看到过对柯里化(Currying)函数的引用,但我找不到一个好的解释(或者至少是一个有意义的解释!) 最佳答案 柯里化(Currying)是指将一个接受多个参数的函数分解为一系列函
所以我在我们的教科书中经过一些反复试验和研究后得到了以下功能,我可以想出一个解决方案。 def prodC1(f : Int => Int) : (Int, Int) => Int = { def
我有问题,可以简化为以下示例: let func a b c = printf "%s %s %s" a b c let partial = func "a" let something_that_r
今天开始学习 Scala,我很好奇你是否可以重载一个函数来添加柯里化(Currying),比如: def add(x: Int, y: Int): Int = x + y def add(x: Int
我正在尝试编写柯里化(Currying)函数的策略,包括通用量化函数。 Require Import Coq.Program.Tactics. Definition curry1 := forall
我想以某种方式组合函数。请在伪代码(不是 F#)中考虑这两个函数 F1 = x + y F2 = F1 * 10 // note I did not specify arguments for F1,
在 Perl 6 世界中,currying 是表示部分实例化的通用术语,它也用于 (parametrized) roles 的世界。 . 但是,尚不清楚如何实际使用它: role Zipi[::T]
我想知道是否可以在多参数组函数上使用柯里化(Currying): scala> def sum(a: Int)(b: Int): Int = { a+b } sum: (a: Int)(b: Int)
我是一名优秀的程序员,十分优秀!