--
You received this message because you are subscribed to the Google Groups "golang-dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email to golang-dev+unsubscribe@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.
The problem with an environment variable is that it effectively prevents aliases from being tried seriously, out of fear that support for the feature might disappear again. On the other hand, if they are widely (and appropriately) used, an environment variable cannot be changed anyway without breaking code. We have seen exactly this effect with GO15VENDOREXPERIMENT. Only once we enabled vendoring for good, people started using it.
Hence the decision was made by the Go team to go ahead with the minimal, regular, and quite restricted alias feature we have now implemented.
Let me say this regarding the fear of misuse: The Go language also implements the goto statement, and it is undisputed that uncontrolled use of gotos is hugely detrimental for readability and comprehension of code. Yet, there is hardly code that abuses gotos these days. But there are rare cases where a goto is exactly the right choice: when you need one (*), you really do.
Dear all,
I'm writing to formally request that the process of adding aliases to
the language be rolled back.
Code from the draw package for 1.8:const Over => draw.Overconst Src => draw.Srcfunc Draw => draw.Drawfunc DrawMask => draw.DrawMaskI find this unreadable and confusing.
Let me say this regarding the fear of misuse: The Go language also implements the goto statement, and it is undisputed that uncontrolled use of gotos is hugely detrimental for readability and comprehension of code. Yet, there is hardly code that abuses gotos these days. But there are rare cases where a goto is exactly the right choice: when you need one (*), you really do.
To unsubscribe from this group and stop receiving emails from it, send an email to golang-dev+...@googlegroups.com.
On Oct 28, 2016 8:19 AM, "Russ Cox" <r...@golang.org> wrote:
>
> I want to say again what I wrote on the issue on September 15:
>
> """
> I wish there could be widespread agreement on this issue about the merits and tradeoff here. That is our ideal for any proposal. But there is not, and after two months of discussion it seems clear that further discussion is not going to change the situation. At this point the best way to learn more is to implement this proposal and try it. We still have until the Go 1.8 release to disable it if a strong reason turns up.
>
> Although the many important voices here are split, Rob, Robert, Ian, and I are not. Along with Ken, who is no longer working on Go on a daily basis, we were responsible for nearly all of the original design of Go, and we all agree, based on our extensive experience with Go and with very large Go code bases, that something along the lines of this proposal is needed. I ask only that you give us the benefit of the doubt on this decision and come along with us to see how it turns out.
> """
>
> We certainly hear the people saying that they think this is making code less readable, or can or will be abused. To those people I can only ask for patience to let this process play out.
>
> We all have a natural bias to see "different" as "unreadable". I remember very clearly the discussion in Rob's office in January 2009 in which we - Rob, Robert, Ian, Ken, and I - decided to try "upper case means exported" for symbol visibility. I personally thought it was not a good idea and hurt readability, but the proposal addressed a real need (selective export of struct fields), and I could make no technical arguments against it other than I didn't like the way it looked. We did of course try it, and after a few weeks it stopped looking unreadable (that really meant "less like C than Go had before") and became completely natural. Today it is one of my favorite Go features, and I don't think anyone here would argue that it makes the code unreadable. To the contrary, there is actually a technical argument that it enhances readability. I realized this a few years later, when I had to do some work in an unfamiliar section of Google's C++ code base. I found it quite frustrating that I couldn't tell just from looking at a use of a method whether this was a public or private method. I'd see a call and think "wow, is that part of the public API? That would be scary." and have to go dig up the actual method definition and see that oh, it's marked private. In Go, that information is visible at each use, and I'd grown accustomed to having that information implicitly at hand when reading code. So not only was I wrong about the aesthetics of "upper case means exported" - we all adapted just fine to reading Go code written that way - but if we'd let the aesthetics make the decision, we would have cut off this other technical benefit, which we certainly discussed at the time but I think could not fully appreciate the value of until later.
>
> Every language feature can be abused. The fact that Go uses predeclared identifiers instead of keywords when possible makes it easier to extend the language with new builtins without fear or breaking existing programs, like when we added delete. It also lets code dealing with marshalling or unmarshalling have methods with clear names like int and string (see for example go/src/encoding/gob/debug.go). These are good things. It also lets people write code like https://play.golang.org/p/3wrRikamA-, which no one would say is a good thing. We accept the fact that the last example is possible as a consequence of abuse of these more limited good things, and over time we learn conventions about what to do and not do. If you saw code like that playground example anywhere but a compiler test case (it's really go/test/rename.go), you'd encourage the author to write it differently.
>
> Every language feature is overused at first. Experimenting is how we explore and chart the boundaries of what a language feature is and is not good for. The experiments that fail are the ones we later understand as overuse. When Go was first created, the pieces most unique to Go were channels and goroutines, so naturally we emphasized them in our talks about the language and our examples. This led to overuse of channels in particular, and in response we had to develop advice about when not to use channels: Don't use them for lightweight iterators. Don't use them when a plain mutex is sufficient, but do use them when you might use a mutex+condition variable in another language.
>
> Back to the specifics of alias: as I said in September, based on our experience with Go and with very large Go code bases, Rob, Robert, Ian, and I believe that Go needs some kind of indirection mechanism, to enable incremental evolution of and changes to the layout of Go source trees (C/C++ programs use a combination of typedef and #define). Alias has been designed to (we think) harmonize with and be orthogonal to the rest of the language, in the spirit of Go's design, a generalization of typedef without the abuses of #define. The community feedback in the proposal discussion raised important, objective technical suggestions to limit abuse, and in response we introduced (we think) reasonable limits on alias: it can be used only at top level, it can refer only to imported symbols, it cannot refer to package unsafe. The feedback also included some important but more subjective arguments, such as the "detriment of the readability and comprehension" of Go programs. These latter arguments being subjective, all I can say is that we hear you but we disagree that they outweigh the benefits, keeping in mind especially that there is a natural bias to see different as unreadable, especially at first; that every language feature can be abused, so potential for abuse is not by itself disqualifying; and that every language feature is overused at first, as part of the natural process of exploring how it should be used.
>
> To respond to Dave's specific points:
>
> - Robert and others brought up the idea of an environment variable, but we decided against that. GO15VENDOREXPERIMENT was important because the changed meaning of the directory name "vendor" was going to break code that worked in Go 1.4. The environment variable let us use Go 1.5 as the "let people find out what will break and update their code" cycle. But it also created pockets of mutually uninteroperable Go code because some only compiled with GO15VENDOREXPERIMENT=1 and some only compiled without it. It was important to have that transition, but it was also an unfortunate situation. We do not want to repeat that.
>
> - Types are not the only declaration that doesn't have an existing analog. Vars don't either, and while funcs can be worked around, the alias form is significantly cleaner. That leaves consts, for which aliases require one more character than ordinary assignment and have roughly equivalent effect. We could have excluded aliases from consts but it seemed more orthogonal to let them apply to all four instead of three of the four (or, if you argue for excluding funcs too, two of the four).
>
> - As I hope I explained above, aliases are about incremental evolution of and changes to the layout of Go source trees. We see this in a variety of ways in large Go source trees. One common way does involve protocol buffers but is not fundamental to protocol buffers. What we see specifically is engineers doing incremental evolution of and changes to the layout of Google's source tree, in particular to protocol buffer definitions that compile to language-specific libraries. When this happens, C/C++ and Java have no problem accommodating this evolution while Go acts as a hindrance to that evolution. The ability to make this kind of change to a source tree is something C/C++ and Java programmers take for granted and are frustrated not to be able to do in Go, just as seeing the visibility of an identifier at each use is something Go programmers take for granted and are (at least sometimes) frustrated not to be able to do in C/C++ and Java. The specific protocol buffer setting was just the way that C/C++ and Java programmers helped us find this shortcoming of Go. Since Go was designed explicitly for large code bases, this is an important shortcoming to address. This is not a quid pro quo for Google. This is using our experience working in a very large source tree at Google to inform making Go work well for software development at scale. We have taken advantage of this experience throughout the design of Go, and we'll continue to do that.
>
> - Nigel's use of aliases to make a "draw++" package seems like a good experiment. Maybe we will find that this is a compelling way to evaluate possible evolution of existing packages and end up building tooling to support that use. Maybe we'll find that it's a mistake, like using channels as iterators, and discourage that use. These things are hard to predict. It is certainly too early to say.
>
> This thread asking for the feature to be rolled back started less than nine hours after the compiler support was committed. That is really not enough time to make an informed decision or really even build up an informed opinion about the practical usage of a new language feature. Please be patient and in fact please join us as we experiment to find out what this feature is and is not good for.
I think the fear stems from the fact it's already been merged. In my experience, it's harder and harder to back out things once merged. Stuff gets merged on top and as time ticks by it seems like the only way this will be reverted is if it's harming kittens or something obscene. Obviously that won't be the case as it's more just a general dislike from a lot of people so I truly think the reality is setting in.
I stand with Dave.
package L2
func Foo() {
println("foo")
}
--
You received this message because you are subscribed to the Google Groups "golang-dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email to golang-dev+unsubscribe@googlegroups.com.
Go was always intended for programming at large scale, which includes working in large software environments, with large teams, and in the presence of complicating factors such as interoperating with other languages. The alias feature is directed at solving a problem that arises in that area, which is refactoring a package in an environment too large or complex to update all the dependents of a package at once. This problem is often seen as a versioning problem, but in monorepos versioning doesn't help, while aliases do.Now, some of Go's popularity is also because of its clarity and readability, but it is worth observing that those properties, which were also goals of the language, are sometimes in conflict with the need for programming at scale. There are other features of the language that are there for industrial-level work but clearly at odds with simplicity. Goto is the most obvious (it's present for machine-generated code). The verbosity of struct literals is another. The way interface embedding works, allowing redundancy if it's not used, is a third. There are more.What's really different in this conversation is that, for the first time, the community is seeing the difficulty of trying to decide what to do when a new issue raises such a conflict. If we today decided to start enforcing the need to put types on the fields of struct literals, there would be an outcry, but we would do it anyway, because the benefits outweigh the cost, high though the cost is.
The alias feature is important, but it is also ugly. [snip]
--
I honestly don't think this will hurt readability much,
and I care deeply about readability.
I have however just realised what feels odd to me about the
specific syntax:
type A => B
makes it look like A flows to B, but actually the flow is the
other way.
type A <= B
looks odd though.
I kinda wish it had been decided to go with type aliases only.
type A = B
because mutable global variables are almost always a smell, and
functions and constants are trivial to do already.
--
You received this message because you are subscribed to the Google Groups "golang-dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email to golang-dev+...@googlegroups.com.
--
You received this message because you are subscribed to the Google Groups "golang-dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email to golang-dev+unsubscribe@googlegroups.com.
To unsubscribe from this group and stop receiving emails from it, send an email to golang-dev+unsubscribe@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.
--
You received this message because you are subscribed to the Google Groups "golang-dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email to golang-dev+unsubscribe@googlegroups.com.
Again, the perfect example of where the aliasing feature helps for refactoring, is the move of golang.org/x/net/context to context/. The specific workflow for a case like this (not this particular case, as it's already too late for that) is:a) Create the context/ package, with all the code. In the same commit, add aliases in x/net/context for all types and functions to refer to context/b) Give a long deprecation phase for people to change their references from x/net/context directly to context/c) After (almost) all references are changed, delete x/net/context
This creates a path, where all code in the universe remains buildable and mutually compatible, no matter to which package it refers to. This is currently not possible otherwise, because if package a definestype Foo func(context.Context)and package b has afunc Bar(context.Context)
you'll need to update both A and B simultaneously from x/net/context to context/ to be able to use b.Bar as an a.Foo, which is usually not feasible (because, e.g., they have different release cycles).This is the "large scale refactoring" problem that is referred to and that aliases provide a solution for. This has also been described very often in the issue and discussion so far.
To unsubscribe from this group and stop receiving emails from it, send an email to golang-dev+...@googlegroups.com.
On Friday, 28 October 2016 11:13:37 UTC-7, Axel Wagner wrote:Again, the perfect example of where the aliasing feature helps for refactoring, is the move of golang.org/x/net/context to context/. The specific workflow for a case like this (not this particular case, as it's already too late for that) is:a) Create the context/ package, with all the code. In the same commit, add aliases in x/net/context for all types and functions to refer to context/b) Give a long deprecation phase for people to change their references from x/net/context directly to context/c) After (almost) all references are changed, delete x/net/contextIn theory this could have also been done with a symlink (assuming we get them to work across all OS-s and setups)?
This creates a path, where all code in the universe remains buildable and mutually compatible, no matter to which package it refers to. This is currently not possible otherwise, because if package a definestype Foo func(context.Context)and package b has afunc Bar(context.Context)Please, no facilitiated examples... it is impossible to tell whether Foo and Bar are good ideas in the first place. I know it's a convenient shortcut for discussions, but they trivialize real problems.
On Fri, Oct 28, 2016 at 8:26 PM, Egon Elbre <egon...@gmail.com> wrote:On Friday, 28 October 2016 11:13:37 UTC-7, Axel Wagner wrote:Again, the perfect example of where the aliasing feature helps for refactoring, is the move of golang.org/x/net/context to context/. The specific workflow for a case like this (not this particular case, as it's already too late for that) is:a) Create the context/ package, with all the code. In the same commit, add aliases in x/net/context for all types and functions to refer to context/b) Give a long deprecation phase for people to change their references from x/net/context directly to context/c) After (almost) all references are changed, delete x/net/contextIn theory this could have also been done with a symlink (assuming we get them to work across all OS-s and setups)?No. Unless the compiler would know about it and assume both packages to be equal. It would also make the confusion even worse; now you can not see from the source at all that there is aliasing happening and will end up with two packages referring to the same package by different names. Imagine getting an error message for foo/bar/baz/main.go, but finding this string in your source, because spam/eggs has been aliased to it and you are importing that instead.
It would also not solve moving single types between packages, but only whole packages as a unit.
This creates a path, where all code in the universe remains buildable and mutually compatible, no matter to which package it refers to. This is currently not possible otherwise, because if package a definestype Foo func(context.Context)and package b has afunc Bar(context.Context)Please, no facilitiated examples... it is impossible to tell whether Foo and Bar are good ideas in the first place. I know it's a convenient shortcut for discussions, but they trivialize real problems.The level of abstraction to go from this to something realistic is very low.
As a specific example where this specific problem is happening right now, see
I don't have so much of a problem with aliasing in general, because I see plenty of indirection of underlying value all the time. Whether or not the specific usage of indirection is good or not is up to the situation. However, the right arrow (->) syntax seems problematic.
To unsubscribe from this group and stop receiving emails from it, send an email to golang-dev+...@googlegroups.com.
To unsubscribe from this group and stop receiving emails from it, send an email to golang-dev+...@googlegroups.com.
based on our extensive experience with Go and with very large Go code bases, that something along the lines of this proposal is needed. I ask only that you give us the benefit of the doubt on this decision and come along with us to see how it turns out.
--
You received this message because you are subscribed to the Google Groups "golang-dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email to golang-dev+unsubscribe@googlegroups.com.
--
You received this message because you are subscribed to the Google Groups "golang-dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email to golang-dev+...@googlegroups.com.
> email to golang-dev+unsubscribe@googlegroups.com.
--
Lucio De Re
2 Piet Retief St
Kestell (Eastern Free State)
9860 South Africa
Ph.: +27 58 653 1433
Cell: +27 83 251 5824
FAX: +27 58 653 1435
--
You received this message because you are subscribed to the Google Groups "golang-dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email to golang-dev+unsubscribe@googlegroups.com.
Go was always intended for programming at large scale, which includes working in large software environments, with large teams, and in the presence of complicating factors such as interoperating with other languages. The alias feature is directed at solving a problem that arises in that area, which is refactoring a package in an environment too large or complex to update all the dependents of a package at once. This problem is often seen as a versioning problem, but in monorepos versioning doesn't help, while aliases do.Now, some of Go's popularity is also because of its clarity and readability, but it is worth observing that those properties, which were also goals of the language, are sometimes in conflict with the need for programming at scale. There are other features of the language that are there for industrial-level work but clearly at odds with simplicity. Goto is the most obvious (it's present for machine-generated code). The verbosity of struct literals is another. The way interface embedding works, allowing redundancy if it's not used, is a third. There are more.What's really different in this conversation is that, for the first time, the community is seeing the difficulty of trying to decide what to do when a new issue raises such a conflict. If we today decided to start enforcing the need to put types on the fields of struct literals, there would be an outcry, but we would do it anyway, because the benefits outweigh the cost, high though the cost is.
The alias feature is important, but it is also ugly. We know that. It is open to abuse. We know that. But we have been listening: the feature is very heavily restricted because of the many good points raised in the issue discussion. The possibility for abuse is greatly restricted, and the conversation that got us here was invaluable. But the conversation is behind us; now the time has come to try it out. If it turns out to be a real problem in practice, there are three months left to roll it back.But I don't think it will be a problem, because I believe the community will help make sure the abuses don't happen. If you see an alias appear in code where none is necessary, complain about it, publicly. Update golint to yell whenever the feature is used.Most important, explain to people what it is for: that, like goto, it is a necessary evil for program development in the modern world.-rob
--
You received this message because you are subscribed to a topic in the Google Groups "golang-dev" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/golang-dev/OmjsXkyOQpQ/unsubscribe.
To unsubscribe from this group and all its topics, send an email to golang-dev+unsubscribe@googlegroups.com.
Does the alias feature allow us to define our own methods on imports?
I mean essentially what we are wanting to do with this feature is to avoid breakage in our dependencies when we want to redesign our API correct? How does this feature allow us to get passed the headaches with methods where we want to redefine the number of arguments and/or their type definitions?
Personally I really hate the fact that we are allowing ourselves to be like "derp how do we do this, oh screw it lets just throw in a new operator, =>".
I mean Isn't that the lambda operator used in other languages???? (e.g. C#). If we want to convince people that we are coming from a place of understanding regarding what's wrong with other languages shouldn't we be encouraging of the fact that some of us have perhaps used the more popular solutions out there enough to know that we are probably the only language who thought to use this operator like this.
Wasn't there a way python goes about solving this issue?
A good metaphor for what im trying to avoid is that I want to have basically a map of the entire area i can look at to get a general understanding of where everything is. Rather than just looking through a crap load of files to see where all these alias defines are scattered all over the place. My solution is ugly but at least its like a feature that it is considering we want people to really think about their api's design.
On Friday, October 28, 2016 at 10:08:04 AM UTC-5, Rob Pike wrote:Go was always intended for programming at large scale, which includes working in large software environments, with large teams, and in the presence of complicating factors such as interoperating with other languages. The alias feature is directed at solving a problem that arises in that area, which is refactoring a package in an environment too large or complex to update all the dependents of a package at once. This problem is often seen as a versioning problem, but in monorepos versioning doesn't help, while aliases do.Now, some of Go's popularity is also because of its clarity and readability, but it is worth observing that those properties, which were also goals of the language, are sometimes in conflict with the need for programming at scale. There are other features of the language that are there for industrial-level work but clearly at odds with simplicity. Goto is the most obvious (it's present for machine-generated code). The verbosity of struct literals is another. The way interface embedding works, allowing redundancy if it's not used, is a third. There are more.What's really different in this conversation is that, for the first time, the community is seeing the difficulty of trying to decide what to do when a new issue raises such a conflict. If we today decided to start enforcing the need to put types on the fields of struct literals, there would be an outcry, but we would do it anyway, because the benefits outweigh the cost, high though the cost is.The alias feature is important, but it is also ugly. We know that. It is open to abuse. We know that. But we have been listening: the feature is very heavily restricted because of the many good points raised in the issue discussion. The possibility for abuse is greatly restricted, and the conversation that got us here was invaluable. But the conversation is behind us; now the time has come to try it out. If it turns out to be a real problem in practice, there are three months left to roll it back.But I don't think it will be a problem, because I believe the community will help make sure the abuses don't happen. If you see an alias appear in code where none is necessary, complain about it, publicly. Update golint to yell whenever the feature is used.Most important, explain to people what it is for: that, like goto, it is a necessary evil for program development in the modern world.-rob
--
You received this message because you are subscribed to the Google Groups "golang-dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email to golang-dev+unsubscribe@googlegroups.com.
On Wed, Nov 2, 2016 at 8:39 AM, <nice...@gmail.com> wrote:
> [...]
> Instead of giving you the benefit of the doubt, how about some bullets
> outlining concrete examples of how this will benefit all of us who also have
> extensive experience with Go but who don't see the same need?
Several examples have already been given in the proposal discussion
and in mailing list discussions. These examples are inevitably
complex. The nature of the problem is that it only becomes visible
when dealing with a complex set of packages. In simple cases simple
solutions are fine.
You can reject this example as overly complex. As I said earlier,
these problems only arise in complex situations. But they do arise,
and they must be solved. There are various awkward solutions.
Aliases are intended to be a simple solution. The simplicity can be
seen in the file
https://github.com/golang/net/blob/master/context/go18.go, which uses
aliases as currently expected to be in Go 1.8.
You received this message because you are subscribed to a topic in the Google Groups "golang-dev" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/golang-dev/OmjsXkyOQpQ/unsubscribe.
To unsubscribe from this group and all its topics, send an email to golang-dev+...@googlegroups.com.
Just throwing ideas here, could it be done at compile time instead of doing it in the sources?
go build --alias="golang.org/x/net/context:context"
That said, try to read the previous conversation & proposals before throwing ideas there.
On Thu, Nov 3, 2016 at 12:46 PM, Robert Griesemer <g...@golang.org> wrote:
Please add your suggestions to the proposal issue https://github.com/golang/go/issues/16339 - that is the right place to further this discussion. Thanks.- gri
On Thu, Nov 3, 2016 at 12:06 PM, <mikegl...@gmail.com> wrote:
Just throwing ideas here, could it be done at compile time instead of doing it in the sources?
go build --alias="golang.org/x/net/context:context"
--
You received this message because you are subscribed to the Google Groups "golang-dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email to golang-dev+...@googlegroups.com.
--
You received this message because you are subscribed to the Google Groups "golang-dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email to golang-dev+...@googlegroups.com.
I could not find this question answered in the proposal doc or discussion:
Can a package export a name from an "internal" package, i.e. a package with "internal" in the path name?
package foo;type A => myinternal.A
If so, then it is not true that referencing foo.A is semantically the same as importing "foo/internal/myinternal".A, since the latter can't be referenced outside of foo.
The points about making interfaces compatible if they have the same signature only fixes a subset of these problems. You still can't (or rather should not) make that work for non-interface types.