Why a function value assignment to f is not a composite literal?
Go lang specification Composite literals says below, hence function value cannot be constructed with composite Literal.
Composite literals construct values for structs, arrays, slices, and maps and create a new value each time they are evaluated
However, the function value assignment to f in the code looks as a composite literal expression for type func() int.
Is there a reason function object cannot be constructed as a composite literal?
package main
import (
"fmt"
)
func main(){
var x int = 0
var f func() int
f = func() int{ x++; return x * x } // <---- Why this cannot be a composite literal?
fmt.Println(f()) // 1
fmt.Println(f()) // 4
fmt.Println(f()) // 9
// Define a type for "func() int" type
type SQUARE func() int
g := SQUARE{ x++; return x * x} // <--- Error with Invalid composite literal type: SQUARE
fmt.Println(g())
}
f = func() int{ x++; return x * x }
looks like composite literal?Not really)
As spec states:
Composite literals construct values for structs, arrays, slices, and maps... They consist of the type of the literal followed by a brace-bound list of elements.
To make this statement clearer, here is production rule for composite literal:
CompositeLit = LiteralType LiteralValue .
You can see, that production rule for LiteralValue
is:
LiteralValue = "{" [ ElementList [ "," ] ] "}" .
and FunctionBody
, doesn't look at all like this. Basically, it's list of Statement
's:
FunctionBody = Block .
Block = "{" StatementList "}" .
StatementList = { Statement ";" } .
I wasn't able to find any documented answer to that, but simplest assumption would be that main reasons are:
type SquareFunc func() int
type Square struct {
Function SquareFunc
}
func main() {
f := SquareFunc{ return 1 }
s := Square{ buildSquareFunc() }
}
s:= ...
line(which is supposed to be composite type) could be easily confused with 1st line.
Signature
. If you could construct composite literal for function, how would you define it's arguments and return parameters names? You could define names in type definition -- but that would cause inflexibility(sometimes you want to use different parameter names) and code like:type SquareFunc func(int x) int
func main() {
x := 1
f := SquareFunc{
x++
return x * x
}
f(2)
}
would look too unclear, as it wouldn't be obvious what x
variable does it actually use.