What does this do? That should be a no-op by default in any sane language.
What does this do? That should be a no-op by default in any sane language.
var item *Item = item
It creates a locally scoped variable that shadows the existing one.On the left side, "item" resolves to the "item" in inner scope (that is declared on the same line). On the right side it resolves to the "item" in outer scope.
Then I understand what's happening though I'm still not convinced it's sane behaviour. I would expect all identical names in a single scope to refer to the same variable.
my_goose : Goose = get_a_goose();
... lets us give my_goose an explicit type, while we can write: my_goose := get_a_goose();
... and leave the compiler to infer that my_goose is a Goose because that's what get_a_goose() returns and we didn't specify.The idea here is that we have this flexibility but we didn't burden the language with what feels like an extra feature (like C++ auto) with its own special rules. Given that := starts out as a single token this is in some sense revisionist, but so long as you're trying to learn to program, not studying the history of programming, that's fine.
It reminds me of how eggcorns can become language features. A person incorrectly analyses a word or phrase they've heard, e.g. they think the things which fall off an oak tree must be named "eggcorns" because they look a bit like eggs. They apply this analysis, and, if the results are successful and out-competes existing correct analysis, it can dominate, next thing you know† your spelling correction tool says "Did you mean eggcorn?" when you type acorn.
† In reality these transitions usually take generations
One shadows the variable by a variable of the same name. The key is that the new variable is scoped only to the inside of the loop, whereas the original variable is scoped to the outside of it, thus assigning to the original variable in a next iteration of the loop updates that variable again.
The major case where this is an issue is if one somehow took a reference to the variable, that reference thus now points to the new value rather than the old.
Taking a reference to the new, more closely scoped variable that is local to the iteration of the loop does not have this problem.
That is a no-op
a := b
Declares a new variable a and assigns it. It's sugar for:
var a = b
So read it as:
var item = item
Many languages have scopes and variable shadowing. You can argue this is bad practice or whatever, but it's only confusing if you think := is assignment which is covered in the first page of the Go language tutorial.
var item = item
should still be a noop imo. If it does some magic like dereferencing, make it explicit. And no, other languages making the same mistake is not a good excuse. Especially not for a language focused on inexperienced newgrads.That said, it looks and feels dirty and buggy and it's a known workaround for a Go issue, so I'm glad they're at least talking about fixing it.
What does the print function exactly do if I pass a variable to it.
The statement by itself doesn't produce any visible side effect.
However it creates a new logical variable in the abstract machine, and that can have real consequence in the real underlying machine, depending on which statements happen next.
In particular, the new variable and the old variable are independent and thus the new variable may require to allocate some storage location (e.g. on the stack, a register, ...) to keep track of further mutations to its value (I say "may" because an optimising compiler may do without that extra location)
item := item
item := item
the two lines doing different things even though looking exactly the same.I'm a Scala dev and in Scala we have a similar thing, where a new import or definition in the middle of the code can change line semantics between two equal lines.
But the difference is that this is not a mistake but a concious design to switch "contexts" and is heavily guarded by the typesystem, where GOs typesystem is incredibly weak in comparison, which is not an inherent drawback, but here it is.
I do feel that I'll stick to my feelings that this design is confusing and should have been avoided from the beginning. Ku udos to the go team for breaking compatibility here. This is necessary for a language to not become another COBOL.
item := item
item := item
"no new variables on left side of :="You can't declare the same variable twice in the same scope.
item := item
works only because it declares a new variable in the current scope, initialized with a variable with the same name (but different variable) from the outer scope.Go distinguishes declarations from assignments. In this example, the second assignment is a no-op indeed.
item := item
item = item let x = ... x ...
and every such line is a declaration of a new variable that shadows the preceding one. let x = 0 in
let x = x + 1 in
... let foo = foo.clone();
let bar = bar.into_inner();
let baz = baz.to_owned();
let quz = quz.unwrap();
...