Как можно пойти карри?
В функциональном программировании нравится Haskell, я могу определить функцию
add a b = a+b
Затем add 3
вернет функцию, которая принимает один параметр и вернет 3 + something
Как я могу сделать это в GO?
Когда я определяю функцию, которая принимает более одного (скажем n) параметров, могу ли я дать только один параметр и получить другую функцию, которая принимает n-1 параметров?
Обновление
Извините за неточные слова в моем исходном вопросе.
Я думаю, что мой вопрос должен задаваться как два вопроса:
- Есть ли частичное приложение в GO?
- Как GO выполняет функцию карри?
Спасибо TheOnly92 и Alex за решение моего второго вопроса. Однако мне также интересен первый вопрос.
Ответы
Ответ 1
Чтобы расширить предыдущий ответ, который позволяет принимать произвольное количество аргументов:
package main
import (
"fmt"
)
func mkAdd(a int) func(...int) int {
return func(b... int) int {
for _, i := range b {
a += i
}
return a
}
}
func main() {
add2 := mkAdd(2)
add3 := mkAdd(3)
fmt.Println(add2(5,3), add3(6))
}
Ответ 2
Возможно, что-то вроде
package main
import (
"fmt"
)
func mkAdd(a int) func(int) int {
return func(b int) int {
return a + b
}
}
func main() {
add2 := mkAdd(2)
add3 := mkAdd(3)
fmt.Println(add2(5), add3(6))
}
Ответ 3
Вы можете сделать еще один шаг, указав тип функции, а затем добавив к ней метод.
package main
import "fmt"
type Add func(int, int) int
func (f Add) Apply(i int) func(int) int {
return func(j int) int {
return f(i, j)
}
}
func main() {
var add Add = func(i, j int) int { return i + j }
add3 := add.Apply(3)
fmt.Println("add 3 to 2:", add3(2))
}
Вы даже можете попробовать с вариационными функциями:
package main
import "fmt"
type Multiply func(...int) int
func (f Multiply) Apply(i int) func(...int) int {
return func(values ...int) int {
values = append([]int{i}, values...)
return f(values...)
}
}
func main() {
var multiply Multiply = func(values ...int) int {
var total int = 1
for _, value := range values {
total *= value
}
return total
}
var times2 Multiply = multiply.Apply(2)
fmt.Println("times 2:", times2(3, 4), "(expect 24)")
// ... and you can even cascade (if assigned the Multiply type)
times6 := times2.Apply(3)
fmt.Println("times 6:", times6(2, 3, 5, 10), "(expect 1800)")
}
Надеюсь, это поможет!