Is new() really needed?

367 views
Skip to first unread message

ludius

unread,
Jul 22, 2010, 7:25:26 AM7/22/10
to golang-nuts
I've spent hours of mental energy deciding whether to use new() in my
codes or not... but I have to admit, I don't get it. Pardon my idiocy
but my question is why and when new() is used instead of the more
straightforward i:=0 or x:=X{} ?

Or maybe there's no mystery there but just a matter of preference. Is
it?

ludius

unread,
Jul 22, 2010, 7:33:56 AM7/22/10
to golang-nuts
Follow up... I know that new() returns a pointer and X{} creates a
value. But if I need a pointer, I can just use the & operator like
&X{} . So is there anything else new() does something special or
different? Or it's just there as a use-it-or-ignore-it function?
Again, I'm a newbie so bear with me.

Ian Lance Taylor

unread,
Jul 22, 2010, 7:47:57 AM7/22/10
to ludius, golang-nuts
ludius <meetl...@gmail.com> writes:

The main difference is that new() is the only way to get a pointer to an
unnamed integer or other basic type. You can write "p := new(int)" but
you can't write "p := &int{0}". Other than that, it's a matter of
preference.

Ian

bflm

unread,
Jul 22, 2010, 7:55:19 AM7/22/10
to golang-nuts
On Jul 22, 1:33 pm, ludius <meetlud...@gmail.com> wrote:
> Follow up... I know that new() returns a pointer and X{} creates a
> value. But if I need a pointer, I can just use the & operator like
> &X{} . So is there anything else new() does something special or
> different? Or it's just there as a use-it-or-ignore-it function?
> Again, I'm a newbie so bear with me.

The & operator provides the address of an existing entity or of a
(newly allocated) literal. But you can't write e.g. 'a := &123', you
have to write 'a := new(int); *a = 123;'. Without 'new' it wouldn't be
possible to do such things as (explicitly) heap allocating an integer,
string ...

chris dollin

unread,
Jul 22, 2010, 8:04:04 AM7/22/10
to bflm, golang-nuts
On 22 July 2010 12:55, bflm <befeleme...@gmail.com> wrote:

> The & operator provides the address of an existing entity or of a
> (newly allocated) literal. But you can't write e.g. 'a := &123', you
> have to write 'a := new(int); *a = 123;'. Without 'new' it wouldn't be
> possible to do such things as (explicitly) heap allocating an integer,
> string ...

As it hinted at in your first line above, not so:


--
Chris "allusive" Dollin

roger peppe

unread,
Jul 22, 2010, 8:04:10 AM7/22/10
to Ian Lance Taylor, ludius, golang-nuts
On 22 July 2010 12:47, Ian Lance Taylor <ia...@google.com> wrote:
> The main difference is that new() is the only way to get a pointer to an
> unnamed integer or other basic type.  You can write "p := new(int)" but
> you can't write "p := &int{0}".  Other than that, it's a matter of
> preference.

AFAICS, p := new(T) is exactly equivalent to:

var p *T; {var i T; p = &i}

but it's more convenient sometimes.

personally, i still think that new's functionality should be subsumed
into make.

Paulo Pinto

unread,
Jul 22, 2010, 8:16:34 AM7/22/10
to golang-nuts
I agree.

I still don't understand why there are two ways of allocating memory
together with two ways of creating variables.

new vs make vs &{} syntax

var some_var = value vs some_var := value

It feels a bit perlish to me (TIMTOWTDI).

--
Paulo

On Jul 22, 2:04 pm, roger peppe <rogpe...@gmail.com> wrote:

Scott Lawrence

unread,
Jul 22, 2010, 5:23:27 PM7/22/10
to Paulo Pinto, golang-nuts
From "Effective Go" (http://golang.org/doc/effective_go.html) - make
"creates slices, maps, and channels only." I suppose these are really
rather different (implementation wise) from other objects, and a
second function is justified.

For &{} - do you not have to provide initial values with that?


--
Scott Lawrence

Miek Gieben

unread,
Jul 22, 2010, 5:38:31 PM7/22/10
to golang-nuts
[ Quoting Scott Lawrence in "Re: [go-nuts] Re: Is new() really n"... ]

> From "Effective Go" (http://golang.org/doc/effective_go.html) - make
> "creates slices, maps, and channels only." I suppose these are really

<snip>

And why is this? Can't make (or new) be made smarter so that it checks
to see what needs to be created and just does it?

Regards,
Miek

signature.asc

Russ Cox

unread,
Jul 22, 2010, 5:54:34 PM7/22/10
to Robson França, golang-nuts
we have both make and new mainly for
pragmatic reasons.

new(T) returns *T.
so it can't return chan int, which doesn't have the form *T.
so another operator is needed.

for a short time, we tried getting by with just make,
and make(*T) was like new(T) is today.
people found it too surprising coming from
c, c++, and java.

russ

Paulo Pinto

unread,
Jul 22, 2010, 5:56:45 PM7/22/10
to golang-nuts
I am quite familiar with that page, and with the usual email that everyone new on this
list gets when it complains about it.

From my point of view, if the Go compiler was a bit smarter, new and make could be merged
into a common language construct. It is just a matter where to put the complexity, on the compiler itself,
or on the code the developers have to write.

--
Paulo

ptolomy23

unread,
Jul 22, 2010, 6:24:31 PM7/22/10
to Paulo Pinto, golang-nuts
On Thu, Jul 22, 2010 at 2:56 PM, Paulo Pinto <paulo....@gmail.com> wrote:
I am quite familiar with that page, and with the usual email that everyone new on this
list gets when it complains about it.

From my point of view, if the Go compiler was a bit smarter, new and make could be merged
into a common language construct. It is just a matter where to put the complexity, on the compiler itself,
or on the code the developers have to write.

That doesn't make much sense to me.
"new" and "make" don't make my life or code any more complicated, as far as I'm concerned.

new(T) allocates.
make(T) allocates and constructs built-ins.

Different operations, and a distinction that I'm happy to make.
If "make" took over the role of "new", that wouldn't be the compiler being smarter,
that would be "make" being too broad in purpose for my taste.


Although, if we had generics, new could just be:

func new(T type) *T {
    var x T
    return &x

I don't use "new" very much; literals are superior in most cases.
It isn't strictly necessary, but it doesn't hurt anything and it acts as convenient shorthand
for those times when all you want to do is allocate. 

Paulo Pinto

unread,
Jul 23, 2010, 1:09:10 AM7/23/10
to golang-nuts
Funny that most other languages seem to do just with one allocation function,
hence the reason lots of people keep asking why new and make do exist.

I can live with it, but for me it is the compiler being made simpler.

Ken Thompson

unread,
Jul 23, 2010, 1:23:19 AM7/23/10
to Paulo Pinto, golang-nuts
they are different functions.

new(T) returns type *T
make(T) returns T

it is true that the compiler could figure it out
with some common syntax, but it would be wrong.

Peter Bourgon

unread,
Jul 23, 2010, 2:49:53 AM7/23/10
to golang-nuts
On Fri, Jul 23, 2010 at 7:23 AM, Ken Thompson <k...@google.com> wrote:
> they are different functions.
>
> new(T) returns type *T
> make(T) returns T

We understand the distinction, and we understand that there is some
underlying issue that makes it convenient for the language developers
to have both new() and make(). But I think this conversation keeps
going around and around because, from a user perspective, there's no
apparent reason to require a special function to create a value/stack
instance of only _certain_types_. Given that we seem to have come to
the understanding that the compiler _could_ figure things out in
context, appeals to what's going on behind the scenes don't hold much
weight, in this frame of reference. I believe that, to many of us,
make() is a needless complication in the language.

There are plenty of sycophants on this list who will say it works and
it's "not that bad" and etc., but the number of things in the language
that garner that reaction are quite numerous... in aggregate, it seems
difficult to justify their existence.

Russ Cox

unread,
Jul 23, 2010, 2:59:47 AM7/23/10
to peter....@gmail.com, golang-nuts
if it makes you feel better, pretend that there were
four ways to create new things: new(T) allocates memory
and returns a *T, makechan(T=channel type) makes a
channel, makemap(T=map type) makes a map, and
makeslice(T=slice type, size) makes a slice.
now pretend that we just simplified the last three into
one operation. pretty good, huh? ;-)

> There are plenty of sycophants on this list who will say it works and
> it's "not that bad" and etc., but the number of things in the language
> that garner that reaction are quite numerous... in aggregate, it seems
> difficult to justify their existence.

what else are we talking about?

russ

chris dollin

unread,
Jul 23, 2010, 3:08:46 AM7/23/10
to r...@golang.org, peter....@gmail.com, golang-nuts
On 23 July 2010 07:59, Russ Cox <r...@golang.org> wrote:
>
>> There are plenty of sycophants on this list who will say it works and
>> it's "not that bad" and etc., but the number of things in the language
>> that garner that reaction are quite numerous... in aggregate, it seems
>> difficult to justify their existence.
>
> what else are we talking about?

I don't know what else we /are/ talking about, but Peter
/might/ have been alluding to absence of conditional
expressions, the capitalisation rule for exports, the
semicolon rule & its consequences, the restrictions on
the types of map keys, the absence of generic types,
or the absence of dynamic code loading. All of which seem
to be speed bumps for at least some people.

I'd rather he'd been explict rather than just saying "a number
of things" (0? 1? 2? i?) and hadn't IMAO unnecessarily turned
up the emotional temperature with "sycophants".

Chris

--
Chris "allusive" Dollin

Peter Bourgon

unread,
Jul 23, 2010, 3:25:15 AM7/23/10
to golang-nuts
On Fri, Jul 23, 2010 at 8:59 AM, Russ Cox <r...@golang.org> wrote:
> if it makes you feel better, pretend that there were
> four ways to create new things: new(T) allocates memory
> and returns a *T, makechan(T=channel type) makes a
> channel, makemap(T=map type) makes a map, and
> makeslice(T=slice type, size) makes a slice.
> now pretend that we just simplified the last three into
> one operation.  pretty good, huh?  ;-)

Again, I understand what you're trying to say, but it's still reading
as post-hoc justification for the status quo. Why do we need a special
function to create & initialize channels, maps and slices? Why can't I
just _create_ them, same as any user-defined struct or primitive type?
I'm sympathetic to wanting to keep the compiler and toolchain simple,
but only to a point; only so long as it's a cost-benefit analysis, and
not simply deferring to one side consistently.

>> There are plenty of sycophants on this list who will say it works and
>> it's "not that bad" and etc., but the number of things in the language
>> that garner that reaction are quite numerous... in aggregate, it seems
>> difficult to justify their existence.
>
> what else are we talking about?

As Chris notes, my apologies for politicizing things with loaded
language. It wasn't my intention. And to be clear, I haven't given
this enough deep thought to really form a persuasive argument. But as
time goes on, and as I read the list and coagulate a "sense" of the
language in my head, I perceive a number of things that I consider
important get casually and continuously brushed to the side as either
working fine as-is or not important. Chris hits on some major ones, to
which I will add: the often confusing semantics surrounding
interface{}; that parallelization via GOMAXPROCS isn't even close to
as fast as it should be at this stage; that the GC is still apparently
MIA; a general reliance on copy-and-paste helper functions (for
example, why a string can't automatically satisfy a ReadClose); and a
number of package-specific gripes, notably that a number of user
requests for the JSON and HTTP packages have gone ignored for almost
the lifetime of the language.

Russ Cox

unread,
Jul 23, 2010, 3:39:25 AM7/23/10
to peter....@gmail.com, golang-nuts
> Again, I understand what you're trying to say, but it's still reading
> as post-hoc justification for the status quo. Why do we need a special
> function to create & initialize channels, maps and slices? Why can't I
> just _create_ them, same as any user-defined struct or primitive type?

I don't know what you mean by create.
You _can_ just create them: just call make.
What code would you like to write instead?

var ch chan int

? How does that work? What if it's in a new (zeroed) struct?
We thought about how to do this for a while
and don't see a way to do it. Do you?

> language in my head, I perceive a number of things that I consider
> important get casually and continuously brushed to the side as either
> working fine as-is or not important.

Most of your list are things we've admitted aren't working fine
and are important, but we are a small team with limited resources.
If any of these is a significant pain point for you, one option is
to roll up your sleeves and write some code.

Hitting a few, reordered:

> Chris hits on some major ones, to
> which I will add: the often confusing semantics surrounding
> interface{};

I don't know exactly what this means - probably the difference
between storing *T vs T in an interface - but interfaces are a new
concept. I don't think it's surprising or even problematic that
people coming from other languages would find certain aspects confusing,
as long as they make sense once explained.

> a general reliance on copy-and-paste helper functions (for

> example, why a string can't automatically satisfy a ReadCloser);

Because string doesn't have Read and Close methods.
This is the only design issue you listed, and it's simply not that
kind of language. Go aims to be small, not syntax-sugary sweet.

> that parallelization via GOMAXPROCS isn't even close to
> as fast as it should be at this stage; that the GC is still apparently

> MIA; and a


> number of package-specific gripes, notably that a number of user
> requests for the JSON and HTTP packages have gone ignored for almost
> the lifetime of the language.

All but one of these are things we know about and are going to
be addressed in time (see comment above about resources).
The exception is JSON: I don't know what you mean.
I think package json is in good shape and don't know about any
ignored user requests there. Search on the issue tracker
in open issues for json only turns up issues related to the
template package (because it was inspired by a template
package named json-template). Details?

Russ

chris dollin

unread,
Jul 23, 2010, 3:46:15 AM7/23/10
to peter....@gmail.com, golang-nuts
On 23 July 2010 08:25, Peter Bourgon <peterb...@gmail.com> wrote:

> Again, I understand what you're trying to say, but it's still reading
> as post-hoc justification for the status quo. Why do we need a special
> function to create & initialize channels, maps and slices? Why can't I
> just _create_ them, same as any user-defined struct or primitive type?

Like this?

x := map[string]int{"hello": 1, "world": 16}
y := []int{1, 1, 2, 3, 5, 8}

However, that syntactic form doesn't help if you want to
specify a slice of type T, length L, and capacity C; or a map
sized to hold N elements "well". make does that. The functionality
/could/ be snuck into the value constructors with some special
extra rules, but then that would just be moving the bump in the
carpet around.

make does something that the existing value constructors don't
do but that one does want to do.

There's a case for

chan whatever{buffer size}

but I'm not sure that's any better.

> ... the often confusing semantics surrounding
> interface{};

?Unpack?

> that the GC is still apparently MIA;

I thought the was a GC implementation but that it wasn't
very fancy yet.

Ian Lance Taylor

unread,
Jul 23, 2010, 3:49:57 AM7/23/10
to ptolomy23, Paulo Pinto, golang-nuts
ptolomy23 <ptol...@gmail.com> writes:

> new(T) allocates.
> make(T) allocates and constructs built-ins.

I think there is good reason to question why we have both new and &T{}.

I think there is good reason to question why we have a make function
that works with slices and maps, and T{}.

However, there is a clear difference between new and make. You can not
construct a new channel with new. You can only construct a pointer to a
nil channel. The only way to construct a new channel is with make. We
can't write make in terms of new and we can't write new in terms of
make. They do not duplicate each other.

And the only way to construct a channel is to use make. Recall that
declaring a new variable of channel type gives you a nil channel.

If we want to eliminate make, then we have to to permit the T{} syntax
to work with channels. c := chan int{}. It's a little weird, but we
could probably do it.

If we want to eliminate new, I don't think it's reasonable to require
people to name a variable and then takes its address. Therefore, we
would have to extend the &T{} syntax to permit any type, not just
composite types. That is, we would have to permit &int{}, and we would
have to permit &chan int{}. And since the latter would presumably
actually make a channel, there would then be no way to get a pointer to
a nil channel without giving it a name.

In short, when you look at all the details, the functions are not quite
as much duplicates as they first appear. There is probably some way to
simplify the language here. But it's not a straightforward change.

I would be happy to see complete suggestions.

Ian

Cory Mainwaring

unread,
Jul 23, 2010, 6:22:02 AM7/23/10
to Ian Lance Taylor, ptolomy23, Paulo Pinto, golang-nuts
The only major snag I seem to hit is that interfaces aren't powerful enough for me. (Make it so interfaces can have return types that satisfy an interface, rather than are an interface)

New and make make sense to me, and wasn't even weird. Slices and Chans are new from Java and C++, so adding one more concept for them doesn't increase overhead. new(T) on everything would be interesting though. And I think, now that I've been in the language having new(T) with optional arguments for Slice/Chan/Map cases wouldn't be so bad (or the same with make instead). It would be slightly confusing at first, given that overloading isn't allowed, but there are several cases of the built-ins being allowed to do things we aren't, though the specific cases just left my head.

As for the other stuff, I don't miss generics 99% of the time. the other 1% is when I try to separate my packages more and find out that interfaces aren't powerful enough for me. GC is fine for now, so long as they are working on a more sophisticated one that doesn't add overhead and hopefully reduces it. Ternary statements just makes for confusing code in my opinion. 

I don't know what semicolon fallout is happening, so I won't try to give a view on it. And, I personally can't think of a good reason for dynamic code loading other than convenience, but that's not necessarily a reason to have it be a non-issue, I don't know in this case as well.

All in all, Go is a work in progress, and has some issues, but it's most definitely a fun language to use, and my only real gripe is in paragraph one. There are issues, but for the most part they are either on the TODO list or really aren't important.

roger peppe

unread,
Jul 23, 2010, 7:17:30 AM7/23/10
to Cory Mainwaring, Ian Lance Taylor, ptolomy23, Paulo Pinto, golang-nuts
On 23 July 2010 11:22, Cory Mainwaring <olr...@gmail.com> wrote:
> The only major snag I seem to hit is that interfaces aren't powerful enough
> for me. (Make it so interfaces can have return types that satisfy an
> interface, rather than are an interface)

that's quite hard to do in general.
i think you're talking about allowing something like this:

type Copier interface { Copy() Copier }
type Foo struct { x int }
func (f *Foo) Copy() *Foo { return &Foo{f.x} }
var c Copier = &Foo{}

the main difficulty is that, unlike some other
languages, all types are not the same size in Go,
so a function returning a word sized value (Foo.Copy)
cannot stand in for a function returning a double-word sized
value (Copier.Copy).

the above example isn't too hard - the conversion could
insert a shim function for Copy that turns the returned
*Foo value into a Copier interface - but why should
a singleton return value be special? surely this should
be allowed too:

type MultiCopier interface { MultiCopy(n int) []MultiCopier }
func (f *Foo) MultiCopy(n int) []*Foo {
r := make([]*Foo, n)
for i := range r {
r[i] = f.Copy()
}
return r
}

if *Foo is to satisfy the MultiCopier interface, then the
[]*Foo value has to look like []MultiCopy to the caller
of MultiCopy. there's no way of doing that without
copying the slice, and that is not only inefficient,
if breaks the reference semantics of the slice.

return &Foo{f.x} }

a slice of MultiCopier values does

roger peppe

unread,
Jul 23, 2010, 7:48:35 AM7/23/10
to Cory Mainwaring, Ian Lance Taylor, ptolomy23, Paulo Pinto, golang-nuts
oops, ignore my last two lines.

Cory Mainwaring

unread,
Jul 23, 2010, 11:15:23 AM7/23/10
to roger peppe, Ian Lance Taylor, ptolomy23, Paulo Pinto, golang-nuts
given a special syntax so that one could differentiate between wanting to satisfy an interface and wanting to return an interface, it wouldn't be so bad. When you invoke a Copy() on a variable of type Copier, you get a pointer to a Copier, rather than struct Foo, just like every other interface. It could potentially be a bit confusing, but I would think that it would be ok, since the entire point of interfaces is that the code built around the interface cares about nothing but the functions that the interface can invoke, rather than the underlying structure.

Of course, I can already do this with:

type Copier interface { Copy() interface{} }
type Foo struct { x int }
func (f *Foo) Copy() interface{} { return &Foo{f.x} }
var c Copier = &Foo{}

But then my code get ugly with lots of x.(Copier) going around.

As for the slice thingy, I would think it's no different, since I can easily turn it into an interface{} value.

type MultiCopier interface { MultiCopy(int) []interface{} }
func (f *Foo) MultiCopy(n int) []interface{} {
   r := make([]interface{}, n)
   for i := range r {
       r[i] = f.Copy()
   }
   return r
}

However, that's ugly, and again, my code would be riddled with type assertions after every Copy() or MultiCopy(). So, in skipping that, just type assert the *Foo to MultiCopier. If it comes back true, *Foo = MultiCopier, and can then skip the type assertions and convert easily.

As for reference semantic, either []*Foo satisfies []MultiCopier, or []Foo satisfies []MultiCopier, since those two types are supposedly separate. One of them would satisfy (assuming the easier to convert, which I would guess is the pointer array, as it can just be type asserted rather than referenced through to get the MultiCopier version of it).

I could be wrong completely, but if I don't think it's too far a leap. And it would pretty much eliminate any need or want for generics if it's speedy upon implementation. interface{} is a generic type, as anything satisfies it, but it's also cumbersome (more so than templates) because of all of the type asserting one has to do to make it work for you. If the above examples could be built just using things that satisfy the interfaces, rather than having to return interface values, you could separate all links to interfaces from the things that implement them, without the ugliness and unsafeness of interface{}.

roger peppe

unread,
Jul 23, 2010, 12:07:39 PM7/23/10
to Cory Mainwaring, Ian Lance Taylor, ptolomy23, Paulo Pinto, golang-nuts
On 23 July 2010 16:15, Cory Mainwaring <olr...@gmail.com> wrote:
> type Copier interface { Copy() interface{} }

type Copier interface { Copy() Copier }

is fine, with no x.(Copier) necessary.
the Foo method would have to return Copier
rather than *Foo however.

> As for the slice thingy, I would think it's no different, since I can easily
> turn it into an interface{} value.
> type MultiCopier interface { MultiCopy(int) []interface{} }
> func (f *Foo) MultiCopy(n int) []interface{} {
>    r := make([]interface{}, n)
>    for i := range r {
>        r[i] = f.Copy()
>    }
>    return r
> }
> However, that's ugly, and again, my code would be riddled with type
> assertions after every Copy() or MultiCopy(). So, in skipping that, just
> type assert the *Foo to MultiCopier. If it comes back true, *Foo =
> MultiCopier, and can then skip the type assertions and convert easily.

> As for reference semantic, either []*Foo satisfies []MultiCopier, or []Foo
> satisfies []MultiCopier, since those two types are supposedly separate.

i'm not quite sure what you mean here.
neither of those two assertions are necessarily true. one
crucial attribute of a slice is its element size, and *Foo,
MultiCopier and Foo may all have different sizes.

that means that a copy *must* be made, because the
caller always expects a slice of MultiCopier values
(double-word sized) to be returned. not to mention
the fact that an interface value holds its type as well
as the value itself.

if you make a copy, then you break the reference
semantics.

> If the above examples
> could be built just using things that satisfy the interfaces, rather than
> having to return interface values, you could separate all links to
> interfaces from the things that implement them, without the ugliness and
> unsafeness of interface{}.

as i pointed out above, you don't have to return interface{},
you can return the particular interface type instead.

but that does mean that the object implementing the interface
must be aware that it is implementing that interface.

Cory Mainwaring

unread,
Jul 23, 2010, 12:15:03 PM7/23/10
to roger peppe, Ian Lance Taylor, ptolomy23, Paulo Pinto, golang-nuts
And thus it's no better than having an "implements" syntax hanging over your head. The point of interfaces is to have the structures implicitly satisfy interfaces, and I would submit that by extension, the structures shouldn't have to even know about the existence of interfaces to satisfy them. I see the point about the slice now, though it could be conceivable to avoid the copying overhead in enough of the instances that I would prefer to see it implemented rather than not.

roger peppe

unread,
Jul 23, 2010, 12:40:39 PM7/23/10
to Cory Mainwaring, Ian Lance Taylor, ptolomy23, Paulo Pinto, golang-nuts
On 23 July 2010 17:15, Cory Mainwaring <olr...@gmail.com> wrote:
> And thus it's no better than having an "implements" syntax hanging over your
> head. The point of interfaces is to have the structures implicitly satisfy
> interfaces, and I would submit that by extension, the structures shouldn't
> have to even know about the existence of interfaces to satisfy them.

i agree with that, but i don't see a solution.

> I see
> the point about the slice now, though it could be conceivable to avoid the
> copying overhead in enough of the instances that I would prefer to see it
> implemented rather than not.

AFAICS the only instance where you could avoid the copying overhead
is when the result is []interface{} and the original type is a slice
of a pointer type.

that's really not worth doing, surely.

Cory Mainwaring

unread,
Jul 23, 2010, 1:05:10 PM7/23/10
to roger peppe, Ian Lance Taylor, ptolomy23, Paulo Pinto, golang-nuts
It's conceivable to avoid building slices of interfaces by having an extra interface to handle that.

type MultiCopySlice interface {
    At(int) Copy
    Len() int
    MultiCopy
}
type MultiCopy interface { MultiCopy(int) MultiCopySlice }

It's not the best, but it certainly dodges a bit of overhead. Idk what to do to optimize it so that copying need never occur, but it still seems the most elegant way to correct the problem of generics and keeping separate packages separate when there are types based on structures.

David/Jones

unread,
Jul 23, 2010, 1:49:42 PM7/23/10
to golang-nuts


On 23 Jul., 09:49, Ian Lance Taylor <i...@google.com> wrote:
I'm quite much on your side there - just that I think that new and
make are just fine. I would rather eliminate the T{} syntax, since I
feel it is inconsistent with new being a word and T{} being some fancy
struct literal. new and make are both words and hence give a much more
consistent syntax.
a := new(T)
b := make(T, 0, 2, 3 )
c := make( chan bool ) // I love the way "make chan bool" sounds.

vs

a := new(T)
b := T{ 0, 2, 3 }
c := chan bool{} // Doesn't sound good. Doesn't even look good.

Forget about that sound argument though ; )

> Cory Mainwaring
> The only major snag I seem to hit is that interfaces aren't powerful enough
> for me. (Make it so interfaces can have return types that satisfy an
> interface, rather than are an interface)

Well, I am missing something with interfaces/structs too - but I don't
agree that doing what you want is a good idea.

Doing what you say would allow the following:

type Container interface {
Get() interface{}
Set(interface{})
}

type funny struct { ... }

func (f *funny) Get() int { ... }
func (f *funny) Set( s string ) { ... }

type even_funnier struct { ... }

func (f *even_funnier) Get() string { ... }
func (f *even_funnier) Set( i int ) { ... }

func main() {
var f,e Container
f = new(funny)
e = new(even_funnier)
s := f.Get()
f.Set(s)
s = e.Get()
e.Set(s)
}

According to the Cointainer interface, this code is perfectly valid.
But as you can see, it is not.
+what roger said.

Cory Mainwaring

unread,
Jul 23, 2010, 2:21:20 PM7/23/10
to golang-nuts
It's a case that only occurs with empty interfaces. Disallowing empty interfaces to be implicitly satisfied would be simple enough, especially if a certain syntax was required to have the interfaces be satisfied rather than literal. Maybe a "satisfies" keyword or something.

A good argument against T{} would be the chan bool{} situation. It reads "channel of bool literals". Not "channel of bools literal". For the latter case, you would need (chan bool){} or something to keep it consistent. bool{} is already used (as with all other types) as the literal syntax, so having it work on channels without the parenthetical notation should be creating channels of literals, which I would submit is bad.

If the only reason for keeping new around is to make people more comfortable, I would suggest that make maintain functionality for make(*T) and have new be faded out eventually.

Scott Lawrence

unread,
Jul 23, 2010, 6:13:49 PM7/23/10
to Cory Mainwaring, golang-nuts
On 7/23/10, Cory Mainwaring <olr...@gmail.com> wrote:
> If the only reason for keeping new around is to make people more
> comfortable, I would suggest that make maintain functionality for make(*T)
> and have new be faded out eventually.

But make() implies - both because of its use with channels/slices and
its name - that it does some kind of additional processing to ensure
that the returned object makes sense. I would like make() be
'overloadable' in a way, so that make(*T,...) called make_T (...) if
it existed, and otherwise new(T). (And then new() would probably fade
out by convention.)

--
Scott Lawrence

mg

unread,
Jul 25, 2010, 4:11:40 AM7/25/10
to golang-nuts
On Jul 24, 5:13 am, Scott Lawrence <byt...@gmail.com> wrote:
> I would like make() be 'overloadable' in a way,
> so that make(*T,...) called make_T (...) if
> it existed, and otherwise new(T).

Hmmm... I'd like it to also make copies of slices. ;-)

type S []T

func make_S(s S, c int) (r S) {
        l := len(s)
        if l > c {
                l = c
        }
        r = make(S, l, c)
        copy(r, s)
        return
}
Reply all
Reply to author
Forward
0 new messages