Function currying is a concept from functional programming and involves partial application of functions. It allows a function with multiple arguments to be transformed into a sequence of functions, each taking a single argument.
Example:
funcmain(){squareFunc:=selfMath(multiply)doubleFunc:=selfMath(add)fmt.Println(squareFunc(5))// prints 25fmt.Println(doubleFunc(5))// prints 10}funcmultiply(x,yint)int{returnx*y}funcadd(x,yint)int{returnx+y}funcselfMath(mathFuncfunc(int,int)int)func(int)int{returnfunc(xint)int{returnmathFunc(x,x)}}
In the example above, the selfMath function takes in a function as its parameter and returns a function that itself returns the value of running that input function on its parameter.
Assignment
The Textio API needs a very robust error-logging system so we can see when things are going awry in the back-end system. We need a function that can create a custom "logger" (a function that prints to the console) given a specific formatter.
Complete the getLogger function. It should take as input a formatter function and return a new function. The new logger function takes as input two strings and passes them to the formatter, then prints the result. Keep the order of the strings.
Full program (solution included):
1
Step 1 — Function signature
getLogger receives a function (formatter) that takes two strings and returns a single string.
getLogger returns another function that takes two strings and prints (does not return) the formatted result.
2
Step 2 — Return an anonymous function (closure)
Return an anonymous function that captures formatter:
The returned function is a closure: it "remembers" the formatter passed to getLogger.
3
Step 3 — Usage
Example usage in the program:
In plain English: getLogger builds a custom printing function. You supply a formatter, and it returns a logger that uses that formatter to print messages consistently.
Key concepts
Concept
Meaning
Higher-order function
A function that takes or returns another function (getLogger)
Anonymous function
A function with no name (func(first, second string) { ... })
Closure
When an inner function “remembers” variables from its outer scope (formatter)
Formatter
A function that defines how two strings are combined (e.g. colonDelimit, commaDelimit)
package main
import (
"errors"
"fmt"
)
// getLogger takes a function that formats two strings into
// a single string and returns a function that formats two strings but prints
// the result instead of returning it
func getLogger(formatter func(string, string) string) func(string, string) {
return func(first, second string) {
formatted := formatter(first, second)
fmt.Println(formatted)
}
}
// don't touch below this line
func test(first string, errors []error, formatter func(string, string) string) {
defer fmt.Println("====================================")
logger := getLogger(formatter)
fmt.Println("Logs:")
for _, err := range errors {
logger(first, err.Error())
}
}
func colonDelimit(first, second string) string {
return first + ": " + second
}
func commaDelimit(first, second string) string {
return first + ", " + second
}
func main() {
dbErrors := []error{
errors.New("out of memory"),
errors.New("cpu is pegged"),
errors.New("networking issue"),
errors.New("invalid syntax"),
}
test("Error on database server", dbErrors, colonDelimit)
mailErrors := []error{
errors.New("email too large"),
errors.New("non alphanumeric symbols found"),
}
test("Error on mail server", mailErrors, commaDelimit)
}
logger := getLogger(colonDelimit)
logger("Error on database server", "out of memory")
// prints: Error on database server: out of memory
commaLogger := getLogger(commaDelimit)
commaLogger("Error on mail server", "email too large")
// prints: Error on mail server, email too large