首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Swift中的Curry函数

Swift中的Curry函数
EN

Stack Overflow用户
提问于 2014-06-08 14:36:01
回答 4查看 2.9K关注 0票数 11

我想做一个函数,返回一个咖喱函数,如下所示

代码语言:javascript
复制
func addTwoNumbers(a: Int)(b: Int) -> Int {
    return a + b
}

addTwoNumbers(4)(b: 6) // Result: 10

var add4 = addTwoNumbers(4)
add4(b: 10) // returns 14     

这类函数的返回类型是什么,我如何使用使用变量参数的函数生成这样的函数。

代码语言:javascript
复制
func generateCurry(.../*Variadic parameters*/) -> .../*curry function type*/ {
  return ...//curry function
}

我想要一个通用的解决方案,而不是仅以Int作为参数,在generateCurry函数的参数中

代码语言:javascript
复制
let curried = curry(func(a, b, c) {
  print(a + b + c)
})
curried(1)(2)(3) //prints 6
EN

回答 4

Stack Overflow用户

回答已采纳

发布于 2014-08-19 03:16:06

通过闭包,您可以很容易地做到这一点:

代码语言:javascript
复制
/// Takes a binary function and returns a curried version
func curry<A,B,C>(f: (A, B) -> C) -> A -> B -> C {
    return { a in { b in f(a, b) } }
}

curry(+)(5)(6) // => 11

let add: Int -> Int -> Int = curry(+)
add(5)(6) // => 11

如果能够对包含3、4或更多参数的函数执行相同的操作,但不重复实现,那就太好了。这样一个函数的签名可能会启动如下内容:

代码语言:javascript
复制
/// Take a function accepting N arguments and return a curried version
func curry<T>(args: T...) -> /* ? */

返回类型是什么?它将根据对函数的输入进行更改。这在Swift目前是不可能的,如果没有某种宏观系统,我认为这是不可能的。但是,即使使用宏,我也不认为编译器会满意,除非它在编译时知道列表的长度。

话虽如此,使用接受3、4、5或更多参数的版本手动重载运行函数确实是一种直截了当的做法:

代码语言:javascript
复制
func curry<A,B,C,D>(f: (A, B, C) -> D) -> A -> B -> C -> D {
    return { a in { b in { c in f(a,b,c) } } }
}

func curry<A,B,C,D,E>(f: (A, B, C, D) -> E) -> A -> B -> C -> D -> E {
    return { a in { b in { c in { d in f(a,b,c,d) } } } }
}

// etc.
票数 15
EN

Stack Overflow用户

发布于 2014-06-08 14:45:19

我不确定这是否真的会像Python这样的语言中的方式一样成为可能。

我看到有一个通用解决方案的核心问题是要接受的闭包/函数的强类型。

您可以相当容易地创建一个用于特定或通用函数签名的curry函数,但就一般用途咖喱而言,我看不到它的工作方式。问题不仅仅在于论点的类型(如评论中提到的那样),还包括它们的数量。

我编写了一个简单的例子,说明如何实现curry函数。它可以工作,但我不认为有一个明智的方式,有一个真正的通用的,你可以在更松散的类型的语言。

代码语言:javascript
复制
func add(a1: Int, a2: Int) -> Int {
    return a1 + a2
}

func curry(argument: Int, block: (Int, Int) -> Int) -> Int -> Int{
    func curried(arg: Int) -> Int {
        return block(argument, arg)
    }

    return curried
}

curry(5, add)(6)
票数 1
EN

Stack Overflow用户

发布于 2017-01-24 09:10:26

如果您想要快速获得任意数量的参数的curry函数,就可以生成它,如这个要旨所示。

代码在SWIFT2.2中,并为SWIFT2.2生成代码(目前)。它使用简单的基于模板的方法(一种可能的替代方法是构建AST,然后进行代码生成):

代码语言:javascript
复制
func genCurry(n: Int, indent: Indent = .fourSpaces, accessLevel: AccessLevel = .Default, verbose: Bool = false) -> String {

    // ...
    // The bulky park is skipped for clarity.

    return accessLevel.asPrefix + "func curry<\(genericParams)>(f: \(fSig)) -> \(curriedSig(n)) {\n"
        + indent.single + "return \(closure)\n"
        + "}\n"
}
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/24107191

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档