web-dev-qa-db-fra.com

Pourquoi Go n'autorise-t-il pas les déclarations de fonctions imbriquées (fonctions à l'intérieur des fonctions)?

Edit: Si ce n'était pas clair ce que je demandais: quels sont les problèmes qui sont atténués en n'autorisant pas les déclarations de fonctions imbriquées? =

Les Lambdas fonctionnent comme prévu:

func main() {
    inc := func(x int) int { return x+1; }
}

Cependant, la déclaration suivante à l'intérieur d'une déclaration n'est pas autorisée:

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

Pour quelle raison les fonctions imbriquées ne sont-elles pas autorisées?

67
corazza

Je pense qu'il y a 3 raisons pour lesquelles cette fonctionnalité évidente n'est pas autorisée

  1. Cela compliquerait légèrement le compilateur. Pour le moment, le compilateur sait que toutes les fonctions sont au niveau supérieur.
  2. Cela créerait une nouvelle classe d'erreur de programmation - vous pourriez refactoriser quelque chose et imbriquer accidentellement certaines fonctions.
  3. Avoir une syntaxe différente pour les fonctions et les fermetures est une bonne chose. Faire une fermeture est potentiellement plus cher que de faire une fonction, vous devez donc savoir que vous le faites.

Ce ne sont que mes opinions - je n'ai pas vu de déclaration officielle des concepteurs de la langue.

45
Nick Craig-Wood

Bien sûr qu'ils le sont. Il suffit de les affecter à une variable:

func main() {
    inc := func(x int) int { return x+1; }
}
24
Matt Williamson

Foire aux questions (FAQ)

Pourquoi Go n'a-t-il pas la fonctionnalité X?

Chaque langue contient de nouvelles fonctionnalités et omet la fonctionnalité préférée de quelqu'un. Go a été conçu en tenant compte de la félicité de la programmation, de la vitesse de compilation, de l'orthogonalité des concepts et de la nécessité de prendre en charge des fonctionnalités telles que la concurrence et la récupération de place. Votre fonctionnalité préférée peut être manquante car elle ne convient pas, car elle affecte la vitesse de compilation ou la clarté de la conception, ou parce qu'elle rendrait le modèle de système fondamental trop difficile.

Si cela vous dérange que la fonctionnalité X manque à Go, veuillez nous pardonner et enquêter sur les fonctionnalités de Go. Vous constaterez peut-être qu'ils compensent de manière intéressante le manque de X.

Qu'est-ce qui justifierait la complexité et le coût de l'ajout de fonctions imbriquées? Que voulez-vous faire que vous ne puissiez pas faire sans fonctions imbriquées? Etc.

22
peterSO

Voici un moyen d'implémenter des fonctions imbriquées et des fonctions dans des fonctions imbriquées

package main

    import "fmt"

    func main() {
        nested := func() {
            fmt.Println("I am nested")

            deeplyNested := func() {
                fmt.Println("I am deeply nested")
            }

            deeplyNested()
        }

        nested()
    }
12
Koala3

Les fonctions imbriquées sont autorisées dans Go. Il vous suffit de les affecter à des variables locales dans la fonction externe et de les appeler à l'aide de ces variables.

Exemple:

func outerFunction(iterations int, s1, s2 string) int {
    someState := 0
    innerFunction := func(param string) int {
        // Could have another nested function here!
        totalLength := 0
        // Note that the iterations parameter is available
        // in the inner function (closure)
        for i := 0; i < iterations; i++) {
            totalLength += len(param)
        }
        return totalLength
    }
    // Now we can call innerFunction() freely
    someState = innerFunction(s1)
    someState += innerFunction(s2)
    return someState
}
myVar := outerFunction(100, "blah", "meh")

Les fonctions internes sont souvent pratiques pour les goroutins locaux:

func outerFunction(...) {
    innerFunction := func(...) {
        ...
    }
    go innerFunction(...)
}
1
vthorsteinsson