mon
mon

Reputation: 22254

Understanding go composite literal

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())
}

Upvotes: 10

Views: 38477

Answers (2)

Grigoriy Mikhalkin
Grigoriy Mikhalkin

Reputation: 5573

Does 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 ";" } .

Why function cannot be constructed as a composite literal?

I wasn't able to find any documented answer to that, but simplest assumption would be that main reasons are:

  • Avoid confusion. Here is example, if it would be allowed to construct composite literal for function:
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.

  • Besides body, function has one more important thing -- 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.

Upvotes: 7

Vivek
Vivek

Reputation: 86

You need to format it.

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(func()int{ x++; return x * x})   // <--- Error with Invalid composite literal type: SQUARE 

   fmt.Println(g())
}

Wrap your variable f using (). In the case of SQUARE, you need to write the func() int before starting your function code

Upvotes: 1

Related Questions