Le funzioni anonime

Una funzione anonima è un blocco di istruzioni a cui non è stato dato un nome e viene definita direttamente nel punto in deve essere eseguita. Può anche essere definita e salvata all’interno di una variabile per potere essere utilizzata più volte.

In alcuni linguaggi, come Python e C#,  viene chiamata lambda, in JavaScript viene definita tramite un arrow function () => {} oppure con function() {} mentre Rust utilizza le closure.

Le funzioni anonime vengono usate anche quando dobbiamo richiamare una funzione che deve accedere a variabili che non possono essere passate come argomenti.

Esempio di funzione anonima

L’esempio è preso dal tutorial di una REStFul API fatto con Go e la libreria Gin: Tutorial: Developing a RESTful API with Go and Gin – The Go Programming Language.

Riscriviamo tutto il codice relativo gli album su un modulo separato e lasciamo nel file main.go soltanto la variabile che contiene la lista e la funzione principale. Perciò creiamo una cartella album, e da terminale digitiamo go mod init web-service-gin/album. Creiamo anche un workspace e aggiungiamo il file principale e il sottomodulo:

go work init .
go work use ./album

Per richiamare le funzioni get e post dobbiamo passare il context e la lista tramite una funzione anonima. Sotto sono indicate soltanto il nome delle funzioni con gli argomenti richiesti:

func GetAlbums(c *gin.Context, albums AlbumList) {

}

func GetAlbumById(c *gin.Context, albums AlbumList) {

}

func PostAlbums(c *gin.Context, albums AlbumList) {

}

Questo è la funzione originale:

func main() {
    router := gin.Default()
    router.GET("/albums", getAlbums)
    router.GET("/albums/:id", getAlbumByID)
    router.POST("/albums", postAlbums)

    router.Run("localhost:8080")
}

Questa è il metodo per usare la funzione anonima:

func main() {
	router := gin.Default()
	router.GET("/albums", func(c *gin.Context) {
		album.GetAlbums(c, albums)
	})
	router.GET("/albums/:id", func(c *gin.Context) {
		album.GetAlbumById(c, albums)
	})
	router.POST("/albums", func(c *gin.Context) {
		album.PostAlbums(c, albums)
	})

	router.Run("localhost:8080")
}

Questa modifica è necessaria perché i metodi GET e POST della libreria gin accettano come secondo parametro soltanto il nome delle funzione o un blocco di istruzioni definito al suo interno e non è possibile richiamare direttamente al suo interno una funzione già definita con i parametri.

Quando tutto il codice si trovava sullo stesso file gli argomenti venivano passati automaticamente senza che ce ne rendessimo conto. Ma quando rendiamo il codice modulare e pulito le funzioni esterne non possono accedere alle variabili locali e dobbiamo passarli noi tramite funzioni anonime.