51 votes

Fonctions de première classe en Go

Je viens de JavaScript, qui dispose d'un soutien fonctionnel de premier ordre. Par exemple, vous pouvez :

  • passer une fonction comme paramètre à une autre fonction
  • retourner une fonction à partir d'une fonction.

Quelqu'un peut-il me donner un exemple de la façon dont je ferais cela en Go ?

41voto

RC. Points 18567

Langage Go et programmation fonctionnelle pourrait aider. Extrait de cet article de blog :

package main
import fmt "fmt"
type Stringy func() string
func foo() string{
        return "Stringy function"
}
func takesAFunction(foo Stringy){
    fmt.Printf("takesAFunction: %v\n", foo())
}
func returnsAFunction()Stringy{
    return func()string{
        fmt.Printf("Inner stringy function\n");
        return "bar" // have to return a string to be stringy
    }
}
func main(){
    takesAFunction(foo);
    var f Stringy = returnsAFunction();
    f();
    var baz Stringy = func()string{
        return "anonymous stringy\n"
    };
    fmt.Printf(baz());
}

L'auteur est le propriétaire du blog : Dethe Elza (pas moi)

27voto

Oscar Riveros Points 181
package main

import (
    "fmt"
)

type Lx func(int) int

func cmb(f, g Lx) Lx {
    return func(x int) int {
        return g(f(x))
    }
}

func inc(x int) int {
    return x + 1
}

func sum(x int) int {
    result := 0

    for i := 0; i < x; i++ {
        result += i
    }

    return result
}

func main() {
    n := 666

    fmt.Println(cmb(inc, sum)(n))
    fmt.Println(n * (n + 1) / 2)
}

de la production :

222111
222111

6voto

icza Points 3857

La section correspondante de la spécification : Types de fonctions .

Toutes les autres réponses ici déclarent d'abord un nouveau type, ce qui est bien (pratique) et rend votre code plus facile à lire, mais sachez que ce n'est pas une obligation.

Vous pouvez travailler avec des valeurs de fonction sans déclarer un nouveau type pour elles, comme le montre l'exemple ci-dessous.

Déclarer une variable de type fonction qui a 2 paramètres de type float64 et possède une valeur de retour de type float64 ressemble à ceci :

// Create a var of the mentioned function type:
var f func(float64, float64) float64

Écrivons une fonction qui renvoie une fonction additionnelle. Cette fonction additionneuse doit prendre 2 paramètres de type float64 et doit renvoyer la somme de ces deux nombres lorsqu'il est appelé :

func CreateAdder() func(float64, float64) float64 {
    return func(x, y float64) float64 {
        return x + y
    }
}

Ecrivons une fonction qui a 3 paramètres, les 2 premiers étant de type float64 et le troisième étant une valeur de fonction, une fonction qui prend 2 paramètres d'entrée de type float64 et produit une valeur de float64 type. Et la fonction que nous écrivons appellera la valeur de la fonction qui lui est passée en paramètre, et en utilisant les 2 premiers float64 comme arguments pour la valeur de la fonction, et renvoie le résultat que la valeur de la fonction transmise renvoie :

func Execute(a, b float64, op func(float64, float64) float64) float64 {
    return op(a, b)
}

Voyons les exemples précédents en action :

var adder func(float64, float64) float64 = CreateAdder()
result := Execute(1.5, 2.5, adder)
fmt.Println(result) // Prints 4

Notez que vous pouvez bien sûr utiliser la fonction Déclaration de variable courte lors de la création adder :

adder := CreateAdder() // adder is of type: func(float64, float64) float64

Essayez ces exemples sur le site Go Playground .

Utilisation d'une fonction existante

Bien sûr, si vous avez déjà une fonction déclarée dans un paquet avec le même type de fonction, vous pouvez l'utiliser aussi.

Par exemple, le math.Mod() a le même type de fonction :

func Mod(x, y float64) float64

Vous pouvez donc transmettre cette valeur à notre Execute() fonction :

fmt.Println(Execute(12, 10, math.Mod)) // Prints 2

Impressions 2 parce que 12 mod 10 = 2 . Notez que le nom d'une fonction existante fait office de valeur de fonction.

Essayez-le sur le Go Playground .

Remarque :

Notez que les noms des paramètres ne font pas partie du type, le type de 2 fonctions ayant les mêmes types de paramètres et de résultats est identique quels que soient les noms des paramètres. Mais sachez que dans une liste de paramètres ou de résultats, les noms doivent être soit tous présents, soit tous absents.

Ainsi, par exemple, vous pouvez également écrire :

func CreateAdder() func(P float64, Q float64) float64 {
    return func(x, y float64) float64 {
        return x + y
    }
}

O:

var adder func(x1, x2 float64) float64 = CreateAdder()

5voto

jorelli Points 2494

Également ce billet : Types de fonctions en Go

4voto

Drew LeSueur Points 2507

Voir également ce message sur le groupe Google : Programmation fonctionnelle

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X