Groups keyboard shortcuts have been updated
Dismiss
See shortcuts

"The Language I Wish Go Was"

499 views
Skip to first unread message

MCM112

unread,
Oct 21, 2010, 8:46:26 AM10/21/10
to golang-nuts
I recently stumbled across this article at:
http://journal.stuffwithstuff.com/2010/10/21/the-language-i-wish-go-was/

I thought it might be prudent to post it here to hear the views of the
go community on some of the points raised by the author.

Cheers,

Ben

Corey Thomasson

unread,
Oct 21, 2010, 9:13:09 AM10/21/10
to MCM112, golang-nuts
Some of those points are invalid (block arguments for example, are
just another form of closures, which go has). The rest have been
discussed, and discussed, and discussed on the mailing list.

Andrew Gerrand

unread,
Oct 21, 2010, 9:15:48 AM10/21/10
to MCM112, golang-nuts

It's a long post that proposes adding a lot of things to the language.
I think the author picked a good title; he wants a language that is
not Go.

Go is a (very) small language, and IMO that is one of its major
strengths. Features are only introduced after they are deemed
essential.

Andrew

peterGo

unread,
Oct 21, 2010, 11:53:28 AM10/21/10
to golang-nuts
Ben,

On Oct 21, 8:46 am, MCM112 <m...@stickyeyes.com> wrote:
> I recently stumbled across this article at:http://journal.stuffwithstuff.com/2010/10/21/the-language-i-wish-go-was/

The author probably likes stuff like this too.

Giant Knife 16999 - Wenger Swiss Army Knife
http://www.wengerna.com/giant-knife-16999

Peter

nsf

unread,
Oct 21, 2010, 11:54:22 AM10/21/10
to golan...@googlegroups.com

Yeah, like "I want to stick in a bunch of features to the Go", but as
Andrew has pointed out, that won't be the Go anymore. IMHO the author
of that article doesn't really realizes that if he will stick in
templates _and_ operator overloading in any language it will become
a mess. It is inevitable. I mean really, we have a language that has
(almost) all these "nice" features and it is called D. And no one uses
D, because it is overcomplicated and bloated.. But you know, it
compiles faster than Go, but that's no the only reason why we love Go.

Being simple is a very hard property to achieve, and Go is the closest
thing we have today.

Of course Go has its own issues, like recent proposal of a new built-in
"append" function showed us, which btw removes the need for a "vector"
package mentioned in article. But let's be honest. Go is good enough and
adding new features now should be a strictly "de facto" thing. I mean
when we want to add something we must have at the same time enough
cases which this new feature solves and extra steps should be
considered to make sure that the solution is generic enough to be
included in the language. Let's take me for example. Currently I have
one major Go app (> 5k loc) - gocode, and many small ones. And the
only case where I had to use very evil copy&paste technique was exactly
the vector-like append functions.

Experience in other programming languages tells me that all you need
most of the time is a vector and a hash table, because these two has
the most interesting properties (vector is a contiguous chunk of memory
and linear/streaming memory access patterns are preferred on modern
CPUs, and map has insertion/lookup complexity close to O(1)). Take a
look at most of the scripting languages, almost all of them has two
types of built-in containers, it is a vector and a hash table. What I
mean here is that maybe (really, maybe) we don't need generics at all.

On the other hand there are few cases where having an optimal sort
function is a big win. And current "sort.Interface" is not a solution
to that, it will always be slower than C's qsort which is slower than
C++'s std::sort. Also we don't have any kind of generic binary search,
which is sad. I don't think that adding built-in function for each of
those cases are a good idea, but for some.. maybe.

That's what I think regarding most painful topic of the Go - generics..
Let's see what else in that article:

- Named/keyword args - I think author proposes some kind of a name
mangling and compile-time code generation features. Crap.

- Block arguments - they're nice. But it's pure syntax sugar for
calling functions where the last argument has a function type. Syntax
sugar needs a lot of arguments to be considered for adding to the
language, IMHO.

- Operator overloading - makes language unreadable, especially if mixed
with templates. Also requires other considerations like "reference"
types (see C++). In theory is simple, in practice complicates a
language a _lot_.

- Tuples - maybe, but python experience tells me that they are a very
bad duplication for structs. Once you want to have a name for each of
the tuple's components, you're screwed. Better leave them out.

- Unions - I miss them, at least for my go lemon parser generator port.
C's and D's versions have no problems with lemon, because they both
have unions. In Go I have to use interface{} magic, which has bad
performance properties.

- Constructors - my experience shows me that they are useless. First of
all they don't work if you don't have function overloading, because
obviously for some types there is more than one way to initialize
them. And function overloading adds another layer of complexity and
ambiguity. Secondly, the problem with error handling. People will
want to write myFunc(MyObject(1, 2, 3)) and then they will complain
that it's not possible, because constructor returns multiple values
(we need to handle errors, right.. ugh.. exceptions I forgot). Crappy
features, please don't even consider it.

- Eliminating nil - I'm a C guy, nulls are ok for me. Go solves the
most nasty problem btw, it doesn't allow programmers to use 0 as nil.
The problem is addressed in C++0x as well, but it's too late for that
language.

- Exceptions - some people keep telling me that they are a superior way
of handling errors. Other people (including few very famous
programmers like John Carmack) tend to avoid them. I don't understand
them as well. Having panic/recover is fine for me as long as they
don't introduce additional language statements (hello to
try/catch/finally, the most horrible thing I've ever knew about
programming languages) and as long as Go's standard library doesn't
force me to use them.

- Generics - I've already said enough about them in the beginning.

- Uniform Access - who? Bertrand Meyer? OOP guy? I think he is nuts. In
fact every person who seriously considers OOP as a valid term is
nuts.

Summary: I dunno... A long answer to the long article.

Russ Cox

unread,
Oct 21, 2010, 12:55:19 PM10/21/10
to m...@stickyeyes.com, golan...@googlegroups.com
> Eliminating nil

There was a very long discussion about this last year
on this mailing list. No one had any proposals that
worked and left the language intact.

> Exceptions

http://blogs.msdn.com/b/oldnewthing/archive/2004/04/22/118161.aspx
http://blogs.msdn.com/b/oldnewthing/archive/2005/01/14/352949.aspx

Having to write and then maintain codereview.py
has only made me more aware of how right he is.

Russ

Namegduf

unread,
Oct 21, 2010, 1:27:36 PM10/21/10
to golan...@googlegroups.com
On Thu, 21 Oct 2010 05:46:26 -0700 (PDT)
MCM112 <m...@stickyeyes.com> wrote:

It's nice that they've tried the language and seen what they thought,
but I can't say I found the post particularly illuminating. The central
problem that, in my view, makes it an unsatisfactory review is that a
number of the issues they raise are handled in Go by common idioms, and
they haven't reviewed their suggestions against these idioms, at least
not as explictly and in as much detail as I think would be required to
be able to tell if their ideas actually provide benefit.

The alternative for "scoped behaviour" in their example is defer, which
is not discussed (well), and the provision of New* functions replaces
constructors with a more explicit form; their request for constructors
needs to be directly compared against this. Their section on error
handling is very sparse on discussion of whether the explicitness of
the handling is good or bad, which is the primary change exceptions
make, and also lacks a discussion of the value or lack thereof of
banning, by convention, panic()/exception-like behaviour across package
boundaries, another important idiom.

This might just be my opinion, but I don't think future-proofing, as
they describe it, is an idiom in Go, either. They should directly
compare the uniform access feature against a lack of any such
future-proofing, not against speculatively wrapping everything. I feel
this would be hard to prove reliably either way. My personal opinion is
one of dubiousness that the cost of modifying every call site in the
event changes happen in one place beat the costs of mitigating it
*everywhere* pre-emptively.

Another of their points seem not quite thought through; their point
about "type safety without coupling" would only apply if the error from
their function was the only error the function it was passed to
returned, and their function only ever returned one type of error.
It seems unlikely to be valid in real code, where os.Error is common.

Finally, their suggestion for multiple types for a return value is just
bad; it appears to create both additional syntax and be longer, and they
suggest it would be more efficient for "avoiding creating a variable"
without actually suggesting an implementation so the other performance
effects could be examined; I'd think this would require returning
something like an interface to make the type switch possible, which
seems like it would have significant effects of its own.

All in all... I think it would be a better review if the author had
spent more time with the language, possibly working with other people's
code, before judging the language, and perhaps thought a little harder
in some cases. It is hard to begrudge them this, although I would have
suggested not writing the review if they weren't willing to seriously
consider what is idiomatically used as alternatives to the desired
features, and be quiet about performance when they haven't analysed
what their idea would cost to implement. Perhaps my standards for blogs
are too high, though.

It does seem, though, that the language they want is not Go.

unread,
Oct 21, 2010, 1:50:23 PM10/21/10
to golang-nuts
On Oct 21, 5:54 pm, nsf <no.smile.f...@gmail.com> wrote:
> - Block arguments - they're nice. But it's pure syntax sugar for
>   calling functions where the last argument has a function type. Syntax
>   sugar needs a lot of arguments to be considered for adding to the
>   language, IMHO.

I don't think the mentioned "block arguments" are syntactic sugar,
because they are able to ensure certain semantic properties (e.g:
always closing a file no matter what). Pure syntactic sugar looks
somewhat differently. For example, overloading the operator "+" in C++
is pure syntactic sugar (I'm not saying it is useless), because it is
just a fancy way of defining a function. Another example, multiple
return values in Go are pure syntactic sugar, because you could do the
same thing by defining a new struct type and returning it instead.

> - Constructors - my experience shows me that they are useless. First of
>   all they don't work if you don't have function overloading, because
>   obviously for some types there is more than one way to initialize
>   them. And function overloading adds another layer of complexity and
>   ambiguity. Secondly, the problem with error handling. People will
>   want to write myFunc(MyObject(1, 2, 3)) and then they will complain
>   that it's not possible, because constructor returns multiple values
>   (we need to handle errors, right.. ugh.. exceptions I forgot). Crappy
>   features, please don't even consider it.

I agree. You are better of if you define and then call a function to
create the object, instead of introducing constructors into the
language.

Although I do *not* think this applies to copy-constructors and move-
constructors.

> - Eliminating nil - I'm a C guy, nulls are ok for me. Go solves the
>   most nasty problem btw, it doesn't allow programmers to use 0 as nil.
>   The problem is addressed in C++0x as well, but it's too late for that
>   language.

I don't agree. The fact that *any* pointer can be nil is a bad thing.

bflm

unread,
Oct 21, 2010, 4:39:30 PM10/21/10
to golang-nuts
On Oct 21, 7:50 pm, ⚛ <0xe2.0x9a.0...@gmail.com> wrote:
> > - Eliminating nil - I'm a C guy, nulls are ok for me. Go solves the
> >   most nasty problem btw, it doesn't allow programmers to use 0 as nil.
> >   The problem is addressed in C++0x as well, but it's too late for that
> >   language.
>
> I don't agree. The fact that *any* pointer can be nil is a bad thing.
It's not a bad thing, it's something quite different - it's your
opinion. Let's imagine e.g. a single linked list in a language without
nil pointers. So you have to use for the nil's purpose a specially
instantiated non nil sentinel with exactly the same semantics as a
trivial, no constructing necessary, nil would have already. Would you
not check for the next pointer being equal to the sentinel (vs.
checking it against nil), you're gonna process garbage instead of
getting a segfault. The later could often be even a lot more safe and
preferred bug behaviour.

IMO demanding a guarantee of any pointer being non nil in a
programming language model is just like asking for a zero being model-
wide forbidden as an integer value only because it can crash some
process when blindly used as a divisor.

unread,
Oct 21, 2010, 4:59:15 PM10/21/10
to golang-nuts
I guess you need some time before you understand what the article was
saying about nil pointers ...

Eleanor McHugh

unread,
Oct 21, 2010, 5:04:09 PM10/21/10
to golang-nuts
On 21 Oct 2010, at 16:54, nsf wrote:
> - Block arguments - they're nice. But it's pure syntax sugar for
> calling functions where the last argument has a function type. Syntax
> sugar needs a lot of arguments to be considered for adding to the
> language, IMHO.

Personally I think syntactic sugar for this would be a huge win. It certainly is in Ruby, particularly for blocks which make use of yield to iterate generated results in a traditional coroutine style. In Go this could be integrated nicely with range to improve orthogonality between slice types and user-defined types.

> - Unions - I miss them, at least for my go lemon parser generator port.
> C's and D's versions have no problems with lemon, because they both
> have unions. In Go I have to use interface{} magic, which has bad
> performance properties.

Unions are another feature I could leverage a lot if it were added to Go. A lot of the dirty hackery I currently do with unsafe would disappear and the type safety of my code would be improved.

> - Exceptions - some people keep telling me that they are a superior way
> of handling errors. Other people (including few very famous
> programmers like John Carmack) tend to avoid them. I don't understand
> them as well. Having panic/recover is fine for me as long as they
> don't introduce additional language statements (hello to
> try/catch/finally, the most horrible thing I've ever knew about
> programming languages) and as long as Go's standard library doesn't
> force me to use them.

It's trivially easy to roll your own exceptions on to of panic/recover (see the code I posted a couple of months back for an example of the Ruby exception idiom in Go) and whilst I'm quite keen on them I don't see any reason they should become a core language feature.

Overall I understand the perspective the article's coming from because there are all kinds of aspects of Go that I'd like to see tweaked to suit my personal needs or biases, but the point is that Go's a young language that needs to be given space to be itself. Just last night I was being asked in an online interview how I could go from Ruby to this supposed 1970s bare-metal language, but that's not really a good characterisation of Go. Sure it's not the bastard child of C and Simula that's C++ or the half-arsed Smalltalk clone we call Java: I prefer to think of it as the best bits of C + CLU without any of the 90s Enterprise OOP nonsense that's made commercial development such a nightmare.

Would I like to see a few features from Ruby or other elegant languages? Certainly. Does that mean Go isn't fit for purpose? Far from it. It's the most productive systems language I've used in thirty years of coding and I don't think that's accidental...


Ellie

Eleanor McHugh
Games With Brains
http://feyeleanor.tel
----
raise ArgumentError unless @reality.responds_to? :reason


munificent

unread,
Oct 21, 2010, 5:43:53 PM10/21/10
to golang-nuts
Hi, I'm the author of that post.

On Oct 21, 6:13 am, Corey Thomasson <cthom.li...@gmail.com> wrote:
> block arguments for example, are just another form of closures, which go has

I'm aware of that. Wasn't that clear from the article? It was under
the "syntax" section and specifically says that the parser will
desugar it to a regular anonymous function. The goal here isn't to
change semantics, it's to add some syntactic support so that scoped
behavior doesn't look so awkward. I think a little syntax can go a
long way towards encouraging something to be idiomatic.

- bob

bflm

unread,
Oct 21, 2010, 6:01:31 PM10/21/10
to golang-nuts
Let me clarify. As you can see above I quoted and commented only
*your* two sentences about nil pointers. No article involved.

munificent

unread,
Oct 21, 2010, 6:05:33 PM10/21/10
to golang-nuts
Hi, I'm the author. Before I reply, I should probably set some
context.

My expectation with this is not to change Go. I would be honestly
surprised if anything in that post ever made its way into the
language. My goals were:

1. To get a better understanding of programming languages in general
by looking at one with a critical eye. I could write similar and
hopefully equally interesting (or uninteresting) posts about Scheme,
ML, C++, or Java.

2. To try to put down in one place my understanding of some of the
things I hear people asking for in Go and why I think they want it.

I'm interested in pretty much all programming languages, so something
like this is just good recreation for me even if nothing comes of it.
Please don't take it as me saying your baby's ugly or trying to take
something away from you. One of the things that speaks very well of Go
is how strongly some people love it. It's like rye bread versus white
bread. Sure some people hate rye bread, but some people *love* it. No
one has strong feelings at all about white bread.

On Oct 21, 8:54 am, nsf <no.smile.f...@gmail.com> wrote:
> MCM112 <m...@stickyeyes.com> wrote:
> Yeah, like "I want to stick in a bunch of features to the Go", but as
> Andrew has pointed out, that won't be the Go anymore.

That sounds to me like there's some platonic ideal of Go out in the
ether than I'm not aware of. Maybe I have too prosaic a perspective on
languages. I consider them tools for humans to use, and something free
to be shaped or reshaped as needs change.

> IMHO the author
> of that article doesn't really realizes that if he will stick in
> templates _and_ operator overloading in any language it will become
> a mess. It is inevitable.

C# pulled it off. There's nothing magical at all about operator
overloading, with the exception of the assignment operation, which
*is* special. I probably wouldn't encourage the ability to overload
that. Other operators are just functions. They don't cause problems
with templates any more than regular prefix functions do, as far as I
know.

> I mean really, we have a language that has
> (almost) all these "nice" features and it is called D.

Java and C# have most of these features too.

> Being simple is a very hard property to achieve, and Go is the closest
> thing we have today.

Being simple is easy. Forth is simple. R4RS Scheme is simple. What's
very hard is being simple without just pushing the complexity onto the
users. I think simplicity is only one term in the equation and
focusing on it can miss the bigger goal. The goal is to maximize
*power*: what the language can express / its complexity. Reducing
complexity will increase power but only to the degree that it
*doesn't* reduce expressiveness.

> - Named/keyword args - I think author proposes some kind of a name
>   mangling and compile-time code generation features. Crap.

Don't hold back. Tell us how you really feel.

> - Block arguments - they're nice. But it's pure syntax sugar for
>   calling functions where the last argument has a function type.

Yup.

> - Operator overloading - makes language unreadable, especially if mixed
>   with templates. Also requires other considerations like "reference"
>   types (see C++). In theory is simple, in practice complicates a
>   language a _lot_.

Eliminate assignment from your list of operators. Do your complaints
still stand?

> - Tuples - maybe, but python experience tells me that they are a very
>   bad duplication for structs. Once you want to have a name for each of
>   the tuple's components, you're screwed. Better leave them out.

Couldn't you make that same argument about multiple returns? Shouldn't
you be returning a struct instead?

> And function overloading adds another layer of complexity and ambiguity.

Overloading is a separate issue, but Go should be in a much happier
place than C++ if it added it because it already shies away from
implicit conversions.

> - Exceptions - some people keep telling me that they are a superior way
>   of handling errors. Other people (including few very famous
>   programmers like John Carmack) tend to avoid them.

Carmack's perspective is pretty deeply tied to the needs of games.
Things like GC and closures tend to be pretty rare there too.

> - Uniform Access - who? Bertrand Meyer? OOP guy?

Yeah, what does that guy know, right?
http://en.wikipedia.org/wiki/Eiffel_%28programming_language%29
http://www.amazon.com/dp/0136291554

- bob

munificent

unread,
Oct 21, 2010, 6:26:49 PM10/21/10
to golang-nuts
> a number of the issues they raise are handled in Go by common idioms, and
> they haven't reviewed their suggestions against these idioms, at least
> not as explictly and in as much detail as I think would be required to
> be able to tell if their ideas actually provide benefit.

Sorry, I was trying to balance a fully clarifying my points while
trying to be brief enough to keep the post interesting for a more
general audience. It's already painfully long, so I didn't want to go
all language lawyer and make it worse. I can try to clarify some of my
thoughts here where the audience may be more receptive to greater
detail.

> The alternative for "scoped behaviour" in their example is defer, which
> is not discussed (well)

My main complaint with defer is the obvious one: it's not automatic.
If there's something I need to *always* remember to do, to me that
sounds like something I should automate. Scoped behavior is one way to
do that.

> and the provision of New* functions replaces
> constructors with a more explicit form; their request for constructors
> needs to be directly compared against this.

Yeah, those two sections are in rough collision. I'm certain the two
could be brought into a harmonious alignment but that would likely
take more work than is worth doing on a proposal that few would be
interested in to begin with. Overall, my goals for construction are:

1. A uniform syntax between "raw" struct creation and user-defined
initialization functions. That way going from a zero-inited type to
one that later requires initialization doesn't require you to touch
every call site that creates a struct.
2. A way to define initialization functions that get called when a
struct is created.

Almost no languages outside of dynamic ones do 1. Most OOP languages
handle 2 pretty well.

> Their section on error
> handling is very sparse on discussion of whether the explicitness of
> the handling is good or bad

I think explicitness is good where it clarifies and bad where it
obfuscates. If errors are common, then mainline code will need to
address them. In that case, error-handling should be terse and simple.
Return codes (especially with unions) are good for that. I'd use those
for things like parsing and collection lookup.

Cases where errors are rare (stack overflow, out of mem, etc.), the
error handling should not clutter up the main code paths. I like how
exceptions (and panic/recover) handle that.

> discussion of the value or lack thereof of
> banning, by convention, panic()/exception-like behaviour across package
> boundaries, another important idiom.

I don't know enough about how that works to discuss it.

> This might just be my opinion, but I don't think future-proofing, as
> they describe it, is an idiom in Go, either.

Agreed: "Right now, Go avoids this by having a culture of not future-
proofing."

They should directly
> compare the uniform access feature against a lack of any such
> future-proofing, not against speculatively wrapping everything. I feel
> this would be hard to prove reliably either way.

I consider language usability an empirical science, so I'm not sure
what "proof" would mean. There is strong evidence that reasonable
programmers *do* do this exact kind of future-proofing though:
established coding guidelines for lots of languages state things like
"always wrap fields in getters and setters".

> one of dubiousness that the cost of modifying every call site in the
> event changes happen in one place beat the costs of mitigating it
> *everywhere* pre-emptively.

I don't know which cost is worse there, but I do know that languages
that give you uniform access save you from having to pay *either*.
Properties in C# are really nice.

> their point
> about "type safety without coupling" would only apply if the error from
> their function was the only error the function it was passed to
> returned, and their function only ever returned one type of error.

I'm not sure I follow here.

> without actually suggesting an implementation so the other performance
> effects could be examined; I'd think this would require returning
> something like an interface to make the type switch possible, which
> seems like it would have significant effects of its own.

I think union types are fairly well-understood. Many languages have
them and smart implementations can create them without any need for
boxing. It should boil down to a simple struct with a type tag and the
value. In many cases union types should be a net win over multiple
returns: there's fewer values to zero-initialize.

> It is hard to begrudge them this, although I would have
> suggested not writing the review if they weren't willing to seriously
> consider what is idiomatically used as alternatives to the desired
> features,

I did my best to cover "the Go way to do things" whenever I could but
my time is limited.

> and be quiet about performance when they haven't analysed
> what their idea would cost to implement.

I don't recall making any specific performance claims, but I also
haven't described anything here that isn't well-established in other
successful languages.

> Perhaps my standards for blogs are too high, though.

My threshold for posting is:
1. Do I feel I have something interesting to say?
2. Do I feel like there's only a slim chance of putting my foot in my
mouth and looking like an idiot?

This one just squeaked by. ;)

- bob

nsf

unread,
Oct 21, 2010, 6:47:42 PM10/21/10
to golan...@googlegroups.com
On Thu, 21 Oct 2010 15:05:33 -0700 (PDT)
munificent <munifi...@gmail.com> wrote:

> Hi, I'm the author. Before I reply, I should probably set some
> context.

Hi.

Don't get me wrong too, these all are just my opinions, and who am I?
I'm no one. :)

> > IMHO the author
> > of that article doesn't really realizes that if he will stick in
> > templates _and_ operator overloading in any language it will become
> > a mess. It is inevitable.
>
> C# pulled it off. There's nothing magical at all about operator
> overloading, with the exception of the assignment operation, which
> *is* special. I probably wouldn't encourage the ability to overload
> that. Other operators are just functions. They don't cause problems
> with templates any more than regular prefix functions do, as far as I
> know.

I think C# is a mess. I've tried writing code using it's standard
library, it was one of the most horrible experiences in my programming
practice.

>
> > I mean really, we have a language that has
> > (almost) all these "nice" features and it is called D.
>
> Java and C# have most of these features too.

Then why people tend to use C and C++ for most of the systems
programming? On my linux machine I have tons of software and 0 is
written in C#/Java.

>
> > Being simple is a very hard property to achieve, and Go is the closest
> > thing we have today.
>
> Being simple is easy. Forth is simple. R4RS Scheme is simple. What's
> very hard is being simple without just pushing the complexity onto the
> users. I think simplicity is only one term in the equation and
> focusing on it can miss the bigger goal. The goal is to maximize
> *power*: what the language can express / its complexity. Reducing
> complexity will increase power but only to the degree that it
> *doesn't* reduce expressiveness.

I'm still not really sure that expressiveness is a some kind of magical
property that makes people's programs shine. Like Ruby is expressive,
Perl is expressive and I have very hard time reading programs written
in these languages. D goes to that category as well. On the other hand
things written in C and Go are very easy to read and understand.

>
> > - Named/keyword args - I think author proposes some kind of a name
> >   mangling and compile-time code generation features. Crap.
>
> Don't hold back. Tell us how you really feel.

You're proposing some kind of magic transformations behind the scenes
of a call expression. substring(from: start, to: end) becomes
substring__from__to(start, end). That's how languages like C++ and D do
function overloading. They simply encode argument types as a part of a
function name (also the process is knowsn as name mangling). It can't
be good. Have you ever tried reading crappy undocumented C++ code? I
literally spent hours trying to grep things in C++ apps like that.
That's why I call this a "crap". Overloading is a very bad idea and the
fact that some form of overloading is required for generic functions
implementation makes all this stuff even worse.

> > - Operator overloading - makes language unreadable, especially if mixed
> >   with templates. Also requires other considerations like "reference"
> >   types (see C++). In theory is simple, in practice complicates a
> >   language a _lot_.
>
> Eliminate assignment from your list of operators. Do your complaints
> still stand?

Let's be honest. When do you need operator overloading? The most
common area for that is games and 3d/2d graphics in general. These apps
tend to have a lot of math, and operator overloading makes someone's
life simpler. But the thing is, that operator overloading adds a lot of
indirections in a language. It is possible to hide complex operations
under simply looking expressions. It is bad. Don't get me wrong. It's
much better to write code in a language that has operator overloading,
but it's much harder to read it and especially debug it.
Reading/debugging has a higher priority over writing.

>
> > - Tuples - maybe, but python experience tells me that they are a very
> >   bad duplication for structs. Once you want to have a name for each of
> >   the tuple's components, you're screwed. Better leave them out.
>
> Couldn't you make that same argument about multiple returns? Shouldn't
> you be returning a struct instead?

Multiple return values are ok, because they don't introduce persistent
storage type as tuples do. It's like passing multiple arguments to a
function. Function form in general comes from math and in math
functions do return only one value, but computing world is different,
it makes sense to have multiple return values the same way as it makes
sense to be able to pass multiple arguments to a function.

>
> > And function overloading adds another layer of complexity and ambiguity.
>
> Overloading is a separate issue, but Go should be in a much happier
> place than C++ if it added it because it already shies away from
> implicit conversions.

It's not a separate issue, overloading is a very annoying issue,
because in a lot of places it struggles to get in. Want constructors?
But there are sometimes multiple ways to initialize a value, solution -
function overloading. Want generics? But is it possible to have multiple
functions with the same name but with different types as arguments,
solution - function overloading.

Yes, absence of implicit conversions helps us in a way that we don't
need to use function overloading for operator overloading as well. But
is it help, really?

Plus argument above, function overloading makes it harder to read the
code.

>
> > - Exceptions - some people keep telling me that they are a superior way
> >   of handling errors. Other people (including few very famous
> >   programmers like John Carmack) tend to avoid them.
>
> Carmack's perspective is pretty deeply tied to the needs of games.
> Things like GC and closures tend to be pretty rare there too.

Well, exceptions are used in game industry. Of course most people tend
to avoid them, especially if their game is a very computing resources
greedy. But I believe his (John Carmack) opinion has nothing to do with
that. Writing exception safe code is much more painful than good error
checking code. Maybe I'm an idiot, I don't know, but I don't get how
exceptions make my code better.

>
> > - Uniform Access - who? Bertrand Meyer? OOP guy?
>
> Yeah, what does that guy know, right?
> http://en.wikipedia.org/wiki/Eiffel_%28programming_language%29
> http://www.amazon.com/dp/0136291554

I'm sorry, it tells me nothing. I've read a lot of OOP books and I've
used a lot of OOP (I mean especially those, when an author emphasise
that fact) languages, their authors are nuts. And you're pointing
to the guy that started all this OOP mess? That's just my opinion.

>
> - bob

Bob Cunningham

unread,
Oct 21, 2010, 6:52:23 PM10/21/10
to golang-nuts

To beat this to death, let's say the linked list was implemented within
an array, where all 'pointers' were indices into the array. In this
case, 'nil' or zero is clearly a valid value. Which means the end of
the list (EOL) would need to be identified some other way. Would you
choose -1 for this implementation?

Using a 'special' value of the Next field to indicate EOL is encoding
more data into the field than just a 'next' value: It is also encoding
the existence of a next item in the list. This is more popularly known
as 'in-band signaling', where a special value in the domain of a field
is reserved to encode a meaning different from all other values in the
domain. The 'out-of-band' version of the list structure would have a
separate boolean field called EOL, and only when False would the Next
field have any meaning or relevance.

Merging two separate data items into a single field in this manner is
nothing less than a non-type-safe risky hack. This use of nil/null/zero
should be eliminated, if only to greatly reduce the use of problem-prone
ad-hoc in-band signaling. There are times when in-band signaling is
inevitable (such as over bit-serial links), but this specific use of nil
for in-band signaling within a pointer field isn't one of them.

The use of nil pointers in this manner is so entrenched in C and its
progeny that its elimination may seem an impossibility. I don't
recommend eliminating the 'existence' of nil pointers (doing so would
complicate operating system implementations), but their intentional use
should require jumping through some linguistic hurdles to make it
blindly clear what's happening.

Bottom line, the language should make it very difficult (but not quite
impossible) for a user to either intentionally or accidentally create or
dereference a nil pointer. At compile time, not just run time.


-BobC

konrad

unread,
Oct 21, 2010, 7:20:24 PM10/21/10
to golang-nuts
My take on the article:

Tupels: I really don't see how a tuple would fit in a statically typed
language. really if you have to write a type definition you might as
well name the arguments.

Keyword parameters: I believe the conventional wisdom is that
functions with a large argument count are a sign that you are doing
things wrong. Perhaps it would be better to pass a structure instead.

If your reluctant to do this because of the overhead, well guess what,
having the language do it implicitly with keyword arguments also has
overhead.

The Uniform access principle:

I'm a fan of this. The most frequent approach to this is to make
method invocations look like reading and assignment of fields. However
this is not the only way to do it.

Go's primitive for uniform access is the interface, which exposes
methods only. But when you use interfaces you still get uniform
access, and don't have to worry how the information is stored or
calculated.

One think my toy projects in go have taught me is that if in doubt use
an interface. If you don't you will end up re-factoring the code
later, and it will be a painful process.



Gordon Tisher

unread,
Oct 21, 2010, 7:24:14 PM10/21/10
to Bob Cunningham, golang-nuts
On Thu, Oct 21, 2010 at 3:52 PM, Bob Cunningham <Fly...@gmail.com> wrote:
> Merging two separate data items into a single field in this manner is
> nothing less than a non-type-safe risky hack.  This use of nil/null/zero
> should be eliminated, if only to greatly reduce the use of problem-prone
> ad-hoc in-band signaling.  There are times when in-band signaling is
> inevitable (such as over bit-serial links), but this specific use of nil for
> in-band signaling within a pointer field isn't one of them.
>
> The use of nil pointers in this manner is so entrenched in C and its progeny
> that its elimination may seem an impossibility.  I don't recommend
> eliminating the 'existence' of nil pointers (doing so would complicate
> operating system implementations), but their intentional use should require
> jumping through some linguistic hurdles to make it blindly clear what's
> happening.
>
> Bottom line, the language should make it very difficult (but not quite
> impossible) for a user to either intentionally or accidentally create or
> dereference a nil pointer.  At compile time, not just run time.

What value should the Next pointer of the last element in a linked
list have, then?

--
Gordon Tisher

Rob 'Commander' Pike

unread,
Oct 21, 2010, 7:31:10 PM10/21/10
to Gordon Tisher, Bob Cunningham, golang-nuts

17

-rob


munificent

unread,
Oct 21, 2010, 7:33:40 PM10/21/10
to golang-nuts


On Oct 21, 4:20 pm, konrad <kzielin...@gmail.com> wrote:
> Tuples: I really don't see how a tuple would fit in a statically typed
> language. really if you have to write a type definition you might as
> well name the arguments.

Take a look at ML, F#, or Haskell. It works surprisingly well.

> Keyword parameters:
> If your reluctant to do this because of the overhead, well guess what,
> having the language do it implicitly with keyword arguments also has
> overhead.

What I proposed has no overhead. It would be handled purely by the
parser.

> One think my toy projects in go have taught me is that if in doubt use
> an interface. If you don't you will end up re-factoring the code
> later, and it will be a painful process.

That seems like a good best practice, but also the exact of thing
that's annoying about languages like Java. If practices like that
become common where every type definition become a pair of struct
+interface definitions with all of the requisite copy/paste between
them, then it starts to look to me like Go has sadly been dragged back
to the same swamp that Java and C++ are in.

- bob

Alexey Gokhberg

unread,
Oct 21, 2010, 7:35:23 PM10/21/10
to golang-nuts

On 22 Okt., 00:52, Bob Cunningham <FlyM...@gmail.com> wrote:
> On 10/21/2010 03:01 PM, bflm wrote:
>
> Merging two separate data items into a single field in this manner is
> nothing less than a non-type-safe risky hack.  This use of nil/null/zero
> should be eliminated, if only to greatly reduce the use of problem-prone
> ad-hoc in-band signaling.
>

Well, the consequent application of this principle may bring some very
interesting results.

rec type intList is variant(cons: intNode; tip: null)
& intNode is structure(hd: int, tl: intList)

let reverseList = proc(list: intList -> intList)
begin
let temp := intList(tip: nil);
let done := false;
while ~done do
project list as X onto
cons: begin
temp := intList(cons: struct(hd = X(hd); tl :=
temp))
list := X(tl)
end
default: done := true
temp
end

This is how Napier88 handles simple linked lists. The type describing
a list is a union (variant) of a pointer to a list node and a special
data type "null" that has only one value "nil". The "project"
statement inside the loop works like the type switch in Go. The code
is bomb proof, but personally I don't think I would like to code
processing of simple lists this way.

munificent

unread,
Oct 21, 2010, 7:40:17 PM10/21/10
to golang-nuts
> What value should the Next pointer of the last element in a linked
> list have, then?

"Empty". Here's a complete linked list definition in SML:

datatype a' list = Node of a' | Empty

No null in sight, and you're statically prevented from trying to
access the value of a list node without first checking to see that it
isn't Empty.

- bob

Bob Cunningham

unread,
Oct 21, 2010, 7:45:35 PM10/21/10
to Gordon Tisher, golang-nuts

It doesn't matter: Use any value you want!

The 'safe' implementation is to have a boolean 'Last' field, and the
Next field is accessed only when Last is False. It is up to the
programmer to ensure that Next has been correctly set before Last is set
to False.

Ian Lance Taylor

unread,
Oct 21, 2010, 7:59:30 PM10/21/10
to munificent, golang-nuts
munificent <munifi...@gmail.com> writes:

We've fought this particular battle at great length on the mailing list
and wound up right back where we started.

E.g.:

http://groups.google.com/group/golang-nuts/browse_thread/thread/aef193652154f2c6/f498a152f025b147

Ian

Gordon Tisher

unread,
Oct 21, 2010, 8:31:42 PM10/21/10
to Ian Lance Taylor, golang-nuts, munificent

Ya know, the Unreal game engine's scripting language has the best of both worlds -- null pointers and no crashes. The compiler inserts null checks for dereferences that print an error message and then jump to the next source line :-)

On 2010-10-21 4:59 PM, "Ian Lance Taylor" <ia...@google.com> wrote:

munificent <munifi...@gmail.com> writes:

>> What value should the Next pointer of the last elem...

fango

unread,
Oct 21, 2010, 8:54:39 PM10/21/10
to golang-nuts
> 17
>
> -rob

Haha, what's the story here? Thought it was 42 which will had been
tooking mice 17½ million years to put that up and (almost) verified
it.

http://en.wikipedia.org/wiki/Answer_to_the_Ultimate_Question_of_Life,_the_Universe,_and_Everything#Answer_to_the_Ultimate_Question_of_Life.2C_the_Universe_and_Everything_.2842.29

Charles Thompson

unread,
Oct 22, 2010, 12:49:50 AM10/22/10
to golang-nuts
The paradox of choice says less is more. Go validates this premise.

I'm drawn to Go because it's easy to learn and read. Its idioms
embrace common sense. And its concurrency aspects are easy to reason
about. Michael Hoisie's blog post was great anecdotal evidence this.

Fortunately, Go's package system makes it simple to add missing
feature XYZ. Therefore, I humbly beg the creators of Go to resist the
temptations of adding generics, and other new features at the risk of
being closed minded.

Music is composed of seven notes, yet there is limitless expression
and creativity.

Finally, it would be terrible to find something that resembles this
infamous line of Scala in Go's standard lib:

implicit def TraversableBind[M[X] <: Traversable[X]] = new Bind[M] {
def bind[A, B](r: M[A], f: A => M[B])(implicit w: CanBuild[B,
M[B]]): M[B] = r.flatMap(f)(breakOut)
}


On Oct 21, 5:46 am, MCM112 <m...@stickyeyes.com> wrote:
> I recently stumbled across this article at:http://journal.stuffwithstuff.com/2010/10/21/the-language-i-wish-go-was/
>
> I thought it might be prudent to post it here to hear the views of the
> go community on some of the points raised by the author.
>
> Cheers,
>
> Ben

Paulo Pinto

unread,
Oct 22, 2010, 2:38:34 AM10/22/10
to golang-nuts
It was a nice article, and I tend to agree to a great extent to what
you wrote.

I spent some time playing around with Go, but it really does lake some
features
for the time of programming I am used to do.

I can see Go replace C as systems language, because it does offer more
features
(except enums) together with more type safety. Plus it already has a
kind of proven
history. It is really interesting how similar Go is to Alef or Limbo.

But I am not seeing Go being able to replace languages that offer much
better abstractions.
At least not for me.

I only keep coming to the list from time to time, and to the D list as
well I confess, because
I like programming languages. Compiler development was one of my main
subjects at the university.

But this is me. Surely lots of Go users are happy with Go as it is.

Christophe de Dinechin

unread,
Oct 22, 2010, 4:34:19 AM10/22/10
to golang-nuts
> What value should the Next pointer of the last element in a linked
> list have, then?

If you had read it, the original blog post offers a correct answer to
this: real union types.

With it, the pointer type has no nil value. If you need an end-of-list
value, then you create a new type that is "pointer or end-of-list".
This also makes it possible to encode correctly something like a tree
as "leaf or two pointers to tree", no nil ever happening in that tree.
That also means that you won't incorrectly confuse "end-of-list" with,
say, "error-happened", whereas with "nil" you can't make a difference
between the two pointer values, both are nil.

Many languages like Haskell can build linked list without nil very
well. Your question demonstrates that you don't know these languages,
but the original author obviously does.

Benny Siegert

unread,
Oct 22, 2010, 4:42:38 AM10/22/10
to Bob Cunningham, golan...@googlegroups.com
On Fri, Oct 22, 2010 at 01:45, Bob Cunningham <Fly...@gmail.com> wrote:
> It doesn't matter:  Use any value you want!

I choose nil.

> The 'safe' implementation is to have a boolean 'Last' field, and the Next
> field is accessed only when Last is False.  It is up to the programmer to
> ensure that Next has been correctly set before Last is set to False.

The 'safe' implementation is to have a pointer, which can be nil,
which is only _dereferenced_ when it is not nil. It is up to the
programmer to ensure that the pointer is non-nil before using it.

--Benny.

roger peppe

unread,
Oct 22, 2010, 5:10:01 AM10/22/10
to munificent, golang-nuts
On 21 October 2010 23:05, munificent <munifi...@gmail.com> wrote:
> Overloading is a separate issue, but Go should be in a much happier
> place than C++ if it added it because it already shies away from
> implicit conversions.

actually, Go doesn't shy away from implicit conversions entirely.
it has implicit conversions from constant values, implicit
conversions to interface values, and implicit conversions from nil.

any or all of these would make overloading a pain in Go.

roger peppe

unread,
Oct 22, 2010, 5:25:26 AM10/22/10
to konrad, golang-nuts
On 22 October 2010 00:20, konrad <kziel...@gmail.com> wrote:
> Tupels: I really don't see how a tuple would fit in a statically typed
> language. really if you have to write a type definition you might as
> well name the arguments.

tuples can fit just fine in a statically typed language.
Limbo, one of Go's predecessors, has tuples and they work well.
i miss them in Go - it's annoying having to think of a name for
a type when the only reason for the type is to combine two values.
and it's a shame that the return value of a function isn't first class.

but it would be awkward retrofitting them into Go, because
of the way that Go overloads on number of arguments assigned to.

unread,
Oct 22, 2010, 6:28:15 AM10/22/10
to golang-nuts
I agree. It is a very good solution to be able to use 17 in the last
element of a linked list. (I am *not* joking)

If Go would enable me to safely reason - at compile-time - about the
last element of a linked list and the value "17" optionally used
there, then I am all for it. Scrap the current Go, and welcome the new
Go that will enable me to perform this kind of reasoning!

unread,
Oct 22, 2010, 6:56:50 AM10/22/10
to golang-nuts
On Oct 22, 1:59 am, Ian Lance Taylor <i...@google.com> wrote:
> http://groups.google.com/group/golang-nuts/browse_thread/thread/aef19...
>
> Ian

The impression I got from reading (now and back then) the "Repeating
the billion dollar mistake?" discussion is that, in the minds of the
original Go creators, non-nullable pointers have little value. The
generic reason for this is that Go is *not* a language built for the
purpose of fulfilling the needs of those programmers who want to
translate their ideas into code with as much precision as possible or
want the compiler to "understand" what the programmer means.

roger peppe

unread,
Oct 22, 2010, 7:32:09 AM10/22/10
to ⚛, golang-nuts

even in languages with no nil, such as Haskell, you can still get
exceptions from using things that have an unexpected form.

e.g. head []

that's not too different from a nil pointer exception.
so even if you go the non-nil route, you may still end
up paying a good proportion of the "billion dollar"
price.

Carl

unread,
Oct 22, 2010, 8:13:11 AM10/22/10
to golang-nuts
"The Language I Wish Go Was"

<< Did you expect C++ to become such a success? ... Of course not. The
success rate for general-purpose programming languages is vanishingly
small. I knew that, and I knew that the chance of success was affected
by marketing clout, which I did not have. >>

from Bjarne Stroustrup's FAQ.

How does one measure the QUALITY of a general purpose programming
Language?

I think the usual common approach to this is to count to quantity of
features and functions. This will t