To summarize i am proposing 2 things:1) Removal of the new() builtin function
2) Removal of the &t{} construct.
I agree with the first proposal.
I haven't made a decision about the second proposal, but I'd like to point out that preventing &T won't be weird since &1 and &"a" are already not possible (for example). I cannot see how important are the pros of doing so, since I have never made a pointer just because it was one keystroke away, and this is not obvious to me that there are people who do so, so I'm waiting to hear others.
I agree with the first proposal if it will be applied in Go 2 and gofix (or any other tool) will replace new(T) with &T{}.
The compiler is only doing what the spec says. It's not some kind
of accident.
It's not "little"; it's *very* convenient to not have to introduce a
new variable
just so that we can use its address.
As pointed out by aram, the &t{} idiom is used commonly in deep nested structures. But isn't that fairly inefficient. That is you need to allocated space for a variable, than a pointer to variable, so every field, thats nested has a 4byte overhead. Isn't that unnecessary use of pointers?
The compiler is only doing what the spec says. It's not some kind
of accident.I am not saying that its an accident, I know it was written that way as i've stated. Its just that its exception to the general rule, which makes it inconsistent with the rest of the language.
It's not "little"; it's *very* convenient to not have to introduce a
new variable
just so that we can use its address.If i am not wrong, that is actually what the &t{} idiom is currently doing. I'm just making it explicit. If you really don't want to use a new variable you can capture that behavior in a function.
And i'm not saying i don't like pointers. I use them alot in c and c++. The problems is that it becomes a problem when we try to program concurrently, that is if they are used carelessly.
Though I must say that its not true that you have to create a function to create a pointer for every in your program, because you don't really need to create pointers that often.
Little sense this claim makes. The code for helloworld.go doesn't need pointers at all. Some apps/packages use pointers heavily and for perfectly good reasons. Some others even cannot be coded w/o pointers in a sane way. There's nothing generic about this and it can hardly be used as an argument for anything.-j
On Thu, Aug 2, 2012 at 11:35 AM, chl <chiah...@gmail.com> wrote:
To summarize i am proposing 2 things:1) Removal of the new() builtin function
Little sense this claim makes. The code for helloworld.go doesn't need pointers at all. Some apps/packages use pointers heavily and for perfectly good reasons. Some others even cannot be coded w/o pointers in a sane way. There's nothing generic about this and it can hardly be used as an argument for anything.-jIts kinda funny, but you are actually contradicting yourself, because your the one that said that we would need to write a function for every type. :p
If you need the pointers for the fields of the struct, you need the
pointers. If you don't, you're not using them. I don't see an inefficiency
in the use of the &T{} construct.
It's not inconsistent, it just not uniform, and that nonuniformity is in
service to more straightforward code. If that's the price, I'll have two.
Yes. That's what we don't want or need. The & is enough explicitness
for the job.
What, not only do I have to have an explicit variable, I have to
introduce a trivial function -- just to disallow &T{}?
That doesn't seem like a good idea to me. (There are /good/ reasons
for introducing constructor functions, but not liking the &T{} syntax
doesn't seem to me to be one of them.
If we're not creating pointers, then the whole proposal is irrelevant. It's
only pointerful structures that it applies to.
There's a place for a discussion about when, and when not, to be using
pointers, but the opening post is exactly about which ways to create
pointer values.
Chris
--
Chris "allusive" Dollin
Requiring that the construct
return me a pointer to a new piece of store initialised this way
be written as
make me a variable v initialised this way
return me a pointer to v
seems pretty transparently less straightforward. v is just a
placeholder variable with no other use, clutter to trip over.
And makes the code clunkier -- more verbose, with more to keep
track of. If every trivial pointer-to-struct construction "needs" a new
function, the fact that these is a function no longer tells us anything.
The current system allows us to recognise trivial constructions as
trivial, trivially.
Well, I don't need to choose the way I create a pointer [to a new
struct] -- I use &T{}. I've never needed the semantics that new gives
me, and I wouldn't consider using `v := T{...}; pv := &v` [or `return &v`]
because, well, why would I want to?
Uniformity is not automatically a virtue. Uniformity would dispense with
:=. Uniformity would require that pointer-receiver methods when applied
to a variable v would require writing (&v).method. Uniformity would have
all our integer literals written in octal (or hex, or decimal). Uniformity would
have us type each element of an argument list separately. Uniformity would
require that all mathematical expressions took exactly two simple
operands.
It's a tradeoff. It's tradeoffs all the way down.
It's about ways for programs in Go to create pointer values. You presented
three of the existing ones and said we should throw two of them away.
First, I need to say that this is not about new vs make, its something completely different.
Putting primitive types aside there are currently 3 ways for a person to creating a pointer to a struct type, t. Eg :
Example 1a = new(t)Example 2a = &t{}Example 3a1 = t{}a2 = &a1My proposal here is to get rid of the first and second example above.If I could drawn your attention to example 1. This is not a perfect way to create a pointer to a struct, because if your struct has any field which should be assign to values other than the default values you need to repeat yourself alot. Eg:Let t be:type t struct {a, b, c, d, e int}you'll need to do this:v := new(t)v.a = 1v.b = 2v.c = 3v.d = 4v.e = 5Notice that we had to repeat the variable name every single time, and that is in my view fairly repetitive. The normal way of creating a struct is less repetitive and is therefore, in my view, better.If I may now draw your attention to example 2. &t{} is an exceptional case, meaning that normally it should not work, but we've written the compiler in such a way that it works. There are really no arguments for allowing this exception other than, the fact it brings with it a little convenience. The cost of this construct though, is that, it makes it harder for a reader of the code to distinguish between a pointer to a t and a value t. Eg:Let t be define as previously defined.
s1 := &t{1, 2, 3, 4, 5}
s2 := t{1, 2, 3, 4, 5}This is easy to distinguish here because there is no code surrounding it, but if you imagine that this is one line in a page of code that is 1000's lines long, it becomes hard to determine if a variable is a pointer or an actual value. This problem is further exaggerated, if t is replaced with a longer name or when values for fields and field names are longer, as this drawn the readers attention away from the leading ampersand even more.The result of this proposal is that:1) all values and pointers will be created in the same way, reducing the cognitive load on the reader.2) removing the new() keyword, makes the language simpler.3) prevent people from using pointers unecessarily.4) draw attention to parts of the code that actually use pointers, to simplify debugging.Therefore, this 2 constructs (example 1, and example 2) should be removed. This however is not without its downsides.The result of this proposal will make it harder to create a pointer to a type t, because now if you want to create a pointer to a type t you'll have to do this:s := t{1, 2, 3, 4, 5}s1 := &sThis is inherently less efficient because you'll need to allocate space in memory, to store s and another to store a pointer to s.The other downside to this is that existing code would need to be changed. So I don't see this change happening in Go1. But probably in Go2.However, if you would look at this situation from a slightly different perspective, the cons to the proposal are actually pros in the majority of situations.First, the odd construct, although slightly more verbose, drawn the readers attention to it, making it easier for the reader to determine when a variable is a pointer.Second, it discourages people from using pointers when not needed. Using less pointers makes it easier to reason about code, and result in less bugs. Case in point:Let num(*int), be a function that adds 1 to the incoming value.n := 1num(&n)fmt.Println(n)because pointers are harder to create, people would use & more often when invoking a function that requires pointer. This allows the reader to determine, if the function changes the value without looking at the prototype of the function.When pointers are truly needed (linked list, trees) , people could create their own functions that create pointers. Eg:func NewInt(n int) *int {return &n}This kinds of functions are trivial to write, but are more powerful than a new() function that covers all cases. In the example above, NewInt() can create a *int, with any value, this is better than the the builtin new() function, if you are going to assign the value the pointer is pointing to to something other than the default value. It should be noted that, there are no performance penalty to this because small functions are inlined during compilation.
To summarize i am proposing 2 things:1) Removal of the new() builtin function
2) Removal of the &t{} construct.
1) Removal of the new() builtin function
'new(int)' -> '&int{}'
The major objection is that {} doesn't mean anything for an int.
Why are the braces there?
You don't need to use it, most people don't, but that doesn't mean it doesn't have a use.
No. Please don't revive a thread that has been dead for two years.
new isn't going away, it can't, it's part of the guaranteed specification for Go 1.
Maybe in other words then, leave "a := new(int)" as this is the only way to get pointer of int,but remove new for structs. Or any other solution that simplifies this and removes redundancy.
var i int; p := &i