What's wrong with Go?

795 visningar
Hoppa till det första olästa meddelandet

Jon Harrop

oläst,
13 nov. 2009 18:29:382009-11-13
till golang-nuts

Are there any comparisons between Go and modern languages (SML, OCaml, Scala,
Haskell, F#, C# 3/4, Clojure, Erlang?)? Can anyone give a bullet point list
summarizing where Go's current design fails to adopt existing solutions to
important language-design problems?

Here's what I've noticed so far:

* They say "Go attempts to reduce the amount of typing in both senses of the
word" but "Hello world" is several times longer in Go than in most modern
languages. Also, they seem to have only very rudimentary type inference.

* Go was designed to be fast but preliminary results seem to indicate that it
is several times slower than most modern languages, even dynamic ones.
Moreover, several fundamental design decisions degrade performance (e.g.
structural typing) and the implementors do not seem to be aware of good
existing solutions to important problems (e.g. generics on the CLR).

* They said "say goodbye to stack overflows" but it sounds as though tail
calls leak stack space.

* They state that development efficiency is a major goal, citing Python, but I
cannot see a Go REPL.

* They replicated the billion dollar mistake.

Has anyone detailed the current implementations of goroutines (Cilk-style
wait-free work-stealing task deques?) and their GC?

--
Dr Jon Harrop, Flying Frog Consultancy Ltd.
http://www.ffconsultancy.com/?e

manatlan

oläst,
13 nov. 2009 18:37:462009-11-13
till golang-nuts
the simplest "hello world" could be written like this :

package main
func main() {
print( "hello world" )
}

my 2 cents ;-)

Jon Harrop

oläst,
13 nov. 2009 18:45:062009-11-13
till golan...@googlegroups.com
On Friday 13 November 2009 23:37:46 manatlan wrote:
> the simplest "hello world" could be written like this :
>
> package main
> func main() {
> print( "hello world" )
> }

Compare with F#:

printf "Hello world"

OCaml:

print_string "Hello world"

Haskell:

main = putStrLn "Hello, World!"

That Haskell looks verbose to me. :-)

Ian Lance Taylor

oläst,
13 nov. 2009 18:59:052009-11-13
till Jon Harrop, golang-nuts
Jon Harrop <j...@ffconsultancy.com> writes:

> Are there any comparisons between Go and modern languages (SML, OCaml, Scala,
> Haskell, F#, C# 3/4, Clojure, Erlang?)? Can anyone give a bullet point list
> summarizing where Go's current design fails to adopt existing solutions to
> important language-design problems?
>
> Here's what I've noticed so far:
>
> * They say "Go attempts to reduce the amount of typing in both senses of the
> word" but "Hello world" is several times longer in Go than in most modern
> languages. Also, they seem to have only very rudimentary type inference.
>
> * Go was designed to be fast but preliminary results seem to indicate that it
> is several times slower than most modern languages, even dynamic ones.
> Moreover, several fundamental design decisions degrade performance (e.g.
> structural typing) and the implementors do not seem to be aware of good
> existing solutions to important problems (e.g. generics on the CLR).
>
> * They said "say goodbye to stack overflows" but it sounds as though tail
> calls leak stack space.
>
> * They state that development efficiency is a major goal, citing Python, but I
> cannot see a Go REPL.
>
> * They replicated the billion dollar mistake.

Go is just another programming language which addresses some issues
that matter to us. If you don't like it, I encourage you to simply
use one of the other fine languages you mention. Identifying all the
ways that Go falls short of your ideal seems an ineffective use of
time.


> Has anyone detailed the current implementations of goroutines (Cilk-style
> wait-free work-stealing task deques?) and their GC?

The GC is currently mark-and-sweep, and improving it is a high
priority task. Goroutines are coroutines multiplexed onto OS
threads.

Ian

Roman Shaposhnik

oläst,
13 nov. 2009 19:08:152009-11-13
till golang-nuts
On Fri, Nov 13, 2009 at 3:29 PM, Jon Harrop <j...@ffconsultancy.com> wrote:
> Are there any comparisons between Go and modern languages (SML, OCaml, Scala,
> Haskell, F#, C# 3/4, Clojure, Erlang?)?

<shameless plug>
you forgot Lua ;-)
</shameless plug>

> Can anyone give a bullet point list
> summarizing where Go's current design fails to adopt existing solutions to
> important language-design problems?

Having such comparison could be, indeed, quite useful. However, as
usual with such
comparisons it is not quite clear whether it should be written by an
expert in FOO
who happens to know Go or by one of the Go creators who happens to know FOO.
I'd love it to be written by one of the Go guys, but something tells
me that they are
way better off spending their time on the language itself ;-)

As for the experts in FOO...

> Here's what I've noticed so far:

[ a bunch of observations skipped ]

...I'm not sure how many of those can escape the allure of simply applying
a checklist of language design decision to Go and running away in horror, as
opposed to spending a couple of weeks writing stuff in it and figuring out
how useful the language as a whole can be.

Thanks,
Roman.

Sebastian Sylvan

oläst,
13 nov. 2009 19:12:022009-11-13
till Ian Lance Taylor, Jon Harrop, golang-nuts
That's a pretty defeatist point of view. How about you fix the shortcomings and take over the world instead?
I don't think anyone would bother to come on this list and complain if they didn't like it in some sense, and want the few remaining niggles sorted out.


--
Sebastian Sylvan

jqb

oläst,
13 nov. 2009 19:17:432009-11-13
till golang-nuts
On Nov 13, 3:59 pm, Ian Lance Taylor <i...@google.com> wrote:

> Go is just another programming language which addresses some issues
> that matter to us.  If you don't like it, I encourage you to simply
> use one of the other fine languages you mention.  Identifying all the
> ways that Go falls short of your ideal seems an ineffective use of
> time.

This attitude is a goodly part of what's wrong with the language.

Toby Hutton

oläst,
13 nov. 2009 19:26:522009-11-13
till jqb, golang-nuts
I wholeheartedly disagree. This attitude is similar to the Haskell
'avoid success at all costs,' i.e., don't try to be everything for
everyone and bloat/complicate the language.

Jon Harrop is a well known troll, google him, and until he has
something constructive to add, I'll ignore him.

Toby.

jqb

oläst,
13 nov. 2009 19:29:102009-11-13
till golang-nuts


On Nov 13, 4:12 pm, Sebastian Sylvan <sebastian.syl...@gmail.com>
wrote:
Go is presented as a new systems programming language after over a
decade since the last one, a language that solves the problems of
existing languages -- the sort of thing that could take over the
world. But Ian's attitude is more in line with what it really is -- a
pet project by people more interested in their own ideas than in the
extensive fruits of a large and sophisticated language design
community.

jqb

oläst,
13 nov. 2009 19:31:242009-11-13
till golang-nuts
On Nov 13, 4:26 pm, Toby Hutton <toby.hut...@gmail.com> wrote:
Your ad hominem is noted and my response is to *plonk* you rather than
Mr. Harrop.

atomly

oläst,
13 nov. 2009 19:34:072009-11-13
till jqb, golang-nuts
You are very wrong.

I think his attitude is exactly what's right about the language. I'm
sick of every fucking language trying to be everything to everybody.
There are a lot of languages out there and some of them are very well
suited for certain jobs. Go was designed to fill a certain area and
it will never directly compete with, say, JavaScript.

The OP, on the other hand, is exactly what's wrong with this list. Do
people really just want to sit around and complain about the language?
I mean, I'm all for constructive criticism and useful suggestions,
but a laundry list of "why this language isn't precisely what one dude
somewhere wants" seems like an exercise in who gives a rat's ass.

I one hundred percent stand behind the Go developer's in their idea to
keep the language simple, even if it's at the expense of possibly
useful features. C++ tries to be everything to everybody and it's
like a hydra wrapped in a cerebus gettin all ouroboros on itself.

All these people that join the list asking for this crazy list of
features are basically asking "hey, you have this nice, relatively
clean language... could you please take a giant crap on its simplicity
for me?" This New Yorker article about feature creep would be a very
good read, in fact:

http://www.newyorker.com/talk/financial/2007/05/28/070528ta_talk_surowiecki

People always think they need everything and the kitchen sink until
they actually have to use it, then they realize that they just pulled
a Homer Simpson (
http://pagesperso-orange.fr/Jas-n-Geoff/Geoff/homer.jpg )

--
:: atomly ::

[ ato...@atomly.com : www.atomly.com : http://blog.atomly.com/ ...
[ atomiq records : new york city : +1.917.442.9450 ...
[ e-mail atomly-new...@atomly.com for atomly info and updates ...

atomly

oläst,
13 nov. 2009 19:38:102009-11-13
till jqb, golang-nuts

Peter Froehlich

oläst,
13 nov. 2009 19:38:052009-11-13
till golang-nuts
Hi all,

On Fri, Nov 13, 2009 at 7:17 PM, jqb <jqba...@gmail.com> wrote:
I think that's a little harsh, but I do see a point to the comment. I
am here because I think there's a chance to fix a few things in Go,
and I am interested mostly because a good part of Go comes from the
languages I've been in love with and worked on all my live (even when
the syntax tries to hide it).

I have not put together my laundry list yet because I wanted more
experience with the details, but if the discussion is completely
closed even on the buggy parts, I'd like to be told.

I guess one thing may be that they just released it. I am sure when
Guido put up Python there wasn't immediately a PEP process. But things
should remain flexible as well. And when are they more flexible (in
theory) than now when the thing is not even fully born yet?

Note that I won't be advocating anything that would go against the
"Spirit of Go" as far as I understand it, but come on, there a plenty
of things that could be improved *without* adding a single new feature
to the language. If discussion is closed on those... :-/

Cheers,
Peter
--
Peter H. Froehlich <http://www.cs.jhu.edu/~phf/>
Senior Lecturer | Director, Johns Hopkins Gaming Lab

jqb

oläst,
13 nov. 2009 19:41:242009-11-13
till golang-nuts
On Nov 13, 4:34 pm, atomly <ato...@atomly.com> wrote:
> The OP, on the other hand, is exactly what's wrong with this list.  Do
> people really just want to sit around and complain about the language?
>  I mean, I'm all for constructive criticism and useful suggestions,
> but a laundry list of "why this language isn't precisely what one dude
> somewhere wants" seems like an exercise in who gives a rat's ass.

This is a radical mischaracterization of his statement.

> All these people that join the list asking for this crazy list of
> features are basically asking "hey, you have this nice, relatively
> clean language... could you please take a giant crap on its simplicity
> for me?"

As is this. The criticisms were about the failure of the design to
achieve its stated goals.

Sebastian Sylvan

oläst,
13 nov. 2009 19:42:052009-11-13
till atomly, jqb, golang-nuts
To be fair though, the OP didn't really request anything that would increase the complexity or make the language any less clean did he?

I totally appreciate what Go's trying to be, I just think it could achieve it's ideal even better than it has so far with some minor tweaks.

--
Sebastian Sylvan

Jon Harrop

oläst,
13 nov. 2009 19:47:332009-11-13
till golan...@googlegroups.com
On Friday 13 November 2009 23:59:05 Ian Lance Taylor wrote:
> Jon Harrop <j...@ffconsultancy.com> writes:
> > ...
> > * They replicated the billion dollar mistake.
>
> Go is just another programming language which addresses some issues
> that matter to us. If you don't like it, I encourage you to simply
> use one of the other fine languages you mention. Identifying all the
> ways that Go falls short of your ideal seems an ineffective use of
> time.

Go's language design FAQ says "Generics may well be added at some point" so I
am hoping to influence you by pointing out low-hanging fruit as early in the
development cycle as possible.

For example, if you use a VM with JIT compilation (e.g. LLVM) then you can
instantiate generic definitions per type in order to remove all run-time
performance penalties. I found the CLR's implementation of this to be an
excellent trade-off but it does complicate the implementation of polymorphic
recursion significantly if you have user-defined value types. However, I do
not value polymorphic recursion so I simply prohibited it in my
implementation.

> > Has anyone detailed the current implementations of goroutines (Cilk-style
> > wait-free work-stealing task deques?) and their GC?
>
> The GC is currently mark-and-sweep, and improving it is a high priority
> task.

I have been looking for an easy-to-implement mostly-concurrent garbage
collector and found the following VCGC garbage collector:

http://doc.cat-v.org/inferno/concurrent_gc/

If you have not already studied it, you may find it as inspirational as I did.

> Goroutines are coroutines multiplexed onto OS threads.

How exactly are they multiplexed? Work stealing or work sharing?

jqb

oläst,
13 nov. 2009 19:46:432009-11-13
till golang-nuts
On Nov 13, 4:38 pm, atomly <ato...@atomly.com> wrote:
> http://en.wikipedia.org/wiki/Ad_hominem#Common_misconceptions_about_a...
>

I know very well about the difference between an ad hominem fallacy
and an insult and have been writing online on that topic for 3
decades; I used the term correctly. Did you even bother to read your
reference?

"The fallacy only occurs if personal attacks are employed in the stead
of an argument to devalue an argument by attacking the speaker"

sergeyn

oläst,
13 nov. 2009 19:48:002009-11-13
till golang-nuts
btw, what's the point of having 'package main' in this program ? can
'packaging' be automatically implied ?

jqb

oläst,
13 nov. 2009 19:52:042009-11-13
till golang-nuts
On Nov 13, 4:38 pm, Peter Froehlich <peter.hans.froehl...@gmail.com>
wrote:
> Hi all,
>
> On Fri, Nov 13, 2009 at 7:17 PM, jqb <jqbal...@gmail.com> wrote:
> > On Nov 13, 3:59 pm, Ian Lance Taylor <i...@google.com> wrote:
>
> >> Go is just another programming language which addresses some issues
> >> that matter to us.  If you don't like it, I encourage you to simply
> >> use one of the other fine languages you mention.  Identifying all the
> >> ways that Go falls short of your ideal seems an ineffective use of
> >> time.
>
> > This attitude is a goodly part of what's wrong with the language.
>
> I think that's a little harsh, but I do see a point to the comment.

The point is that the language design suffers from insularity. In the
case of treating duck typing as something they invented, I would like
to *think* that it is merely insularity.

jqb

oläst,
13 nov. 2009 20:03:342009-11-13
till golang-nuts
On Nov 13, 4:34 pm, atomly <ato...@atomly.com> wrote:

> There are a lot of languages out there and some of them are very well
> suited for certain jobs.  Go was designed to fill a certain area and
> it will never directly compete with, say, JavaScript.

And yet, from the FAQ: "There is a growing rebellion against
cumbersome type systems like those of Java and C++, pushing people
towards dynamically typed languages such as Python and JavaScript. "

Go is *presented* as being an alternative to all of those. My point
was that an insular attitude on the part of the designers of a
language will prevent it from achieving such a lofty goal. Go is small
and elegant and provides good solutions to *some* problems, which is
nice, but it's not enough to address the real problems faced by many
programmers.

Peter Froehlich

oläst,
13 nov. 2009 20:06:392009-11-13
till golang-nuts, Michael Franz
Hi all,

On Fri, Nov 13, 2009 at 7:52 PM, jqb <jqba...@gmail.com> wrote:
> The point is that the language design suffers from insularity. In the
> case of treating duck typing as something they invented, I would like
> to *think* that it is merely insularity.

I don't think they claimed that, notably because it's *not* duck
typing, it's structural conformance of implementations to interfaces.
Which is of course not new either (and it wasn't ten years ago when we
first published papers on it). I just hope they'll fix it to get rid
of accidental conformance and of the old name clash problem, both of
which can be avoided with fairly minor changes to the language.

Jon Harrop

oläst,
13 nov. 2009 20:17:532009-11-13
till golan...@googlegroups.com
On Saturday 14 November 2009 01:06:39 Peter Froehlich wrote:
> I just hope they'll fix it to get rid of accidental conformance...

Can you elaborate on this?

Also, don't structurally-typed objects go against Go's efficiency goals? Is
the assumption that fast code isn't OO code (same as OCaml)?

jqb

oläst,
13 nov. 2009 20:31:112009-11-13
till golang-nuts
On Nov 13, 5:06 pm, Peter Froehlich <peter.hans.froehl...@gmail.com>
wrote:
> Hi all,
They may not say it outright but they leave that impression. As to
whether it's duck typing ... compatibility is determined statically,
but it's based on method names; there's nothing "structural" about it,
and I haven't seen any mention of the run-time cost of interface
method calls. From http://en.wikipedia.org/wiki/Duck_typing:

"in a non-duck-typed language, one can create a function that takes an
object of type Duck and calls that object's walk and quack methods. In
a duck-typed language, the equivalent function would take an object of
any type and call that object's walk and quack methods"

In Go, all you need to add to that is a local interface declaration.
However you want to classify it technically, from a programmer's POV
it walks and talks like duck typing.

Peter Froehlich

oläst,
13 nov. 2009 20:48:242009-11-13
till jqb, golang-nuts
Hi all,

On Fri, Nov 13, 2009 at 8:31 PM, jqb <jqba...@gmail.com> wrote:
> "in a non-duck-typed language, one can create a function that takes an
> object of type Duck and calls that object's walk and quack methods. In
> a duck-typed language, the equivalent function would take an object of
> any type and call that object's walk and quack methods"
>
> In Go, all you need to add to that is a local interface declaration.
> However you want to classify it technically, from a programmer's POV
> it walks and talks like duck typing.

Yes, and the "local interface" is a type, and that type is checked
when your function is called and when you call methods of the object
you were passed.

What "structural compatibility" means in this context is that the
object you pass must have a superset of the methods required by the
interface. In the duck typing example the object passed has no
(statically known) type when it comes in, the type is implicit in the
operations that get called on it (and succeed).

I love Python, and I love duck typing, but what Go does is simply not
the same. Another way to look at it: You won't get a "message not
understood" error in Go which you can obviously get under duck typing.

Peter Froehlich

oläst,
13 nov. 2009 20:52:342009-11-13
till Jon Harrop, golan...@googlegroups.com
Hi all,

On Fri, Nov 13, 2009 at 8:17 PM, Jon Harrop <j...@ffconsultancy.com> wrote:
> Also, don't structurally-typed objects go against Go's efficiency goals? Is
> the assumption that fast code isn't OO code (same as OCaml)?

Are you talking about the performance of the compiled code? That's not
really affected in a major way whether you use structural equivalence
or occurrence equivalence in your *static* type system.

It *could* be a little more overhead for the dynamic dispatch, but I
doubt it's noticeable if the implementation is smart. I didn't look at
the code for the dynamic dispatch though.

Russ Cox

oläst,
13 nov. 2009 20:55:382009-11-13
till Peter Froehlich, jqb, golang-nuts
> I love Python, and I love duck typing, but what Go does is simply not
> the same. Another way to look at it: You won't get a "message not
> understood" error in Go which you can obviously get under duck typing.

If you want a runtime check you can have a runtime check:

if _, ok := v.(io.Reader); !ok {
log.Exitf("Read message not understood");
}

The nice thing about Go, from our point of view, is the static
checking of most of the duck typing, which helps catch bugs
at compile time instead of run time.

Russ

Peter Froehlich

oläst,
13 nov. 2009 21:06:152009-11-13
till r...@golang.org, jqb, golang-nuts
Hi all,

On Fri, Nov 13, 2009 at 8:55 PM, Russ Cox <r...@golang.org> wrote:
> The nice thing about Go, from our point of view, is the static
> checking of most of the duck typing, which helps catch bugs
> at compile time instead of run time.

Oh I don't want runtime checks, trust me. :-D I was simply trying to
explain to the other guy that Go doesn't do duck typing. That's a good
thing in my book. I don't think you should keep calling it duck typing
either, that's simply a different thing. Say "you get most of the
benefit of duck typing" or something.

Jon Harrop

oläst,
13 nov. 2009 21:16:292009-11-13
till golan...@googlegroups.com
On Saturday 14 November 2009 01:52:34 Peter Froehlich wrote:
> Hi all,
>
> On Fri, Nov 13, 2009 at 8:17 PM, Jon Harrop <j...@ffconsultancy.com> wrote:
> > Also, don't structurally-typed objects go against Go's efficiency goals?
> > Is the assumption that fast code isn't OO code (same as OCaml)?
>
> Are you talking about the performance of the compiled code?

Yes.

> That's not really affected in a major way whether you use structural
> equivalence or occurrence equivalence in your *static* type system.
>
> It *could* be a little more overhead for the dynamic dispatch, but I
> doubt it's noticeable if the implementation is smart. I didn't look at
> the code for the dynamic dispatch though.

I ask because invoking a method of a structurally-typed object in OCaml is
over an order of magnitude slower than an ordinary function call.

How is dynamic dispatch implemented in Go?

jqb

oläst,
13 nov. 2009 21:19:512009-11-13
till golang-nuts
On Nov 13, 5:48 pm, Peter Froehlich <peter.hans.froehl...@gmail.com>
wrote:
> Hi all,
I understand that it's not the same technically, but from the POV of
the programmer or designer, one need only be concerned with the names
of the methods, not with where an object sits in an object hierarchy
-- which is why many programmers have looked at Go and said "hunh;
duck typing". The technical issues have to do with how to provide the
programming paradigm in a statically typed language. As for "message
not understood" -- because the method must be searched for at runtime,
one could build an executable that invokes a method call on an object
that doesn't have that method, and the search could fail; a paranoid
implementation that is worried about receiving objects that bypassed
compile-time type checks either because they were injected from
outside the language or because of a bug in the compiler could produce
the equivalent of "message not understood" if the search fails.

jqb

oläst,
13 nov. 2009 21:28:542009-11-13
till golang-nuts
On Nov 13, 6:06 pm, Peter Froehlich <peter.hans.froehl...@gmail.com>
wrote:
You're trying to explain something that I already understand. What you
don't seem to understand is that telling a couple of people on this
list not to call it duck typing won't stop people from calling it duck
typing, because it walks and talk like duck typing. Indeed you get
"most" of the benefit of duck typing, namely the part of the benefit
that deals with objects based on what methods they implement (whether
they walk and talk like ducks) rather than where they fall in a type
hierarchy (whether they are called ducks).

Ian Lance Taylor

oläst,
13 nov. 2009 21:30:022009-11-13
till Sebastian Sylvan, Jon Harrop, golang-nuts
We are more than happy to fix shortcomings, but I think it's important
to differentiate between shortcomings and language design choices.

Go is simply not in the same language space as languages like Scala
and Haskell. It's in the space of languages like C, Java, and, to
some extent, Python. Comparing it to Scala and Haskell can certainly
be fruitful, but a comparison like the one above does not to me appear
to be intended to be useful. It appears to be intended to be an
attack rather than a helpful criticism. Perhaps I am misreading it.

But I'll make some marginally more substansive responses, if you
like.

First let me note that it's perfectly fair to say that the language
space of C, Java, and Python is not the modern language space. But I
think it is also fair to say that that is a language space where the
majority of programmers work today. We wanted to create a language
which would be useful for us and for the majority of programmers at
Google, where we work.


> * They say "Go attempts to reduce the amount of typing in both senses of the
> word" but "Hello world" is several times longer in Go than in most modern
> languages.

What is the point of comparing the size of "hello, world"? We think
Go has less typing than languages like C, C++, and Java when writing
real programs.


> Also, they seem to have only very rudimentary type inference.

Yes. That is a language design choice.


> * Go was designed to be fast but preliminary results seem to indicatethat it
> is several times slower than most modern languages, even dynamic ones.
> Moreover, several fundamental design decisions degrade performance (e.g.
> structural typing) and the implementors do not seem to be aware of good
> existing solutions to important problems (e.g. generics on the CLR).

I am not aware of the preliminary results to which you refer. We have
some results which show that it is reasonable competetitive, though
somewhat slower than, C and C++. Again, that is the space we are in.

We are aware of generics. As we say in the FAQ, we are still
considering whether and how to add them to the language.


> * They said "say goodbye to stack overflows" but it sounds as though tail
> calls leak stack space.

As I've said before, tail calls are optimized in some circumstances.
They never "leak" stack space but they can certainly cause more stack
space to be used for a deep recursion than necessary. If this turns
out to be a problem for real programs, we'll fix it.

Note that this is not a language issue per se.


> * They state that development efficiency is a major goal, citing Python, but I
> cannot see a Go REPL.

It's early days yet. There is an experimental interpreter in
exp/eval.


> * They replicated the billion dollar mistake.

I would be more sympathetic to this comment if I saw NULL pointers
causing a lot of bugs in programs. I've seen far more programs fail
due to race conditions than I have due to NULL pointers, and we did
try to do something about that.

Ian

jqb

oläst,
13 nov. 2009 21:41:292009-11-13
till golang-nuts
On Nov 13, 5:52 pm, Peter Froehlich <peter.hans.froehl...@gmail.com>
wrote:
Unless the object or the interface has only one method, there surely
must be considerably more overhead. Given a method invocation x.quack
(), x could have any number of method calls, among which is quack. The
best the runtime can do is to pass to x's dispatcher a token
representing the interface and a token representing the name quack,
and x's quack method would be searched for among x's methods for the
interface. More likely, the runtime would pass to x's dispatcher a
token representing the name quack and x's quack method would be
searched for among all of x's methods.

Ian Lance Taylor

oläst,
13 nov. 2009 21:41:232009-11-13
till sergeyn, golang-nuts
sergeyn <nenakho...@gmail.com> writes:

> btw, what's the point of having 'package main' in this program ? can
> 'packaging' be automatically implied ?

All code has to be in some package, by design. We could make the
default be "package main", but that would be an exception, and I don't
personally think it would make a significant difference for real code.

Ian

Sverre Rabbelier

oläst,
13 nov. 2009 21:42:562009-11-13
till Ian Lance Taylor, sergeyn, golang-nuts
Heya,
I think the suggesion is to have the package name be determined by the
path, python style?

--
Cheers,

Sverre Rabbelier

jqb

oläst,
13 nov. 2009 21:47:312009-11-13
till golang-nuts
On Nov 13, 6:06 pm, Peter Froehlich <peter.hans.froehl...@gmail.com>
wrote:
Here is a blog entry that notes that 'Structural Typing [...] is often
described as being "type safe Duck Typing"'

http://beust.com/weblog/archives/000476.html

Peter Froehlich

oläst,
13 nov. 2009 21:47:502009-11-13
till jqb, golang-nuts
Hi all,

On Fri, Nov 13, 2009 at 9:41 PM, jqb <jqba...@gmail.com> wrote:
> Unless the object or the interface has only one method, there surely
> must be considerably more overhead. Given a method invocation x.quack
> (), x could have any number of method calls, among which is quack. The
> best the runtime can do is to pass to x's dispatcher a token
> representing the interface and a token representing the name quack,
> and x's quack method would be searched for among x's methods for the
> interface. More likely, the runtime would pass to x's dispatcher a
> token representing the name quack and x's quack method would be
> searched for among all of x's methods.

What you need is a mapping from the "methods" in the interface to the
actual methods an object has (and they may be in different "slots" of
the dispatch table in each and every object (well class of object) you
pass). So yeah, sounds like work.

Until you realize that only *some* combinations of interface /
implementation actually occur, not *all* of them. So once you build a
mapping, you cache it in the runtime. One call *may* actually lead to
the complete search overhead, but you could also try to be smarter
ahead of time.

In any case, that's what my statement was based on, that's what we did
for our language which had the same "problem" you are concerned about.

atomly

oläst,
13 nov. 2009 22:06:592009-11-13
till Ian Lance Taylor, sergeyn, golang-nuts
On Fri, Nov 13, 2009 at 9:41 PM, Ian Lance Taylor <ia...@google.com> wrote:
> All code has to be in some package, by design.  We could make the
> default be "package main", but that would be an exception, and I don't
> personally think it would make a significant difference for real code.

Thank you.

I realize my earlier response in this thread might have been a little
harsh (not enough sleep this week, maybe), but I just want to say once
again that I love what you guys are doing. Please, please, please
stick to your guns on this. I firmly believe in the findings
presented in that New Yorker article to which I linked-- people often
think that they _need_ this feature or that, or that the language
would be *so much* easier if just this one little exception existed,
but inevitably they just lead to a much murkier language definition
and myriad problems down the road.

Given all that, I'd have to say the one thing I don't like about Go as
it stands right now is the error handling-- and that is precisely
because it is an exceptional (pardon the pun) case. Built-in
functions get a special form of error handling that is not available
to other developers, and I think that's a really bad idea. I'd really
love it if the language allowed you to do something like "func foo(arg
int) int, maybe error" or "func foo(arg int) maybe int" or however
you'd want to express it. Basically, give all developers the ability
to write functions that can have the optional "_, ok" syntax.

Outside of that, I think Go is a really well thought-out language. I
really, really love that it focuses on clarity and simplicity. I've
only been coding with it for a few days now and I've already found a
few things that are _much_ easier to implement in Go than they are in
any of the other languages that I regularly use. It's like it has the
lightweight concurrency and message passing of Erlang, but with strong
typing, a cleaner syntax and significantly faster execution. Much
lower level and more consistent than Java, but much more modern than C
(without being as needlessly complex as C++). Languages like Python
and Ruby are nice for a lot of their modern features, but they really
don't fit in the same space as Go, which I really do consider to be a
system language.

Anyway, I'll try to stop jumping on people who are bitching about the
language, but it's really frustrating to be on the list, hoping to
discuss the language in earnest, only to have to read the same few
complaints over and over when they're clearly addressed in the FAQ, in
addition to being responded to multiple time by the language authors
on the list.

And, re: ad hominem attacks (a totally derail of the thread, sorry)--
my point was that it was not an ad hominem attack, because he did not
simply attack the poster, but instead made a real reply to him and
then pointed out what he thought he saw as a pattern in the poster's
history. Maybe it was unnecessary for him to bring that up, but
eliminate the part where he called him a "well-known troll" and his
post is perfectly valid.

Now it is Friday night and I will stop arguing about language design
on the intwerwebs.

Charles Forsyth

oläst,
14 nov. 2009 00:17:072009-11-14
till golang-nuts
"so I am hoping to influence you by pointing out low-hanging fruit as
early in the
development cycle as possible. "

Take care: "low-hanging fruit" is indeed the easiest to reach, but is
the least ripe
and thus least ready for consumption.

jqb

oläst,
14 nov. 2009 02:17:072009-11-14
till golang-nuts
a) Whether true of real fruit or not, that has no bearing on the
metaphor.
b) It's not true of real fruit.

Daniël de Kok

oläst,
14 nov. 2009 03:54:302009-11-14
till Jon Harrop, golan...@googlegroups.com
On Nov 14, 2009, at 12:45 AM, Jon Harrop wrote:
> Compare with F#:
>
> printf "Hello world"
>
> OCaml:
>
> print_string "Hello world"
>
> Haskell:
>
> main = putStrLn "Hello, World!"
>
> That Haskell looks verbose to me. :-)

What's the obsession with one-line hello worlds? ;) Personally I do not care, as long as it is convenient to write serious applications. In the languages that you mention a lot of typically imperative algorithms get long and ugly with a lot of let...ins. Or the reliance on folds where either the order is inverted or the folding is not tail-recursive.

Not to start a language flamewar, but everybody can come up with some his/her favorite pet peeve of what Go does not support. In the end all that matters is whether you can write performant and maintainable software in a language. A language where only the fibonacci function looks pretty is not very useful.

Take care,
Daniel

Intrigued Goer

oläst,
14 nov. 2009 06:25:212009-11-14
till golang-nuts
On Nov 14, 4:30 am, Ian Lance Taylor <i...@google.com> wrote:
> Sebastian Sylvan <sebastian.syl...@gmail.com> writes:
> > On Fri, Nov 13, 2009 at 11:59 PM, Ian Lance Taylor <i...@google.com> wrote:

> > * They replicated the billion dollar mistake.
>
> I would be more sympathetic to this comment if I saw NULL pointers
> causing a lot of bugs in programs.  I've seen far more programs fail
> due to race conditions than I have due to NULL pointers, and we did
> try to do something about that.

Some other thing being a bigger problem is no excuse.

Can you honestly say, that it's exceptional (pun totally intended) for
a complex Java application to produce NullPointerExceptions? That it's
rare that there's a security fix to some system program caused by null
pointer assignment? That in C programs, most of the null pointer error
checking and assertions aren't something that could be done at compile
time? That a lot of code related to null pointer handling will never
get executed, because the code isn't ever executed with null pointer,
and consequently some of that code likely has undiscovered bugs, so
that not only was the code written for nothing, it doesn't actually
prevent crashing or worse, if in future it gets called with null
pointer.

Seriously, incorrect handling of null pointers is one big source of
many kinds of subtle bugs and repetitive error checking code, and it
strongly affects just the domain that Go claims to be designed for.

Please consider if Go could do more here. Just separating non-nullable
and nullable pointers as different types would be cheap and solve a
lot of issues. Even if it was allowed to dereference nullable pointers
(and possibly cause segmentation fault), just type separation + non-
nullability being default + library functions systematically requiring
non-nullable pointers where appropriate would help a lot.

Heck, even just a syntax to require a function/method argument to be
guaranteed to be non-null would go a long way here, especially
combined with being able to tell that a function is guaranteed to
never return a null pointer (so a pointer returned by such a function
could be directly used as a parameter to another function requiring
non-null).

To prove the point about the trouble NULL pointers cause:

http://tinyurl.com/mozilla-bugzilla-nulls
http://tinyurl.com/netbeans-bugzilla-nulls

If that isn't enough proof, then search bug tracker of *any* large
piece of software done in a language that allows null pointers/
references... Do you want future bug trackers of software implemented
in Go to give similar search results?

Jon Harrop

oläst,
14 nov. 2009 09:15:112009-11-14
till golan...@googlegroups.com
That's why I focused on aspects that are already widely consumed.

Jon Harrop

oläst,
14 nov. 2009 10:07:352009-11-14
till golan...@googlegroups.com
On Saturday 14 November 2009 08:54:30 Daniël de Kok wrote:
> On Nov 14, 2009, at 12:45 AM, Jon Harrop wrote:
> > Compare with F#:
> >
> > printf "Hello world"
> >
> > OCaml:
> >
> > print_string "Hello world"
> >
> > Haskell:
> >
> > main = putStrLn "Hello, World!"
> >
> > That Haskell looks verbose to me. :-)
>
> What's the obsession with one-line hello worlds? ;)

Hello world was their example in the context of simplicity:

http://golang.org

Perhaps that page could use a more compelling example?

> In the languages that you mention a lot of typically imperative algorithms
> get long and ugly with a lot of let...ins. Or the reliance on folds where
> either the order is inverted or the folding is not tail-recursive.

Then a typically imperative algorithm would seem like a good example to
showcase Go's brevity. Can you suggest one?

> Not to start a language flamewar, but everybody can come up with some
> his/her favorite pet peeve of what Go does not support. In the end all that
> matters is whether you can write performant and maintainable software in a
> language.

Exactly.

Can you write performant code in Go? Without a decent implementation of
generics you cannot write performant reusable data structures (like the C++
STL, MLton SML basis library or F# standard library).

Can you write maintainable code in Go? With no way to express non-null
pointers in the static type system, you're repeating the billion dollar
mistake.

> A language where only the fibonacci function looks pretty is not very
> useful.

You say that as if these problems were not solved decades ago in languages
that are far more widely used to solve real problems than Go, Pascal, Modula,
Oberon, CSP, Newsqueak, Limbo...

Jon Harrop

oläst,
14 nov. 2009 10:24:292009-11-14
till golan...@googlegroups.com
On Saturday 14 November 2009 03:06:59 atomly wrote:
> On Fri, Nov 13, 2009 at 9:41 PM, Ian Lance Taylor <ia...@google.com> wrote:
> > All code has to be in some package, by design.  We could make the
> > default be "package main", but that would be an exception, and I don't
> > personally think it would make a significant difference for real code.
>
> Thank you.
>
> I realize my earlier response in this thread might have been a little
> harsh (not enough sleep this week, maybe), but I just want to say once
> again that I love what you guys are doing. Please, please, please
> stick to your guns on this. I firmly believe in the findings
> presented in that New Yorker article to which I linked-- people often
> think that they _need_ this feature or that, or that the language
> would be *so much* easier if just this one little exception existed,
> but inevitably they just lead to a much murkier language definition
> and myriad problems down the road.

Have C++, Java and C# not proven that generics really do make programming so
much easier and that generics are important in the context of performance?

> Outside of that, I think Go is a really well thought-out language. I
> really, really love that it focuses on clarity and simplicity. I've
> only been coding with it for a few days now and I've already found a
> few things that are _much_ easier to implement in Go than they are in
> any of the other languages that I regularly use.

May I ask what programming languages you regularly use?

> It's like it has the
> lightweight concurrency and message passing of Erlang, but with strong
> typing, a cleaner syntax and significantly faster execution. Much
> lower level and more consistent than Java, but much more modern than C
> (without being as needlessly complex as C++). Languages like Python
> and Ruby are nice for a lot of their modern features, but they really
> don't fit in the same space as Go, which I really do consider to be a
> system language.

Do you consider writing a web server to be systems programming?

> Anyway, I'll try to stop jumping on people who are bitching about the
> language, but it's really frustrating to be on the list, hoping to
> discuss the language in earnest, only to have to read the same few
> complaints over and over when they're clearly addressed in the FAQ, in
> addition to being responded to multiple time by the language authors
> on the list.

The FAQ states that:

"Generics are convenient but they come at a cost in complexity in the type
system and run-time."

Are generics not hugely important in the context of efficiency?

Does the implementation of generics that I cited really complicate the
run-time?

Ian Lance Taylor

oläst,
14 nov. 2009 12:11:192009-11-14
till Intrigued Goer, golang-nuts
Intrigued Goer <ari.hy...@gmail.com> writes:

> That it's
> rare that there's a security fix to some system program caused by null
> pointer assignment?

I'm genuinely curious about this one: can you point me to a security
fix to some system program caused by null pointer assignment?


> That in C programs, most of the null pointer error
> checking and assertions aren't something that could be done at compile
> time?

I'm completely in favor of having the compiler check.


> Just separating non-nullable
> and nullable pointers as different types would be cheap and solve a
> lot of issues.

My general point is that I do not think it would be cheap. I think it
would affect the language and use of the language in significant ways.


> Heck, even just a syntax to require a function/method argument to be
> guaranteed to be non-null would go a long way here, especially
> combined with being able to tell that a function is guaranteed to
> never return a null pointer (so a pointer returned by such a function
> could be directly used as a parameter to another function requiring
> non-null).

I believe this kind of thing can be done using annotations generated
directly by the compiler.

Ian

Ian Lance Taylor

oläst,
14 nov. 2009 12:12:042009-11-14
till Sverre Rabbelier, sergeyn, golang-nuts
We can consider it. I'm not personally a fan of source code which
changes behaviour if you rename the file, but perhaps it could be
workable.

Ian

Wei Hu

oläst,
14 nov. 2009 12:29:042009-11-14
till golang-nuts


On Nov 14, 12:11 pm, Ian Lance Taylor <i...@google.com> wrote:
> Intrigued Goer <ari.hytti...@gmail.com> writes:
> > That it's
> > rare that there's a security fix to some system program caused by null
> > pointer assignment?
>
> I'm genuinely curious about this one: can you point me to a security
> fix to some system program caused by null pointer assignment?

Not so long ago, Linux kernel was vulnerable to local privilege
escalation exploits, due to dereferencing of null pointers. See the
"Fun with NULL pointers" series on lwn:
http://lwn.net/Articles/342330/
http://lwn.net/Articles/342420/

And to quote a comment from http://lwn.net/Articles/234655/:
When will people learn to use programming languages that do not
overload types? Null is not an Integer, it is not an address. It is an
extra hacked on value. The actual type that should be used Maybe
Integer (to use Haskell types). If you use that then you're forced to
deal with the possibility of the failure up-front, thus such problems
go away.

Wei Hu

oläst,
14 nov. 2009 12:29:132009-11-14
till golang-nuts


On Nov 14, 12:11 pm, Ian Lance Taylor <i...@google.com> wrote:
> Intrigued Goer <ari.hytti...@gmail.com> writes:
> > That it's
> > rare that there's a security fix to some system program caused by null
> > pointer assignment?
>
> I'm genuinely curious about this one: can you point me to a security
> fix to some system program caused by null pointer assignment?

Russ Cox

oläst,
14 nov. 2009 12:44:422009-11-14
till Wei Hu, golang-nuts
> Not so long ago, Linux kernel was vulnerable to local privilege
> escalation exploits, due to dereferencing of null pointers. See the
> "Fun with NULL pointers" series on lwn:
> http://lwn.net/Articles/342330/
> http://lwn.net/Articles/342420/

That particular bug happened because Linux assumed that
the segmentation hardware would catch every NULL pointer
dereference, and malicious user programs could remap their
zero page to violate the assumption. The problem there is that
the kernel's correctness depended on a section of address space
shared with and managed by an untrusted program.

Ordinary user-level C programs don't have that problem--they
can just not map the zero page--but they do have a problem
when the NULL pointer reference is offset far enough off base
that the reference hits a mapped address. That is, C programs
assume that an infinite number of pages are unmapped starting
at address 0, which of course can't be true.

The Go implementations only assume that the first page is unmapped.
References with very large offsets check the base before allowing
the reference. No matter what you try, using a nil pointer will crash
the program, not access the wrong memory.

Russ

Sebastian Sylvan

oläst,
14 nov. 2009 12:49:512009-11-14
till Ian Lance Taylor, Intrigued Goer, golang-nuts
On Sat, Nov 14, 2009 at 5:11 PM, Ian Lance Taylor <ia...@google.com> wrote:
Intrigued Goer <ari.hy...@gmail.com> writes:

> That it's
> rare that there's a security fix to some system program caused by null
> pointer assignment?

I'm genuinely curious about this one: can you point me to a security
fix to some system program caused by null pointer assignment?


> That in C programs, most of the null pointer error
> checking and assertions aren't something that could be done at compile
> time?

I'm completely in favor of having the compiler check.


> Just separating non-nullable
> and nullable pointers as different types would be cheap and solve a
> lot of issues.

My general point is that I do not think it would be cheap.  I think it
would affect the language and use of the language in significant ways.

First, I don't think that's your general point at all. In your last post in the other discussion you still didn't even understand the concept. Don't act like you've argued against it on its merits all along - at most you only just understood it.

I think you should look at some of the languages that do this, because I think it's pretty clear by now that this really isn't that big of a deal. The vast majority of pointers do not have a sensible interpretation for null. In effect, the programmer already assumes they should never be null - this would just ensure that that the compiler enforces that assumption. There are a few cases where it's legitimate to get null back (e.g. opening a file) and you'd have to check those, but you already do that anyway!

I'd also like to point out that you're arguing against your own stated design principles here. You're saying that two totally separate concepts should be munged together under the same construct, but honestly I haven't seen a single positive argument for that so far. You keep saying that you don't think null dereferencing is a big problem (which I personally find to be a pretty remarkable claim!), but that's not a positive argument in favour of compromising your design principles (orthogonality, static safety).

What's so good about conflating references and nullness? You said you want to keep things orthogonal, so what's the reason for not sticking to that on this point? Why is Hoare wrong? Are you sure this isn't just a blind spot due to historical familiarity? Are you sure you really have a good technical reason for doing this?
 


> Heck, even just a syntax to require a function/method argument to be
> guaranteed to be non-null would go a long way here, especially
> combined with being able to tell that a function is guaranteed to
> never return a null pointer (so a pointer returned by such a function
> could be directly used as a parameter to another function requiring
> non-null).

I believe this kind of thing can be done using annotations generated
directly by the compiler.


Again, you should look at people who have already tried this (various static code analysis tools). It requires extremely complicated data flow analysis (which drastically hurts your compile times - another one of your stated goals!) and even then you only catch a tiny fraction of the problems.

Frankly I'm extremely surprised by the resistance to this. It's so obviously the right thing to do that I can't see how you could argue against it, really. 
The fact that you argued against it for half a dozen posts or so before you even bothered to understand it leads me to believe that it's more a knee-jerk defence mechanism than an actual argument, so I have to plead with you to actually take a look at this objectively for a second, and don't treat it like we're saying your baby is ugly. Very smart people have made this exact mistake before, and they've lived to regret it. I think it would be a shame if you don't take the opportunity to learn from their mistakes.

--
Sebastian Sylvan

Sebastian Sylvan

oläst,
14 nov. 2009 12:56:032009-11-14
till r...@golang.org, Wei Hu, golang-nuts
Agreed, but this is still a very common occurrence that's worth preventing statically when the cost of doing so is so tiny (it's all compile-time checks!). I just can't even imagine what kinds of programs you write if you never see null pointer crashes. 
You added a bool type, does that mean you see problems with not having a bool type more often than you see null pointer dereferences? I just can't buy that. Not having bool in C is annoying and sometimes leads to mysterious bugs, but it's not even close to the magnitude of dereferencing null pointers.

--
Sebastian Sylvan

Wei Hu

oläst,
14 nov. 2009 13:51:422009-11-14
till golang-nuts
I gave that kernel bug example just to show that even kernel
programmers can make null pointer bugs. Crashing a user space program
due to null pointer dereference is not a good thing. Other people have
made it clear that null pointers should be caught statically.

Guillaume Leconte

oläst,
14 nov. 2009 13:53:432009-11-14
till Sebastian Sylvan, r...@golang.org, Wei Hu, golang-nuts
On Sat, Nov 14, 2009 at 6:56 PM, Sebastian Sylvan
<sebastia...@gmail.com> wrote:

> You added a bool type, does that mean you see problems with not having a
> bool type more often than you see null pointer dereferences? I just can't
> buy that. Not having bool in C is annoying and sometimes leads to mysterious
> bugs, but it's not even close to the magnitude of dereferencing null
> pointers.

There is a type bool in C99.


--
« I've seen things you people wouldn't believe. Attack ships on fire
off the shoulder of Orion. I watched C-beams glitter in the dark near
the Tanhauser gate. All those moments will be lost in time like tears
in rain. Time to die. »

Intrigued Goer

oläst,
14 nov. 2009 14:37:562009-11-14
till golang-nuts
On Nov 14, 7:11 pm, Ian Lance Taylor <i...@google.com> wrote:
> Intrigued Goer <ari.hytti...@gmail.com> writes:
> > That it's
> > rare that there's a security fix to some system program caused by null
> > pointer assignment?
>
> I'm genuinely curious about this one: can you point me to a security
> fix to some system program caused by null pointer assignment?

Google is your friend:
http://www.google.com/search?q=denial+of+service+null+pointer
http://www.google.com/search?q=exploit+null+pointer
http://www.google.com/search?q=bugtraq+null+pointer

(And yes, DoS vulnerabilities are security vulnerabilities.)

> > That in C programs, most of the null pointer error
> > checking and assertions aren't something that could be done at compile
> > time?
>
> I'm completely in favor of having the compiler check.

But it's hard to do unless language directly supports it.

> > Just separating non-nullable
> > and nullable pointers as different types would be cheap and solve a
> > lot of issues.
>
> My general point is that I do not think it would be cheap.  I think it
> would affect the language and use of the language in significant ways.

I think the changes would be only superficial, a bit of new syntax
(like maybe struct initialisation after new, converting nullable
pointers to safe ones), some error values indicated differently, some
cases needing a default variable to point to, stuff like that.

Example solution for the specific issue of allocating structs with new
and not initialising them right away: Every struct could have an
implicit unsafe "sister type" where every pointer would be nullable.
New would return this type, and it would have to be explicitly
converted to the real type with non-nullable pointers after
initialisation. Because that's what the programmer does anyway, or
should do, at least putting a comment "struct now fully initialised"
where this conversion would be.

Note: I'm not claiming this is a good solution to anything, I haven't
given it enough thought and I don't know Go well enough, I give it
just to illustrate that these problems are solvable.

> > Heck, even just a syntax to require a function/method argument to be
> > guaranteed to be non-null would go a long way here, especially
> > combined with being able to tell that a function is guaranteed to
> > never return a null pointer (so a pointer returned by such a function
> > could be directly used as a parameter to another function requiring
> > non-null).
>
> I believe this kind of thing can be done using annotations generated
> directly by the compiler.

I don't really care how null pointer issue is solved, as long as it
follows Go design philosophy, and it prevents future Go programs from
showing up in above Google searches in a few years.

I'd go as far as to say that this feature could be something that
would really set Go above C(++) as a system programming tool. Other
stuff (channels, goroutines) could be implemented with C(++) library,
so it'd be just a matter of convenience, but native non-nullable
pointers would be impossible to do, for several reasons.

Ola Fosheim Grøstad

oläst,
14 nov. 2009 17:58:492009-11-14
till golang-nuts
On 14 Nov, 01:12, Sebastian Sylvan <sebastian.syl...@gmail.com> wrote:
> I don't think anyone would bother to come on this list and complain if they
> didn't like it in some sense, and want the few remaining niggles sorted out.

Like complaining about "hello world" and the lack of tail-recursion in
a systems programming language????

Ola.

Sebastian Sylvan

oläst,
14 nov. 2009 18:06:102009-11-14
till Ola Fosheim Grøstad, golang-nuts
I agree that "hello world" is a bit of a pointless thing to complain about (though I think the actual complaint was that it's not very terse at all, even though that's a design goal), but tail recursion is pretty crucial for message passing based programming (see essentially any Erlang code) which is a big selling point of Go.

I don't see how being a systems programming language means you should prefer to have the stack grow endlessly. Quite the opposite, in fact!

--
Sebastian Sylvan

Ola Fosheim Grøstad

oläst,
14 nov. 2009 18:23:162009-11-14
till golang-nuts
On 14 Nov, 18:44, Russ Cox <r...@golang.org> wrote:
> The Go implementations only assume that the first page is unmapped.
> References with very large offsets check the base before allowing
> the reference.  No matter what you try, using a nil pointer will crash
> the program, not access the wrong memory.

Compile time errors are better than crashes. Is Go is a system
programming language not to be used for embedded devices? Well, in
that case, maybe it should not be labeled so and rather be labelled as
a minimalistic server-programminglanguage for non-critical
applications...

I think Go has set off onto a very nice track, but it doesn't seem
like you guys have really managed to communicate in which direction
you are heading. I expect Go to improve, but if it isn't going to
provide for more error-catching facilities then it probably isn't
worth the trouble. Go has more competition than C and C++: D comes to
mind along with other smaller competitors.

I can understand if your motivation is to get channels/GC to work
efficiently before adding more cruft, but if you don't want to
increase programmer usability in the long term then that doesn't bode
very well for the future of the language. I expect a modern
"idealistic" language to support static analysis well. Not in the
first iteration, but in the long run.

Ola.

Jon Harrop

oläst,
14 nov. 2009 18:30:072009-11-14
till golan...@googlegroups.com
Does systems programming (which apparently includes writing web servers)
require incidental complexity and inefficient hand-written trampolines to
avoid stack overflows?

Noah Evans

oläst,
14 nov. 2009 18:29:402009-11-14
till Ola Fosheim Grøstad, golang-nuts
I'm current translating a bunch of Java server code into Go and go's
error handling is refreshing compared to the exception hell in the
Java code. It unsnarls all the try/catch nastiness and makes the
control flow much more explicit. Go's error handling and it's switch
statement flattens the code enormously.

Noah

Ola Fosheim Grøstad

oläst,
14 nov. 2009 18:50:382009-11-14
till golang-nuts
On 15 Nov, 00:30, Jon Harrop <j...@ffconsultancy.com> wrote:
> Does systems programming (which apparently includes writing web servers)
> require incidental complexity and inefficient hand-written trampolines to
> avoid stack overflows?

*tongue-in-cheek* Anyone who insists on doing infinite recursion in a
webserver needs to have their overly functional head examined. ;-)

Keeping the stack small is nice, of course, for many reasons. Avoiding
polluting the cache among other things. Removing the entire stack
frame for the sake of having infinite recursion shouldn't be a
priority for a non-functional language IMO. I cannot think of a
convincing use-case for imperative languages...

Ola.

Noah Evans

oläst,
14 nov. 2009 18:51:262009-11-14
till golan...@googlegroups.com
One of go's major advantages against the languages you advocate is
that by being simple, it gives you much more deterministic parsing,
code generation and behavior. You pay for this with a little bit of
added verbosity, but that's a tradeoff that, personally, I'm more than
willing to make.

Have you actually looked at the go source?

levi

oläst,
14 nov. 2009 19:03:212009-11-14
till golang-nuts
On Nov 15, 12:29 am, Noah Evans <noah.ev...@gmail.com> wrote:
> I'm current translating a bunch of Java server code into Go and go's
> error handling is refreshing compared to the exception hell in the
> Java code. It unsnarls all the try/catch nastiness and makes the
> control flow much more explicit. Go's error handling and it's switch
> statement flattens the code enormously.

How is this related to what the OP wrote?

-Levi

Sebastian Sylvan

oläst,
14 nov. 2009 19:08:432009-11-14
till Ola Fosheim Grøstad, golang-nuts
Web servers! :-)
Or at least servers in the general sense of small running "thread-like-things" that process incoming messages according to some protocol.

Seriously, tail calls is not just about recursion. Think of it as a composable form of goto. Imagine a big complicated message protocol for something. It's basically a big state machine with lots of states, each state can take a set of messages (a small subset of the whole set the server accepts) which take it to another state. You could implement this as a giant switch statement over all the messages, each case goto's another case at the end to do state transition, or maybe explicitly keep some state variable and jump to the right state each time. Anyway, the point is that in both cases you end up with big giant switches including every single state and every single message in your protocol. If you're lucky you'd at least put the actual work for each message in a separate function, but that's about all you can do.

With tail calls you write a single function that only deals with the toplevel messages. Maybe that's just 5 out of 500 possible messages, for example. Clearly the complexity of this function is drastically reduced. You can look at it at a glance and go "Okay, this main process can take one of 5 messages". Now, it would switch on this, and each case would just tail call to another function representing that state. Which again, is just a tiny subset of the messages so you can get a nice overview of what could happen in that state. Plus all these different functions that you're tail calling between can be implemented in different files (hard to do with goto!).

Anyway, this is getting too long. Suffice to say I'm not actually too worried about tail calls because I can't possibly see a future where Go takes off as a concurrency oriented language where it won't be implemented sooner or later. Eventually one of the authors will write a complicated message protocol and go "How the hell do they manage this bullshit in Erlang? Oh, tail calls!" and that will be that. It's almost guaranteed to happen, IMO.

--
Sebastian Sylvan

levi

oläst,
14 nov. 2009 19:11:492009-11-14
till golang-nuts
On Nov 15, 12:51 am, Noah Evans <noah.ev...@gmail.com> wrote:
> One of go's major advantages against the languages you advocate is
> that by being simple, it gives you much more deterministic parsing,
> code generation and behavior. You pay for this with a little bit of
> added verbosity, but that's a tradeoff that, personally, I'm more than
> willing to make.

Speaking in subjective terms I wouldn't call it simple. The different
semantics w.r.t. passing values to functions alone is very confusing
and ad-hoc. The same applies to parametric polymorphism which I hope
will be fixed. But there are too many ad-hoc cases in the language to
call it simple.

-Levi

Noah Evans

oläst,
14 nov. 2009 19:26:062009-11-14
till golang-nuts
Start with $GOROOT/src/cmd/gc/go.y and try comparing your code to what
[568]g -S spits out. Then you'll understand what I mean.

Jon Harrop

oläst,
14 nov. 2009 19:27:432009-11-14
till Noah Evans, golan...@googlegroups.com
On Saturday 14 November 2009 23:51:05 you wrote:
> One of go's major advantages against the languages you advocate

I mentioned languages as examples of implementations of various language
features. I was not advocating them.

> is that by being simple, it gives you much more deterministic parsing,
> code generation and behavior.

Absolutely. I greatly value deterministic parsing, code generation and
behaviour. Indeed, predictability is very important in my line of work
(scientific computing), particularly predictable performance.

> You pay for this with a little bit of added verbosity,

Have you tried to quantify the "little bit"? I think it is at least a factor
of 4 in LOC.

> but that's a tradeoff that, personally, I'm more than willing to make.

Then you must think that languages like OCaml and F# are unpredictable
compared to Go. Can you give examples demonstrating this effect?

> Have you actually looked at the go source?

Yes but I haven't read the whole thing yet. :-)

Indeed, I find it interesting to compare the Go implementation with my own
HLVM project because they have similar goals and are at a similar stage of
development in terms of the features they have implemented. I have invested a
total of around 1 man month in HLVM and it is under 2kLOC. In contrast, Go
has taken man years of development time and is 135kLOC.

Jon Harrop

oläst,
14 nov. 2009 19:32:432009-11-14
till golan...@googlegroups.com
Extensible state machines.

In an imperative language, you can implement an inextensible state machine by
jumping between code blocks using goto within a function. If you want to make
the state machine extensible (allowing the user to add new states) you're
screwed and the workaround is to Greenspun a trampoline which is the poor
man's emulation of tail call elimination: cumbersome and inefficient (e.g.
10x slower in Clojure).

If you have tail calls, your states become separate functions that call each
other without leaking stack space and you can easily add new functions to
extend the state machine with new states.

Jon Harrop

oläst,
14 nov. 2009 19:34:132009-11-14
till golan...@googlegroups.com
On Sunday 15 November 2009 00:08:43 Sebastian Sylvan wrote:
> Anyway, this is getting too long. Suffice to say I'm not actually too
> worried about tail calls because I can't possibly see a future where Go
> takes off as a concurrency oriented language where it won't be implemented
> sooner or later. Eventually one of the authors will write a complicated
> message protocol and go "How the hell do they manage this bullshit in
> Erlang? Oh, tail calls!" and that will be that. It's almost guaranteed to
> happen, IMO.

If Go takes off, yes. References (non-null pointers), exceptions and generics
seem to me to be the most important language features under discussion.

levi

oläst,
14 nov. 2009 19:33:112009-11-14
till golang-nuts
On Nov 15, 1:26 am, Noah Evans <noah.ev...@gmail.com> wrote:
> Start with $GOROOT/src/cmd/gc/go.y and try comparing your code to what
> [568]g -S spits out. Then you'll understand what I mean.

See, I was focusing on semantics rather than syntactic issues. In my
book its semantics which makes languages simple or not.

-Levi

Noah Evans

oläst,
14 nov. 2009 19:39:012009-11-14
till levi, golang-nuts
In my book simplicity, especially in a systems language, is how hard
it is to translate between the code I wrote and the machine code it
generates.

Ola Fosheim Grøstad

oläst,
14 nov. 2009 19:42:382009-11-14
till golang-nuts
On 15 Nov, 00:29, Noah Evans <noah.ev...@gmail.com> wrote:
> control flow much more explicit. Go's error handling and it's switch
> statement flattens the code enormously.

Go provides error handling? Guess what, even the minimal language Beta
had "co-routines/light threads", multiple return values and the same
kind of switch statement with comparable performance as Go has almost
two decades ago! + some powerful virtual concepts. (Heck, even it's
ancestor Simula, which c++ is based on, had some kind of co-routines
built in.)

What is promising about Go is not these concepts that have existed in
some fashion in programming langues since the 60s/70s. What makes Go
interesting is the combination of interfaces, channels and
"co-routines" combined with a promise about near-c-like-performance,
and the fact that Google has the money to carry through with their
vision.

I've never seen a programming language been promoted in major
newspapers world wide before, so yes Google have set expectations high
with this announcement... (Newsflash: "Google has invented a new
language") The vision that has been communicated is currently a bit
foggy, it doesn't match the noise and expectations... I am not saying
that they don't have one, I just say that I expect more from Google
than what is being communicated. I am not judging Go by what it is
today, but by where Google is taking it.

I've been following D for a long time, and Walter Bright has done a
great job with it, but he doesn't have the backing of a big
corporation. Today D is a much better language than Go, but it is
moving slowly and isn't as shiny as it could have been with more
man-years behind it. Now, Google is capable of bringing us a better
C++ because they have the money to do it, and the bright people, so I
am willing to bet on Go if they have a clear vision. Bright people
isn't enough, you also need a vision that go a bit further than
covering your own wants. There are enough academic languages or
oldfashioned languages out there, now we need a better modern
high-performance production language that caters for the programmer's
"health" (c++ being the anti-thesis).

Btw, I was arguing in favour of constructs that support and encourage
static code analysis, not exception-handling (which I also am in
favour of, though). The sole purpose of having a typed language with a
certain amount of strictness is to be able to do such analysis. We are
not living in the 1990s anymore, well, the microsofties are, but the
rest of the world should move on and make use of the available
techniques.

Ola.

Keith Sheppard

oläst,
14 nov. 2009 19:46:392009-11-14
till golang-nuts
Looking at the issue of tail calls from the other side: what is the
down side of adding guarantees for tail call optimization? Is there
any negative aside from the effort that it takes to implement in the
compiler which I am sure is not a trivial task? It's a feature that
would be very nice to have even if the answer is that it will take
some time before it's implemented. It doesn't add any complexity for
developers who don't care about it.

Keith

--
keithsheppard.name

Jon Harrop

oläst,
14 nov. 2009 19:59:062009-11-14
till golan...@googlegroups.com
On Sunday 15 November 2009 00:46:39 Keith Sheppard wrote:
> Looking at the issue of tail calls from the other side: what is the
> down side of adding guarantees for tail call optimization?

Good question.

> Is there any negative aside from the effort that it takes to implement in
> the compiler which I am sure is not a trivial task?

The simplest solution is surely to use LLVM because it already has an
excellent and tested implementation of tail call elimination (and superb
implementations of lots of other stuff that Go requires).

> It's a feature that
> would be very nice to have even if the answer is that it will take
> some time before it's implemented. It doesn't add any complexity for
> developers who don't care about it.

The main disadvantages are:

1. Tail call elimination can slow tail calls down slightly because function
arguments must be rearranged from one stack frame for the next.

2. Debugging information in eliminated stack frames is lost so tail call
elimination deletes information about tail calls from debug stack traces.

In practice, the slowdown is usually only ~10% and is shrinking because the
widening memory gap is making the improved locality of reusing stack frames
comparatively more efficient. And you can either disable tail call
elimination (as F# does in debug mode) or use an execution trace instead of a
stack trace (as Haskell does).

Jon Harrop

oläst,
14 nov. 2009 20:00:432009-11-14
till golan...@googlegroups.com
On Saturday 14 November 2009 23:06:10 Sebastian Sylvan wrote:
> tail recursion is pretty crucial for message passing based programming (see
> essentially any Erlang code) which is a big selling point of Go.

And asynchronous workflows in F#. See the section in Expert F# on message
passing, for example.

You should probably be more careful with your terminology in this context:
extensible state machines benefit enormously from *tail call elimination*.
Many people assume that "tail recursion" applies only to functions calling
themselves. Others (including myself when I cock up ;-) use "tail call" to
mean eliminated tail call when, in fact, all languages have tail calls. :-)

Ola Fosheim Grøstad

oläst,
14 nov. 2009 20:02:072009-11-14
till golang-nuts
On 15 Nov, 01:32, Jon Harrop <j...@ffconsultancy.com> wrote:
> Extensible state machines.

Ok, 1-0 to you, extensible SM was a convincing use case. I've never
had the need for this myself. I'd rather do source-code-generation for
non-extensible statemachines if possible.

I hope they add exceptions before doing this though. Exceptions are
supposedly hard to implement and have to be tailored to each language
(no silver bullett I believe), not sure how that effects the stack-
frames of Go.

Ola.

Jon Harrop

oläst,
14 nov. 2009 20:16:392009-11-14
till golan...@googlegroups.com
Yes, I agree that many of the other language features mentioned are higher
priorities than tail calls.

Goroutines look exactly like task parallelism to me (e.g. Cilk, Microsoft's
Task Parallel Library) except that tasks return values whereas goroutines do
not by default. When a task throws an exception, reading its value reraises
that exception. So I'm not sure what an idiomatic Go implementation of
exceptions might do instead...

Steve Newman

oläst,
15 nov. 2009 00:50:142009-11-15
till Noah Evans, Ola Fosheim Grøstad, golang-nuts
On Sat, Nov 14, 2009 at 3:29 PM, Noah Evans <noah....@gmail.com> wrote:
I'm current translating a bunch of Java server code into Go and go's
error handling is refreshing compared to the exception hell in the
Java code. It unsnarls all the try/catch nastiness and makes the
control flow much more explicit. Go's error handling and it's switch
statement flattens the code enormously.

Can you provide a concise before-and-after example that shows how error handling is simpler in the Go code than the Java code?

Steve

Intrigued Goer

oläst,
15 nov. 2009 01:08:342009-11-15
till golang-nuts
On Nov 15, 2:42 am, Ola Fosheim Grøstad
<ola.fosheim.gros...@gmail.com> wrote:
> On 15 Nov, 00:29, Noah Evans <noah.ev...@gmail.com> wrote:
>
> > control flow much more explicit. Go's error handling and it's switch
> > statement flattens the code enormously.
>
> Go provides error handling?

There is "defer" to handle cleanup in the function that got error.
There are multiple return values to conveniently pass error codes
onward. So for function local error handling, you set up cleanup code
on the way as needed instead of putting it in catches, and instead of
throwing, you return with error code. There's even goto, but usually
it shouldn't be needed for this.

I think a lot of people crying for exceptions would be perfectly happy
if "throw" was added as alias for "return" and "catch" was added as
alias for "if" ;-).

On the other hand, with goroutines and channels, it's not always clear
where the exception should ultimately propagate to.

Note: I'm not saying exceptions wouldn't be very very nice. But they
have their problems, and Go has sufficient mechanisms for clean error
handling, so exceptions shouldn't be added at any cost.

Noah Evans

oläst,
15 nov. 2009 11:34:412009-11-15
till Steve Newman, Ola Fosheim Grøstad, golang-nuts
There's no magic here. Here's some code that's been scrubbed to
protect the innocent with a direct go translation:

java:
if (null != thing) {
if (null == otherThing) {
try {
newThing =
LotsOfThings.getThingOfThings().getNewThing();

if (null == newThing) {
throw new ThingException("Cannot get thing");
}
} catch (IOException e) {
throw new ThingException("Cannot get thing");
}
}
return ThingHelper.checkThing(thing, object.thing().thing(),
object.thing().typeOfThing(), otherThing);
}

go:
// res and err are named returns

if thing == nil || otherThing != nil {
return;
}
newThing, err = LotsOfThings.GetThingOfThings().getNewThing();
if newThing == nil || err != nil {
err = ErrBadThing;
return;
}
res = ThingHelper.CheckThing(thing, object.Thing().Thing(),
object.Thing(), object.Thing().TypeOfThing(), otherThing);


There's nothing special about this. C has been doing things for ages.
Making manual "catches" with go's goto is another (very old) common
idiom that I prefer, see $GOROOT/src/cmd/hgpatch/main.go for good
examples of it in go.

This doesn't address the switch statement directly, but when I run
into 4+ levels deep if/else hierarchies, it's a lifesaver.

Noah

Steve Newman

oläst,
15 nov. 2009 12:34:002009-11-15
till Noah Evans, Ola Fosheim Grøstad, golang-nuts
[Side note: your examples aren't quite equivalent -- checkThing takes a different number of parameters, and if thing != null but otherThing == null, the first example will invoke checkThing while the second won't.  This has little impact on the code comparison, but it does mean that the Go sample was able to combine the first two ifs while the Java example was not.]

I would argue that the problems with the Java sample stem from poor design, not any inherent issue with exceptions.  Specifically:

1. Why is it that getNewThing() can throw IOException, but the code sample cannot?  If the desired behavior for thing problems is to throw ThingException, it would seem that this sample code -- which is merely manipulating Things, and not performing low-level transformations to e.g. reconstitute things from raw filesystem or database content -- is the wrong level to wrap an IOException in a ThingException.  Probably it should be in getNewThing, or some even lower layer.  (Side note: I'm not especially fond of this sort of wrapping at all; my style would be to let the IOException propagate indefinitely -- or rather, that would be my style if IOException were unchecked.  I do not like checked exceptions, in my experience that add much boilerplate but little value.  But I digress.)

2. Under what circumstances will getNewThing() return null?  If this can only be caused by serious problems, say out-of-memory or a database integrity violation, then getNewThing() should probably be throwing a ThingException instead.  Here, the Java example is mixing error codes (getNewThing returning null) and exceptions, so it's not surprising that it looks bad.

Suppose getNewThing were to throw ThingException when it can't get a thing, or when it incurs an IOException.  Then the Java code becomes:

  if (thing != null) {
    if (otherThing == null) {
      newThing = LotsOfThings.getThingOfThings().getNewThing();
    }
    return ThingHelper.checkThing(thing, object.thing().thing(), object.thing().typeOfThing(), otherThing);
  }

which, IMHO, is a lot more straightforward than either of the other versions, and needs no explicit error checking code at all.  In the Go equivalent, we would still have to check for and "rethrow" any error result from getNewThing.

The underlying issue here is that when programming-in-the-large, most code is neither the original trigger-point of an error (e.g. it is not directly performing I/O or checking integrity constraints) nor the ultimate authority able to capture and address the error (which is often the near the root RPC handler in a server, or near the event handler in a GUI app).  Exceptions allow you to write the great bulk of this "middleman" code without having to worry about error conditions.  Yes, this doesn't always hold; for instance, you need to be careful that an exception doesn't cause you to leak resources or leave some non-ephemeral data structure in an inconsistent state.  But in well-designed code, this comes up much less often than simple boilerplate error propagation.  The nice thing about exceptions is that their default behavior is the correct default for most middleman code.

Steve

Noah Evans

oläst,
15 nov. 2009 13:55:192009-11-15
till Steve Newman, Ola Fosheim Grøstad, golang-nuts
You're indirectly proving the go's designer's point. I took the code
example from a real java project created by very smart people(not me)
and you pointed out a variety of flaws in the exception handling and
propagation. Exception handling code is very hard to get right.

People may not like go's lack of exceptions, but for the work I'm
trying to do it's a *huge* win in terms of ease of design and
productivity.

Now it's your turn, can you provide run of the mill code using
exceptions that's cumbersome or annoying in go?

Ola Fosheim Grøstad

oläst,
15 nov. 2009 16:13:522009-11-15
till golang-nuts
On 15 Nov, 07:08, Intrigued Goer <ari.hytti...@gmail.com> wrote:
> There is "defer" to handle cleanup in the function that got error.

Ok, that is quite useful, especially when you use exceptions or gotos.
It is simliar to D's scope(exit/success/failure) and gets you some
RAII like behaviour. That's a very good start! (but not enough ;-)

> throwing, you return with error code.  There's even goto, but usually
> it shouldn't be needed for this.

I don't mind goto if it means avoiding conditional-errorhandling-bloat
which easily can make up 60% of your program... That's not good. What
if you errorhandling is buggy? When is your errorhandling going to be
fully tested? That's usually not possible.

That's why I think errorhandling should be made as simple as possible.
Errorhandling should be so simple that it is difficult to write buggy
errorhandling. These code paths are often not fully tested, yet it is
critical that they are correct in the deployed application. Exception
handling introduces some complexities and lack of transparency, but
when used properly you are more likely to avoid uncatched errors.

> I think a lot of people crying for exceptions would be perfectly happy
> if "throw" was added as alias for "return" and "catch" was added as
> alias for "if" ;-).

I don't like exceptions. Hell, I don't like errors. I try to write
code where I/O isn't littered around in the code for that reason. I'd
rather load a file into memory than using buffered I/O. The fewer
points of failure, the better.

But what I dislike more exceptions and errors is the ugly way of
handling errors in C/Unix, error-code-bloat, inconsistent return
values etc. It's a viral error-handling tree which is plain tedious to
get right, but not challenging, just tedious code-writing that get's
in the way of creativity and makes a program less readable. When
programming makes you feel like a mindless robot then there is
something wrong with the language, if it can be automated then it
should be. Proper use of exceptions is one solution that helps some. I
don't mind other solutions. What I mind is having my code littered
with error-propagating statements.

> But they
> have their problems, and Go has sufficient mechanisms for clean error
> handling, so exceptions shouldn't be added at any cost.

Agree. They shouldn't add exceptions until they know how they can get
it without a significant performance (or semantic) cost.

Ola.

Steve Newman

oläst,
15 nov. 2009 17:43:062009-11-15
till Noah Evans, Ola Fosheim Grøstad, golang-nuts
On Sun, Nov 15, 2009 at 10:55 AM, Noah Evans <noah....@gmail.com> wrote:
You're indirectly proving the go's designer's point. I took the code
example from a real java project created by very smart people(not me)
and you pointed out a variety of flaws in the exception handling and
propagation. Exception handling code is very hard to get right.

I pointed out no errors in the exception handling, merely that the API design was not ideal.  Proper API design is indeed difficult, and many code messes stem from poor APIs, but error handling has no monopoly on this.  I suggest you are not demonstrating that "exception handling is often messy" but simply that "real-world code is often messy".
 

People may not like go's lack of exceptions, but for the work I'm
trying to do it's a *huge* win in terms of ease of design and
productivity.

Now it's your turn, can you provide run of the mill code using
exceptions that's cumbersome or annoying in go?

Consider this method (taken from http://golang.org/src/pkg/tabwriter/tabwriter.go):

func (b *Writer) writeLines(pos0 int, line0, line1 int) (pos int, err os.Error) {
    pos = pos0;
    for i := line0; i < line1; i++ {
        line := b.line(i);
        for j := 0; j < line.Len(); j++ {
            c := line.At(j).(cell);

            if j > 0 && b.flags&Debug != 0 {
                if err = b.write0(vbar); err != nil {
                    return
                }
            }
            switch {
            default: // align left

                if err = b.write0(b.buf.Bytes()[pos : pos+c.size]); err != nil {
                    return
                }
                pos += c.size;
                if j < b.widths.Len() {
                    if err = b.writePadding(c.width, b.widths.At(j)); err != nil {
                        return
                    }
                }

            case b.flags&AlignRight != 0: // align right

                if j < b.widths.Len() {
                    if err = b.writePadding(c.width, b.widths.At(j)); err != nil {
                        return
                    }
                }
                if err = b.write0(b.buf.Bytes()[pos : pos+c.size]); err != nil {
                    return
                }
                pos += c.size;
            }
        }

        if i+1 == b.lines.Len() {
            // last buffered line - we don't have a newline, so just write
            // any outstanding buffered data
            if err = b.write0(b.buf.Bytes()[pos : pos+b.cell.size]); err != nil {
                return
            }
            pos += b.cell.size;
        } else {
            // not the last line - write newline
            if err = b.write0(newline); err != nil {
                return
            }
        }
    }
    return;
}

This is classic "middleman" code: its only role in error handling is to propagate errors from the Writer.  If exceptions were being used, all of the bolded code could be removed.  (If anyone is reading this in a plain-text client: all seven instances of "if err =" and "err != nil { return }".)

To emphasize what this does to code clarity, let me repeat the "align left" clause with and without error handling:

                if err = b.write0(b.buf.Bytes()[pos : pos+c.size]); err != nil {
                    return
                }
                pos += c.size;
                if j < b.widths.Len() {
                    if err = b.writePadding(c.width, b.widths.At(j)); err != nil {
                        return
                    }
                }
----------------
                b.write0(b.buf.Bytes()[pos : pos+c.size]);
                pos += c.size;
                if j < b.widths.Len() {
                    b.writePadding(c.width, b.widths.At(j));
                }

That's an example where the lack of exceptions -- or, more precisely, the lack of a "propagate by default" error mechanism -- badly clutters the code.  There are also plenty of examples in the Go tree that are just plain incorrect.  For instance, consider this snippet from http://golang.org/src/pkg/http/request.go:
func (req *Request) Write(w io.Writer) os.Error {
    uri := URLEscape(req.URL.Path);
    if req.URL.RawQuery != "" {
        uri += "?" + req.URL.RawQuery
    }

    fmt.Fprintf(w, "%s %s HTTP/1.1\r\n", valueOrDefault(req.Method, "GET"), uri);
    fmt.Fprintf(w, "Host: %s\r\n", req.URL.Host);
    fmt.Fprintf(w, "User-Agent: %s\r\n", valueOrDefault(req.UserAgent, defaultUserAgent));
    ...
The error result from fmt.FPrintf is ignored; this could lead to silently incorrect behavior.  (Full disclosure: I contributed a bit of code to the http package; this might possibly be my bug.  In any case, there are plenty of other examples in the libraries where fmt.Fprintf's result is ignored.)  This, in my mind, is the single worst thing about error codes: it's so pathetically easy to forget to check them.

Steve

Charles Forsyth

oläst,
15 nov. 2009 18:37:072009-11-15
till golang-nuts
"This, in my mind, is the single worst thing about error codes: it's
so
pathetically easy to forget to check them."

I think it's more deliberate than that: the code would become so
cluttered
with error checking if every operation were checked that programmers
simply
decide which ones they think will actually matter. For instance, in
the
case above, the most likely cause of an error return from Fprintf
is that the connection on w has gone away, so the server will waste
some time preparing output that won't go anywhere (assuming the
underlying system doesn't send a signal, which I suppose it might).

Worse are the schemes that encourage things like C's (void) to
state that you're ignoring an "error" return (that you don't think
matters).
Now you've got the worst of both worlds: you're ignoring the error
return
but the code is still cluttered and harder to read. Brilliant!

Charles Forsyth

oläst,
15 nov. 2009 18:57:322009-11-15
till golang-nuts
As to comments on language design. Computer language
design is probably best viewed as a sport. The pubs and papers
are surely full of sports fans discussing strategy and tactics of the
various teams, even when they themselves have not bowled
or kicked a ball for years, or are even physically unfit to do so.

Ian Lance Taylor

oläst,
15 nov. 2009 19:22:142009-11-15
till Jon Harrop, golan...@googlegroups.com
Jon Harrop <j...@ffconsultancy.com> writes:

> I ask because invoking a method of a structurally-typed object in OCaml is
> over an order of magnitude slower than an ordinary function call.
>
> How is dynamic dispatch implemented in Go?

The two compilers implement it differently, but in both of them a
value of interface type holds a pointer to a table of functions.
Calling a method means loading the pointer and calling the function at
the appropriate table offset. In other words, pretty much the same as
calling a virtual function in C++.

Ian

Ian Lance Taylor

oläst,
15 nov. 2009 19:28:312009-11-15
till Sebastian Sylvan, golang-nuts
Sebastian Sylvan <sebastia...@gmail.com> writes:

>> > Heck, even just a syntax to require a function/method argument to be
>> > guaranteed to be non-null would go a long way here, especially
>> > combined with being able to tell that a function is guaranteed to
>> > never return a null pointer (so a pointer returned by such a function
>> > could be directly used as a parameter to another function requiring
>> > non-null).
>>
>> I believe this kind of thing can be done using annotations generated
>> directly by the compiler.
>>
>>
> Again, you should look at people who have already tried this (various static
> code analysis tools). It requires extremely complicated data flow analysis
> (which drastically hurts your compile times - another one of your stated
> goals!) and even then you only catch a tiny fraction of the problems.

Just to address this point: doing the analysis in an existing language
is much more difficult than doing it in a new language. For example,
a Go compiler could annotate in the export data of a function whether
it dereferences a pointer. Since all imported functions will contain
this annotation, this reduces the problem to analyzing the functions
in a single package. Checking whether a function dereferences a
pointer is simple enough, and checking whether it checks for nil first
is simple enough. It seems to me reasonably straightforward to do a
conservatively correct check here. There would certainly be some
false positive warnings in complex code, but I think there would be
very few false negatives.

I think you are getting a little personal in some of your other
comments, so for the moment I will decline to respond.

Ian

Ian Lance Taylor

oläst,
15 nov. 2009 19:31:542009-11-15
till Intrigued Goer, golang-nuts
Intrigued Goer <ari.hy...@gmail.com> writes:

> I think the changes would be only superficial, a bit of new syntax
> (like maybe struct initialisation after new, converting nullable
> pointers to safe ones), some error values indicated differently, some
> cases needing a default variable to point to, stuff like that.
>
> Example solution for the specific issue of allocating structs with new
> and not initialising them right away: Every struct could have an
> implicit unsafe "sister type" where every pointer would be nullable.
> New would return this type, and it would have to be explicitly
> converted to the real type with non-nullable pointers after
> initialisation. Because that's what the programmer does anyway, or
> should do, at least putting a comment "struct now fully initialised"
> where this conversion would be.

At first glance I don't find this to be very simple. Perhaps I am
missing something.

Does somebody want to make a concrete proposal for how the language
should be changed?

Ian

Rob 'Commander' Pike

oläst,
15 nov. 2009 19:51:332009-11-15
till Steve Newman, golang-nuts
> (j)); err != nil {
It's not a general solution but there are many cases when the
following idea can help. Imagine you're writing a parser and you want
to get out cleanly when you find a syntax error.

We have some type, say Parser.

type Parser struct {
...
}

We want to be able to write something like this in a method of *Parser:

if somethingBad() {
p.Error("you made a mistake")
}

and be done with it. It's easy if we run the parser in a goroutine.
Add a channel to the Parser:

type Parser struct {
....
error chan string;
}

Then write an Error method that calls runtime.Goexit() to abort the
parse:

func (p *Parser) Error(e string) {
fmt.Fprintf(os.stderr, "syntax error on line %d: %s\n", p.lineNum, e);
p.error <- e; // deliver the error
runtime.Goexit(); // terminate the parsing goroutine
}

Finally we write the parser main function like this:

func Parse(r io.Reader) (p *Parser, err string) {
p = new(Parser);
p.error = make(chan string);
// Run the parser method as a goroutine.
go p.Parse(r);
// wait for it to complete.
err = <-p.error;
if err != nil {
p = nil
}
return
}

This clearly takes more setup than exceptions might, but not much, yet
the parser itself can be as clean as Steve Newman wants. And it works
really well for cases like this, or cases where we're running a
goroutine anyway for something like serving a client request from the
network.

The flaw in this is that the current implementations do not call
deferred functions on the way out of the goroutine, which they should,
but that's just a bug and will be fixed.

-rob

jesse.dailey

oläst,
15 nov. 2009 21:44:052009-11-15
till golang-nuts
On Nov 13, 6:29 pm, Jon Harrop <j...@ffconsultancy.com> wrote:
>
> * They state that development efficiency is a major goal, citing Python, but I
> cannot see a Go REPL.
>

There are two different variations of REPL that have popped up
already.

This one works like Python's does (each statement is parsed and
compiled then executed in a persistent scope, called a 'World' in Go):
http://groups.google.com/group/golang-nuts/msg/019ba46aa4567763

There is another one that works by pushing strings into a .go file and
compiling it, which allows for one-liners only (as i understand it):
http://groups.google.com/group/golang-nuts/msg/3c23b5696b43c00f

The biggest problem with Go is just that it's young. But the
development seems to be moving quickly, so you are jumping the gun to
complain.

Steve Newman

oläst,
16 nov. 2009 00:15:372009-11-16
till Charles Forsyth, golang-nuts
On Sun, Nov 15, 2009 at 3:37 PM, Charles Forsyth <charles...@gmail.com> wrote:
"This, in my mind, is the single worst thing about error codes: it's
so pathetically easy to forget to check them."

I think it's more deliberate than that: the code would become so
cluttered with error checking if every operation were checked that programmers
simply decide which ones they think will actually matter.

Yes, plausibly this was the case.  But I don't think it's much of a defense of the error-code approach -- it's just programmers trying to make the best of their bad choices (cluttering the code or ignoring errors).

 
For instance, in
the case above, the most likely cause of an error return from Fprintf
is that the connection on w has gone away, so the server will waste
some time preparing output that won't go anywhere (assuming the
underlying system doesn't send a signal, which I suppose it might).

Key phrase here is "most likely cause".  Someday, another cause might come along, yielding a worse result, such as a corrupted message being sent.  This could even lead to a security hole -- if an attacker could somehow arrange for the header to fail to be sent, then the request body could be interpreted as a header, leading to all sorts of amusement.  That may be a bit of a stretch, but multiply by enough similar coding instances and the odds go up.

Really the issue is very simple: do we honestly want to encourage programmers to ignore errors?

Steve

Steve Newman

oläst,
16 nov. 2009 00:34:032009-11-16
till Rob 'Commander' Pike, golang-nuts
This is a nice trick for, as you say, some cases.  But with the language and libraries as they stand, I don't see it becoming widely adopted.  You'd need glue code whenever error-result code and throw-via-channel code intersect.  The libraries all use error results, and a body of error-result-based code is now accumulating, so throw-via-channel seems likely to be confined to small islands -- available when you really want it, as in the parser example, but not the mainstream technique.

Not to belabor the point, but I'm genuinely curious: are you (Rob, or anyone else on the team) happy with the status quo as illustrated in the two code snippets I referenced a couple of messages back?

(I think it's understood, but to be clear: I'm not suggesting the house is on fire, merely wondering what the consensus is regarding the decor.)

Steve

drewfish

oläst,
16 nov. 2009 00:45:392009-11-16
till golang-nuts
> So I'm not sure what an idiomatic Go implementation of
> exceptions might do instead...

Perhaps instead of just throwing an exception, and exception is thrown
onto a channel. Trying to read from a channel with an exception on it
propagates the exception to the reader's thread.

If the above were true, I can imagine sometimes needing to implement a
proxy goroutine that stops propagation of a wrapped goroutine's
exceptions.

If an exception is not thrown to a particular out channel, it goes to
all out channels. Alas, this is a bit like a burning neighborhood --
one house on fire causes all neighbors to catch fire, which catches -
their- neighbors on fire, etc.

Drew

Rob 'Commander' Pike

oläst,
16 nov. 2009 00:58:382009-11-16
till Steve Newman, golang-nuts

On Nov 15, 2009, at 9:34 PM, Steve Newman wrote:

> Not to belabor the point, but I'm genuinely curious: are you (Rob, or anyone else on the team) happy with the status quo as illustrated in the two code snippets I referenced a couple of messages back?
>
> (I think it's understood, but to be clear: I'm not suggesting the house is on fire, merely wondering what the consensus is regarding the decor.)

I think what's written in the FAQ is honest. We know their purpose, they can help, but we haven't yet found a design we are confident won't infect everything but still be useful. Exceptions should be exceptional. We continue to think about it.

I'm happier with the status quo than with implementing something I'm not satisfied will be right.

-rob

Ola Fosheim Grøstad

oläst,
16 nov. 2009 04:13:392009-11-16
till golang-nuts
On 16 Nov, 01:31, Ian Lance Taylor <i...@google.com> wrote:
> Does somebody want to make a concrete proposal for how the language
> should be changed?

1. Add a new syntax for non-nil pointers "&".
2. Require &pointers to take a value before they are used.
3. Only allow assignment from *pointers to &pointers where they have
been established as non-nil at compile time.
4. Optional: only allow assignment from &pointers to *pointers after
they take a value.

Or did you mean something else?

Ola.

Sebastian Sylvan

oläst,
16 nov. 2009 06:17:342009-11-16
till Ian Lance Taylor, golang-nuts
It strikes me that you're just jumping through hoops to avoid the obvious solution. How is this analysis in any way preferable to plain old type checking that everyone already understands? You're over-complicating things.


--
Sebastian Sylvan

Sebastian Sylvan

oläst,
16 nov. 2009 06:19:102009-11-16
till Ola Fosheim Grøstad, golang-nuts
I think you should just make regular old pointers non-nil. Then you add another type for "nullable" things (e.g. use ?). This can be used with any type, including pointers, to indicate the possibility of an invalid value. 

--
Sebastian Sylvan

Ola Fosheim Grøstad

oläst,
16 nov. 2009 09:10:382009-11-16
till golang-nuts
On 16 Nov, 12:19, Sebastian Sylvan <sebastian.syl...@gmail.com> wrote:
> I think you should just make regular old pointers non-nil. Then you add
> another type for "nullable" things (e.g. use ?). This can be used with any
> type, including pointers, to indicate the possibility of an invalid value.

I don't think of nil as an invalid "value" for a pointer. It can be
used to model "not yet known" or "doesn't have". I think using a
separate notion for non-nil increase readability in more complex types
+ it is kind of similar to C++ so it makes the langauge seem less odd
to many new users picking it up. I am personally so used to the
semantics of *pointers that I prefer they stay the way they are.

Ola.

Intrigued Goer

oläst,
16 nov. 2009 12:04:432009-11-16
till golang-nuts
On Nov 16, 2:31 am, Ian Lance Taylor <i...@google.com> wrote:
Let's see.

Pointers would by default be non-nullable, "safe".

Using ! in front of type would make all pointers in that type (or just
itself if it's a pointer ie. !*) nullable. So a nullable version of
struct containing non-nullable pointers could be easily made, and I
geuss a nullable pointer to nullable version of a struct would be !*!.
Alternatively some keyword notation could be used, but I'm not sure
that would fit with current Go syntax very well?

To make nullable pointer or struct temporarily safe, the syntax could
be:
ifsafe var [, var...] then {
// vars are as if they were declared without !
}
else {
// some nil pointers found
}

Keyword "ifsafe" is just a suggestion, but at least it's short and
matches nicely with "else". Test should not be piggypaged to regular
if, since it would mess up short-circuit condition evaluation, and
since it has a side effect inside "then"-part of if.

Note: ifsafe could be used with floating point values to filter out
NaNs and infinities. Some other uses might be sensible too. I'm not
sure if Go strings can be nil in addition to empty, but if they can
be, this would nicely work with them too.

Nullable types could not be dereferenced. There might be some rare
cases where it would be nice to dereference nullable pointers without
"ifsafe", but I don't think they'd be worth the complexity, and would
partly defeat the whole purpose of not being able to dereference nil.

When initializing non-nullable items, all non-nullable fields would
have to be initialized. Either composite literal or a constructor
method could be given, which could also receive eg. array index if
it's being used with array allocation. Constructor would have to
assign all non-nullable fields before return. This would be identical
to any "variable might be used before initialization" check by
compiler, performed at constructor return, as assigning to non-
nullable field would guarantee it to be non-null. In array
initialization, constructor could receive the array (or slice?) and
index, but so that all other elements of array would be considered
nullable, or possibly with special restriction that they would write-
only. Purpose of this is to allow constructor to initialize other
members of same array to point to itself.

Constructor method would not be specially declared, any method could
be constructor if used as a constructor (or give compiler error if it
did not meet constructor requirements). Would argument types of given
method be valid way (in Go compilation context) to determine what kind
of constructor it is? I mean, would it take single struct, pointer to
struct, array and index, etc? Considering that there is no
overloading, this should be rather simple, I think?

If a struct containted pointers to it's own type, pointer to itself
could be used instead of nil value (combined with a flag or something
if pointing to itself would have other meanings as well).

No "default values" to point to should be provided by compiler. If
programmer needs them, he should declare them himself as needed.

There. I'm sure there are some holes in above suggestion, but is there
anything fundamentally broken?

Ian Lance Taylor

oläst,
16 nov. 2009 13:33:012009-11-16
till Sebastian Sylvan, golang-nuts
Because I think that the type checking approach (which you haven't
spelled out in detail) carries costs which you are not acknowledging.
The solution may be obvious to you but it is not obvious to everyone.

Ian
Den läser in fler meddelanden.
0 nya meddelanden