The following does not work:
struct S { x int }
func f() (int, int)
func main() {
s = &S{}
s.x, n := f() // error in subject line kicks here
}
You circumvent it by writing
n int
s.x, n = f()
But this is annoying, especially when you are using Go idiom like:
if s.x, ok := f(); !ok { ... }
and you want the "ok" to be a local variable.
Is there a fundamental reason why this cannot be improved so as to
make the first example above (with the error) to actually work?
--Petar
I am asking: Is there a fundamental language design reason
why it couldn't be made to work.
Petar
So, the mixture of new vs. existing is not the core problem.
I am simply asking, when the parser sees
s.x, y :=
and recognizes that s.x is a field and y is a new variable, why can't
it treat
s.x as a plain/existing variable for the purpose of this assignment.
P
On Jan 8, 4:46 pm, Kevin Ballard <kball...@gmail.com> wrote:
> Yes, but if you say
>
> x, y :=
>
> it still basically re-creates both variables.
(1) This is somewhat of an ambiguous statement to me (at least)
(2) I am guessing that by "re-create" you mean that it discards the
old variable, say x,
and creates a new one under the same name. After which, all references
to "x" refer
to the new variable. If this is what you mean, there is no problem.
This is an
implementation issue, not a language interpretation issue.
> This doesn't make any
> difference if you say something like
>
> var x string;
> x, y := ...
>
> but it certainly makes a difference when the assignment statement happens
> inside a nested scope. I ran into this exact problem in one of my programs,
> where my error parameter was always coming back nil even when I was
> assigning it to the results of a function call, because I was using := in
> the assignment and the outer scope's error variable was therefore being
> ignored.
This does not sound true. What you probably did is the following:
var err = 8
if err := f(); err == 0 {
...
}
fmt.Printf("%v\n",err)
In this example there are two different err variables. One outside the
if body
and one inside. While you are inside the body, you only see the inner
one.
Changes to "err" made inside the if body do not affect the outside
variable.
P
(1) This is somewhat of an ambiguous statement to me (at least)
(2) I am guessing that by "re-create" you mean that it discards the
old variable, say x,
and creates a new one under the same name. After which, all references
to "x" refer
to the new variable. If this is what you mean, there is no problem.
This is an
implementation issue, not a language interpretation issue.
> This doesn't make anyThis does not sound true. What you probably did is the following:
> difference if you say something like
>
> var x string;
> x, y := ...
>
> but it certainly makes a difference when the assignment statement happens
> inside a nested scope. I ran into this exact problem in one of my programs,
> where my error parameter was always coming back nil even when I was
> assigning it to the results of a function call, because I was using := in
> the assignment and the outer scope's error variable was therefore being
> ignored.
var err = 8
if err := f(); err == 0 {
...
}
fmt.Printf("%v\n",err)
Still, the question remains, can the compiler simply recognize
that s.x is an existing struct field and re-assign it?
As a matter of fact it seems like there is no problem:
An expression of the form s.x (that has a dot in it) can never
be a variable, so it is clearly recognizable as a field,
in which case the compiler can take a different action,
which is to re-assign the field value.
P
P
In my first post, I have given one reason why it makes sense.
P
i'm starting to wonder if this wasn't a step too far;
when i use this property, i sometimes think that
i'm creating fragile code - if i move that code
code into an inner block then the semantics change,
often without any obvious sign that they've done so.
recently, i've been declaring the new variable
anyway and just using =; that way it's obvious
to the reader of the code which variable is new
and which is being assigned to, and moving the
assignment around won't change the meaning.
i can't decide if this is really better.
however, with regard to the original question: i don't see why
not - at least it's obvious that you're not trying to
declare a new variable x.y or whatever.