One thing to keep in mind is that Go development was incremental and was
done, from early on, by having multiple implementations. Incremental
processes often lead to different results than designing a language from a
blank slate. Ambiguities in the spec are often discovered only when someone
notices that implementations disagree and must be resolved somehow.
Sometimes that happens after Go 1 and the resolution must happen in a way
that, as much as possible, retains stability guarantees. So, it's not
unsurprising if we get non-obvious spec clauses such as this.

Specifically, I can well imagine that this particular case arose, because
it was discovered after the fact that one implementation contained an
optimization to not evaluate the argument to `len`, while the other didn't
and the question of side-effects only arose when someone noticed.

I don't really know the answer to your question. I can't think of anything
which would break. That being said, I also don't think it's something that
really needs "fixing", as it seems a pretty uncommon concern.

On Fri, Mar 18, 2022 at 4:36 PM Marvin Renich <m...@renich.org> wrote:

> * 'Axel Wagner' via golang-nuts <golang-nuts@googlegroups.com> [220318
> 08:04]:
> > https://go.dev/ref/spec#Length_and_capacity says:
> >
> > > The expression len(s) is constant if s is a string constant. The
> > > expressions len(s) and cap(s) are constants if the type of s is an
> array or
> > > pointer to an array and the expression s does not contain channel
> receives
> > > or (non-constant) function calls; in this case s is not evaluated.
> > > Otherwise, invocations of len and cap are not constant and s is
> evaluated.
> >
> > So, in your case, the array contains a function call, so `len(…)` is not
> > constant.
>
> Is the intent of that paragraph in the spec to ensure that side effects
> occur?  Clearly the length of [3]int{...} is constant, regardless of any
> channel receives or non-constant function calls.
>
> Why was the spec not written as:
>
>   ....  The expressions len(s) and cap(s) are constants if the type of s
>   is an array or pointer to an array.  If the expression s does not
>   contain channel receives or (non-constant) function calls, then s is
>   not evaluated.  ....
>
> And then in the documentation for the range clause, say something like:
>
>   ...:  if at most one iteration variable is present, the range
>   expression x is only evaluated if it would be evaluated by len(x).
>
> This would allow
>
>   const x = len([3]int{1, 2, f()})
>
> to compile with the obvious side effects, but still result in x being a
> constant.
>
> Is there some other reason to force len([3]int{«non-constant
> initializer»}) to be non-constant?
>
> ...Marvin
>
> --
> You received this message because you are subscribed to the Google Groups
> "golang-nuts" group.
> To unsubscribe from this group and stop receiving emails from it, send an
> email to golang-nuts+unsubscr...@googlegroups.com.
> To view this discussion on the web visit
> https://groups.google.com/d/msgid/golang-nuts/YjSm83cOcG1cACFP%40basil.wdw
> .
>

-- 
You received this message because you are subscribed to the Google Groups 
"golang-nuts" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to golang-nuts+unsubscr...@googlegroups.com.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/golang-nuts/CAEkBMfF%2BwrFLNGXM73tkZPtw1FwxiOHArCZFtVVL91t%2BCxhpHQ%40mail.gmail.com.

Reply via email to