Phi*_*yfi 29 lisp scheme haskell functional-programming currying
有很多关于如何理解函数的教程,以及stackoverflow中的许多问题.然而,在阅读了The Little Schemer,几本书,教程,博客文章和stackoverflow主题之后,我仍然不知道这个简单问题的答案:"有什么关系?" 我明白如何理解一个功能,而不是"为什么?" 在它背后.
有人可以向我解释一下curried函数的实际用法(在每个函数只允许一个参数的语言之外,使用currying的必要性当然非常明显.)
编辑:考虑到TLS的一些例子,有什么好处
(define (action kind)
(lambda (a b)
(kind a b)))
Run Code Online (Sandbox Code Playgroud)
而不是
(define (action kind a b)
(kind a b))
Run Code Online (Sandbox Code Playgroud)
我只能看到更多的代码,没有更多的灵活性......
Yas*_*aev 24
curried函数的一个有效用途是减少代码量.
考虑三个函数,其中两个几乎相同:
(define (add a b)
(action + a b))
(define (mul a b)
(action * a b))
(define (action kind a b)
(kind a b))
Run Code Online (Sandbox Code Playgroud)
如果你的代码调用add,它依次调用action与实物+.同样的mul.
您定义了这些函数,就像您在许多命令式流行语言中所做的那样(其中一些已经包括lambdas,currying和其他通常在功能世界中发现的功能,因为它们都非常方便).
All addand sumdo,action用适当的方式包含调用kind.现在,考虑这些函数的curried定义:
(define add-curried
((curry action) +))
(define mul-curried
((curry action) *))
Run Code Online (Sandbox Code Playgroud)
它们变得相当短.我们只是action通过传递一个参数来调整函数kind,并且得到了接受其余两个参数的curried函数.
这种方法允许您编写更少的代码,具有高级别的可维护性.
试想一下,函数action会立即被重写以接受另外三个参数.没有currying你将不得不重写你的实现add和mul:
(define (action kind a b c d e)
(kind a b c d e))
(define (add a b c d e)
(action + a b c d e))
(define (mul a b c d e)
(action * a b c d e))
Run Code Online (Sandbox Code Playgroud)
但是,currying使你免于那些令人讨厌且容易出错的工作; 你不必重写的功能,甚至一个符号add-curried,并mul-curried在所有的,因为调用函数将提供传递给参数的必要量action.
Bil*_*ill 11
它们可以使代码更易于阅读.考虑以下两个Haskell代码段:
lengths :: [[a]] -> [Int]
lengths xs = map length xs
lengths' :: [[a]] -> [Int]
lengths' = map length
Run Code Online (Sandbox Code Playgroud)
为什么要给你不会使用的变量命名?
Curried函数也有助于这样的情况:
doubleAndSum ys = map (\xs -> sum (map (*2) xs) ys
doubleAndSum' = map (sum . map (*2))
Run Code Online (Sandbox Code Playgroud)
删除这些额外的变量使代码更容易阅读,并且您无需在心理上清楚地知道x是什么以及y是什么.
HTH.