Fwd: [go-nuts] strange scoping rules

46 views
Skip to first unread message

Gustavo Niemeyer

unread,
Nov 26, 2010, 8:32:43 AM11/26/10
to golan...@googlegroups.com
Greetings,

The proposal below seems to address all of the related concerns
brought up previously in the mailing list [1][2][3][4] and in the
issue [5] without requiring modification in other aspects of the
language.

How does the development team feel about it?


[1] http://groups.google.com/group/golang-nuts/browse_thread/thread/5f070b3c5f60dbc1
[2] http://groups.google.com/group/golang-nuts/browse_thread/thread/defbff7e6a81c085
[3] http://groups.google.com/group/golang-nuts/browse_thread/thread/fa0e6d0438bf165e
[4] http://groups.google.com/group/golang-nuts/browse_thread/thread/585ec372c24c83bb
[5] http://code.google.com/p/go/issues/detail?id=377


---------- Forwarded message ----------
From: Gustavo Niemeyer <gus...@niemeyer.net>
Date: Wed, Nov 24, 2010 at 00:10
Subject: Re: [go-nuts] strange scoping rules
To: Nigel Tao <nigel.t...@gmail.com>
Cc: Steven <stev...@gmail.com>, golang-nuts <golan...@googlegroups.com>


> Another possible syntax for being explicit about which variables are
> freshly declared is
> $y, err = f()
> but as Ian pointed out to me, the $ here would mean something much
> different than Perl's or BASIC's $, wheras Go's := is similar to
> Pascal's :=.

If the character used is the only issue, it shouldn't be hard to come
with a more reasonable option.

As an example, suppose we pick the colon itself. Then this:

   a, b := f()

Would be fully equivalent to:

   :a, :b = f()

and a construction in an internal block such as:

   err = f()

might be extended to the following, which is completely clear and unambiguous:

   :a, err = f()

When one doesn't want to redefine err.

One of the things which feels interesting about this proposal is that
it would enable forbidding entirely partial declarations via := if
that's decided to be a good option, without compromising on other
aspects of the language.

--
Gustavo Niemeyer
http://niemeyer.net
http://niemeyer.net/blog
http://niemeyer.net/twitter

Gustavo Niemeyer

unread,
Nov 30, 2010, 8:08:31 AM11/30/10
to golan...@googlegroups.com
Any comments on this proposal?

Ian Lance Taylor

unread,
Nov 30, 2010, 12:55:39 PM11/30/10
to Gustavo Niemeyer, golan...@googlegroups.com
Gustavo Niemeyer <gus...@niemeyer.net> writes:

> Any comments on this proposal?

>> If the character used is the only issue, it shouldn't be hard to come


>> with a more reasonable option.

Speaking purely personally, I don't much like using a character in the
declaration at all. Adding a prefix character feels to me like changing
the name. I would like all direct references to a single object to have
the same name. Also I think that using a prefix character to cause a
name to escape its lexical scope is very odd. And what about

var g int
func f() {
:g := 0
}

Why shouldn't that work?


I also don't think this proposal addresses the most confusing aspect of
the current syntax, which I think is

a := 0
a, x := fn()
if a, f := fn(); f {
}
// Here a is from the first call to fn, not the second.

I think nested scopes are good. I think simple scoping of a name in an
if statement is good. I think := is good. I think permitting := to
redeclare existing names is convenient. But putting all of those
together gives us examples like the above, which is not, in my opinion,
a serious problem, but can be confusing. I haven't yet seen any
proposal to address this which I personally care for.

Ian

Gustavo Niemeyer

unread,
Nov 30, 2010, 1:08:26 PM11/30/10
to Ian Lance Taylor, golan...@googlegroups.com
Hello Ian,

> Speaking purely personally, I don't much like using a character in the
> declaration at all.  Adding a prefix character feels to me like changing
> the name.  I would like all direct references to a single object to have
> the same name.  Also I think that using a prefix character to cause a
> name to escape its lexical scope is very odd.  And what about

That's not the suggested semantics. The : prefix would have the same
effect of using the ":=" operator with the given variables. So this:

a, b := f()

Is the same as:

:a, :b = f()

>        :g := 0
> Why shouldn't that work?

This feels like a strange point as well. I could argue that it doesn't
work for the same reason that g, = 0 doesn't, for instance: it's
invalid syntax. But I'm not sure I get your point.

> I also don't think this proposal addresses the most confusing aspect of
> the current syntax, which I think is
>
>        a := 0
>        a, x := fn()
>        if a, f := fn(); f {
>        }
>        // Here a is from the first call to fn, not the second.

It does solve that problem by enabling the spelling:

if :a, err = f(); err == nil {
...
}

Which explicitly declares the first variable to be local, while the
err must exist and have the same type in the outer scope. This
construct above is actually the classical source of issues in this
regard, as far as I could perceive in the mailing list and in issue
377.

> I think nested scopes are good.  I think simple scoping of a name in an
> if statement is good.  I think := is good.  I think permitting := to
> redeclare existing names is convenient.  But putting all of those

Agreed. Note that the proposal doesn't change the state of affairs in
any of those details.

Is the proposal more clear now?

Ian Lance Taylor

unread,
Nov 30, 2010, 2:20:21 PM11/30/10
to Gustavo Niemeyer, golan...@googlegroups.com
Gustavo Niemeyer <gus...@niemeyer.net> writes:

> That's not the suggested semantics. The : prefix would have the same
> effect of using the ":=" operator with the given variables. So this:
>
> a, b := f()
>
> Is the same as:
>
> :a, :b = f()

I see. I did misunderstand the proposal, but I'm still not personally
fond of using a prefix character on the name of a variable.


>> I also don't think this proposal addresses the most confusing aspect of
>> the current syntax, which I think is
>>
>>        a := 0
>>        a, x := fn()
>>        if a, f := fn(); f {
>>        }
>>        // Here a is from the first call to fn, not the second.
>
> It does solve that problem by enabling the spelling:
>
> if :a, err = f(); err == nil {
> ...
> }

That does not seem to me to be a solution. It avoids the problem but it
seems to me that I can still write the above code and it is still
confusing.

Ian

Gustavo Niemeyer

unread,
Nov 30, 2010, 6:19:47 PM11/30/10
to Ian Lance Taylor, golan...@googlegroups.com
>>>        a := 0
>>>        a, x := fn()
>>>        if a, f := fn(); f {
>>>        }
>>>        // Here a is from the first call to fn, not the second.
>>
>> It does solve that problem by enabling the spelling:
>>
>>   if :a, err = f(); err == nil {
>>       ...
>>   }
>
> That does not seem to me to be a solution.  It avoids the problem but it
> seems to me that I can still write the above code and it is still
> confusing.

Right, the proposal enables the creation of correct code in an
unambiguous, terse, and syntactically similar way. The fact that the
*existing* syntax and semantics continue to be confusing cannot be
addressed without changing them, of course. It would be quite easy to
solve it by disallowing shadowing entirely after including the new
syntax, but that's a separate step and not what I'm advocating for at
this point. Independently of that, the key point is that the proposal
makes the creation of correct code to be at least as convenient as the
creation of incorrect one, which isn't the case today in the examples
brought up in the thread and in the several duplicated issues filed.

Reply all
Reply to author
Forward
0 new messages