Go prend-il en charge les expressions lambda ou similaires?
Je souhaite porter une bibliothèque d'un autre langage utilisant les expressions lambda (Ruby).
Voici un exemple , copié et collé avec soin:
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());
}
Les expressions Lambda sont également appelées littéraux de fonction. Go les soutient complètement.
Voir les spécifications de langue: http://golang.org/ref/spec#Function_literals
Voir un code-walk, avec des exemples et une description: http://golang.org/doc/codewalk/functions/
Oui
En programmation informatique, une fonction anonyme ou une abstraction lambda (littéral de fonction) est une définition de fonction qui n'est pas liée à un identificateur, et Go supporte les fonctions anonymes , qui peuvent former des fermetures. Les fonctions anonymes sont utiles lorsque vous souhaitez définir une fonction en ligne sans avoir à le nommer.
package main
import "fmt"
func intSeq() func() int {
i := 0
return func() int {
i += 1
return i
}
}
func main() {
nextInt := intSeq()
fmt.Println(nextInt())
fmt.Println(nextInt())
fmt.Println(nextInt())
newInts := intSeq()
fmt.Println(newInts())
}
function intSeq renvoie une autre fonction, que nous définissons de manière anonyme dans le corps d'intSeq. La fonction retournée se ferme sur la variable i pour former une fermeture .
Output
$ go run closures.go
1
2
3
1
Le golang ne semble pas faire d’expressions lambda, mais vous pouvez utiliser une fonction anonyme littérale, j’ai écrit quelques exemples lorsque j’étudiais en comparant l’équivalent en JS.
func() string {
return "some String Value"
}
//Js similar: () => 'some String Value'
func(arg string) string {
return "some String" + arg
}
//Js similar: (arg) => "some String Value" + arg
func() {
fmt.Println("Some String Value")
}
//Js similar: () => {console.log("Some String Value")}
func(arg string) {
fmt.Println("Some String " + arg)
}
//Js: (arg) => {console.log("Some String Value" + arg)}
Oui, mais c’est une expression lambda dans sa forme la plus complète, les fermetures et tout. Toutefois, vous n’obtenez pas d’inférence de type avec les littéraux de fonction!
Un exemple qui n’a pas encore été fourni et que je cherchais consiste à affecter directement des valeurs à variable/s à partir d’une fonction anonyme, par exemple.
test1, test2 := func() (string, string) {
x := []string{"hello", "world"}
return x[0], x[1]
}()
Remarque: vous avez besoin des crochets ()
à la fin de la fonction pour l'exécuter et renvoyer les valeurs, sinon seule la fonction est renvoyée et génère une erreur assignment mismatch: 2 variable but 1 values
.
Voici un exemple que je cherchais - comment passer directement une fonction anonyme à un rappel vers une autre fonction.
Supposons que nous ayons une fonction filter
qui prend une valeur de type slice of int et un rappel qui sert de fonction de prédicat pour filtrer les valeurs (les valeurs qui passent le contrôle de prédicat sont renvoyées)
func filter(xi []int, predicate func(v int) bool) []int {
filtered := []int{}
for _, x := range xi {
if predicate(x) {
filtered = append(filtered, x)
}
}
return filtered
}
Maintenant, si nous avons une tranche d’ints [1, 2, 3, 4]
et que nous voulons obtenir une valeur paire, nous pouvons définir la fonction isEven
au préalable avec la signature func isEven(x int) bool
et lui transmettre le second argument de la fonction filter
fonction mais nous pouvons également intégrer cette fonction de cette manière
even := filter(xi, func(x int) bool { return x%2 == 0 })
Notez que nous devons toujours spécifier les types d'arguments de la fonction ainsi que les types de valeurs renvoyées.
Juste pour référence, la ligne de code ci-dessus est équivalente à
func isEven(x int) bool {
return x%2 == 0
}
even := filter(xi, isEven)
Oui, car il s’agit d’un langage entièrement fonctionnel, mais n’a pas de grosse flèche (=>) ni de fine flèche (->) comme le signe lambda habituel, et utilise le mot clé func par souci de clarté et de simplicité.