It's playtime for Go enthusiasts

Meet Fo, an experimental superset for Go

© Shutterstock / fewerton

Playtime never ends in the Go world; there’s something new you can play with every day! This time, it’s an experimental superset for Go. Ladies and Gentlemen, meet Fo!

Go enthusiasts, gather round now! I have a new pastime for you!

Functional Go, or Fo, is an experimental language that adds functional programming features to Go. The main and, so far, only feature of Fo is type polymorphism via generics.

Why use this feature? Well, generics encourage functional programming techniques by making it possible to write flexible higher-order functions and type-agnostic data structures. Fo should be thought of as a proof of a concept that gives us a glimpse into what Go would look like with some new language features and allows us to explore how those features interact and what you can build with them.

Since Fo is still in an experimental state, its syntax and implementation have not been finalized yet. We can, however, have a quick look at what the language consists of so far.

What we have Fo far

Since Fo is a superset for Go, any valid Go program is also a valid Fo program, provided you change the file extension from “.go” to “.fo”.

SEE ALSO: Revive: An extensible and configurable linter for Go

Generic named types

Declaration – Fo extends the Go grammar for type declarations to allow the declaration of generic types. Generic types expect one or more “type parameters”, which are placeholders for arbitrary types to be specified later and the grammar looks like this:

TypeDecl = "type" identifier [ TypeParams ] Type . 
TypeParams = "[" identifier { "," identifier } "]" .

Usage – When using a generic type, you must supply a number of “type arguments”, which are specific types that will take the place of the type parameters in the type definition. The combination of a generic type name and its corresponding type arguments is called a “type argument expression”:

TypeArgExpr = Type TypeArgs . TypeArgs = "[" Type { "," Type } "]" .

Generic functions

Declaration – The syntax for declaring a generic function is similar to named types and grammar looks like this:

FunctionDecl = "func" FunctionName [ TypeParams ] Signature [ FunctionBody ] .
TypeParams   = "[" identifier { "," identifier } "]"

Usage – to use a generic function, you must supply the type arguments. If you actually want to call the function, just add the function arguments after the type arguments:

CallExpr = FunctionName ( TypeArgs ) Arguments .
TypeArgs = "[" Type { "," Type } "]" .

Generic methods

Declaration – Fo supports a special syntax for methods with a generic receiver type. You can optionally include the type parameters of the receiver type and those type parameters can be used in the function signature and body. Whenever a generic method of this form is called, the type arguments of the receiver type are passed through to the method definition:

MethodDecl = "func" Receiver MethodName [ TypeParams ] Signature [ FunctionBody ] .
Receiver   = "(" [ ReceiverName ] Type [ TypeParams ] ")" .
TypeParams = "[" identifier { "," identifier } "]" .

Usage – When calling methods with a generic receiver type, you do not need to specify the type arguments of the receiver.

Getting started

Intrigued? You can give Fo a… go without installing by visiting the Fo playground.

If you feel you are ready to make it more official, you can install Fo like any other Go program:

go get -u;

Eirini-Eleni Papadopoulou
Eirini-Eleni Papadopoulou was the editor for Coming from an academic background in East Asian Studies, she decided that it was time to go back to her high-school hobby that was computer science and she dived into the development world. Other hobbies include esports and League of Legends, although she never managed to escape elo hell (yet), and she is a guest writer/analyst for competitive LoL at TGH.

Inline Feedbacks
View all comments