-2

According to Effective Go, the function math.Sin cannot be used to define a constant because that function must happen at run-time.

What is the reasoning behind this limitation? Floating-point consistency? Quirk of the Sin implementation? Something else?


There is support for this sort of thing in other languages. In C, for example: as of version 4.3, GCC supports compile-time calculation of the sine function. (See section "General Optimizer Improvements").

However, as noted in this blog post by Bruce Dawson, this can cause unexpected issues. (See section "Compile-time versus run-time sin").

Is this a relevant concern in Go? Or is this usage restricted for a different reason?

Phlarx
  • 134
  • 1
  • 8
  • 2
    It's because constants are compile-time concepts, so anything that happens at runtime cannot possibly be a constant. – Jonathan Hall Mar 21 '19 at 20:36
  • FWIW the issue isn't strictly compile-time vs runtime calculations, rather it's the calculation mechanisms being different. – Dave Newton Mar 21 '19 at 20:38
  • 2
    "Something else?" - huh? It's a method call, it happens at runtime. Go's constant compile-time evaluation is quite limited. Why is that, you ask? I'd bet on keeping the compiler simple. IMHO, there are more important things to do. – Sergio Tulentsev Mar 21 '19 at 20:38
  • Expressions can happen at compile-time, such as `1<<3`, or `math.Pi/4`. Why is a function call so fundamentally different, then? – Phlarx Mar 21 '19 at 20:47

2 Answers2

3

Go doesn't support initializing a constant with the result of a function. Functions are called at runtime, not at compile time. But constants are defined at compile time.

It would be possible to make exceptions for certain functions (like math.Sin for example), but that would make the spec more complicated. The Go developers generally prefer to keep the spec simple and consistent.

andybalholm
  • 15,395
  • 3
  • 37
  • 41
  • You make it sound like that is a general rule for all functions in Go. Is this documented anywhere, such as a development blog? – Phlarx Mar 21 '19 at 20:47
  • 3
    It's a general rule for constants in Go. You don't need a development blog: https://golang.org/ref/spec#Constants – Adrian Mar 21 '19 at 20:49
  • 1
    `or the result value of some built-in functions such as unsafe.Sizeof applied to any value`. Okay, so it's not quite a general rule. But this is closer to the answer I was looking for. Some descriptive functions are allowed (in addition to `unsafe.Sizeof`, `cap` or `len`), but all calculative functions seem to be disallowed. – Phlarx Mar 21 '19 at 20:55
0

Go simply lacks the concept. There is no way of marking a function as pure (its return value depends only on its arguments, and it doesn't alter any kind of mutable state or perform I/O), there is no way for the compiler to infer pureness, and there's no attempt to evaluate any expression containing a function call at compile-time (because doing so for anything except a pure function of constant arguments would be a source of weird behavior and bugs, and because adding the machinery needed to make it work right would introduce quite a bit of complexity).

Yes, this is a substantial loss, which forces a tradeoff between code with bad runtime behavior, and code which is flat-out ugly. Go partisans will choose the ugly code and tell you that you are a bad human being for not finding it beautiful.

The best thing you have available to you is code generation. The integration of go generate into the toolchain and the provision of a complete Go parser in the standard library makes it relatively easy to munge code at build time, and one of the things that you can do with this ability is create more advanced constant-folding if you so choose. You still get all of the debuggability peril of code generation, but it's something.

hobbs
  • 223,387
  • 19
  • 210
  • 288