我正在尝试将常规函数转换为curry函数,但获取Execution was interrupted
下面是我正在编写函数并执行unsafeBitCast以使用一个参数调用函数并稍后使用第二个参数调用它的代码。
func curry<T>(f: (T, T) -> T) -> T -> T -> T {
return { a in
typealias Function = (T) -> (T -> T)
let fn = unsafeBitCast(f, Function.self)
return curry(fn(a))
}
}
func curry<T>(f: T -> T) -> T -> T {
return { f($0) } // Throws Runtime Exception
}
func adder(x: Int, y: Int) -> Int {
return x + y
}
let adderCurry = curry(adder)
let add1 = adderCurry(1)
add1(2)
有谁知道如何将具有两个或更多参数的常规函数转换为咖喱函数
func add(x: Int)(y: Int) -> Int {
return x + y
}
编辑:此示例也不起作用
func curry<T>(f: (T, T) -> T) -> T -> T -> T {
typealias Function = T -> T -> T
return unsafeBitCast(f, Function.self)
}
func adder(x: Int, y: Int) -> Int {
return x + y
}
let adderCurry = curry(adder)
let add1 = adderCurry(1)
add1(2)
答案 0 :(得分:2)
你没有对它进行类型转换,你返回依次捕获每个参数的嵌套闭包:
func add(x: Int, y: Int) -> Int {
return x + y
}
func curry<T1, T2, T3>(f: (T1, T2) -> T3) -> T1 -> T2 -> T3 {
return {
(t1: T1) -> T2 -> T3 in
return {
(t2: T2) -> T3 in
return f(t1, t2)
}
}
}
let curriedAdd = curry(add)
let add3 = curriedAdd(3)
println(add3(5))
// 8
这更简洁:
func curry<T1, T2, T3>(f: (T1, T2) -> T3) -> T1 -> T2 -> T3 {
return { t1 in { t2 in f(t1, t2) } }
}
我觉得写一个咖喱制作者会很有趣;在这里 - 如果有人知道如何使其中一个产生一个令人惊奇的实际功能:
func curryRecipe(n: Int) -> String {
let types = join(", ", map(1...n, { "T\($0)" }))
let returnType = join(" -> ", map(1...n, { "T\($0)" }))
let closures = join(" in ", map(1...n, { "{ t\($0)" }))
let braces = join(" ", Array(count: n, repeatedValue: "}"))
return "func curry<\(types), R>(f: (\(types)) -> R) -> \(returnType) -> R {\r" +
" return \(closures) in f(\(types.lowercaseString)) \(braces)\r}"
}
println(curryRecipe(15))
输出:
func curry<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, R>(f: (T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15) -> R) -> T1 -> T2 -> T3 -> T4 -> T5 -> T6 -> T7 -> T8 -> T9 -> T10 -> T11 -> T12 -> T13 -> T14 -> T15 -> R {
return { t1 in { t2 in { t3 in { t4 in { t5 in { t6 in { t7 in { t8 in { t9 in { t10 in { t11 in { t12 in { t13 in { t14 in { t15 in f(t1, t2, t3, t4, t5, t6, t7, t8, t9, t10, t11, t12, t13, t14, t15) } } } } } } } } } } } } } } }
}
答案 1 :(得分:0)
对于任何有兴趣的人,答案是没有办法将正常功能强制转换为咖喱功能,但我解决问题的方法是通过Nate Cook在上面的答案中提出的黑客攻击。这可以用于任何希望动态生成新代码并将其添加到项目中的人,因为Swift因静态类型而不支持某些内容。如果您愿意,也可以手动预处理文件,并在构建文件之前替换它们,并在后期处理中撤消预处理操作或生成已编译的新代码文件。
我在Xcode中创建了一个Pre Build脚本,它运行一个ruby脚本,为2个或更多参数生成咖喱函数,最多10个。ruby脚本是可配置的,但它会生成一个AutoCurry.swift文件,该文件包含在项目中并编译成库代码。例如,此ruby脚本https://github.com/ankurp/Dollar.swift/blob/master/Dollar/gen_auto_curry.rb在构建之前生成此文件https://github.com/ankurp/Dollar.swift/blob/master/Dollar/Dollar/AutoCurry.swift。