Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

Let me explain, Rather than trying to make a language as aesthetically pleasing to the programmer as possible, the Go team tried to get by its limitations with design kludges and workarounds that are visually less appealing and intuitive then the many well-designed solutions that preceded it, e.g:

  - Error codes are a poor substitutions for Exceptions

  - Have to code around lack of generics, e.g. by abusing their typed map if possible 

  - Defer less desirable and intuitive than C# using

  - array bracket notation prefixing the variable

  - No proper classes?
I mean, take their example on a File type (http://golang.org/doc/go_tutorial.html):

type File struct { fd int name string }

func (file File) Read(b []byte) (ret int, err os.Error) {}

func (file File) Write(b []byte) (ret int, err os.Error) {}

file := &File{fd, "file.txt"}

The same signatures in CoffeeScript can be achieved by:

class File

  constructor: (@name) ->

  read: (cb) ->  

  write: (contents) ->
file = new File "file.txt"

Which I'm sure a majority of people would find a lot more readable.

Just for kicks I decided to rewrite Go's Cat example to StdOut in CoffeeScript for a side-by-side comparison. The examples are fairly close but not exact, i.e. cat.Go implements via streaming while CoffeeScript's is non-blocking.

https://gist.github.com/1207994

The CoffeeScript version ways in at 12 LOC, while Go's example is over 110 LOC and a lot more unfriendlier on the eye.



I didn't want to get into a slinging match, but I take issue with all of your points.

"Error codes are a poor substitutions for Exceptions" This is debatable.

"Have to code around lack of generics" Some people complain about this, but in practice their absence hasn't been a big problem. It's still an open issue, though.

"Defer less desirable and intuitive than C# using" Again, debatable.

"array bracket notation prefixing the variable" http://blog.golang.org/2010/07/gos-declaration-syntax.html

"No proper classes?" This is a bizarre complaint. Go doesn't have classes. It has types and methods. Why would you need classes? What is a "proper" class?

The tone of your complaints implies that we didn't consider any of these things, or that these decisions were made through sheer incompetence. This couldn't be further from the truth. Language design is just as much about what you exclude as what you include. One of Go's major strengths is its simplicity. It's a very small language; so small, you can read the spec in one sitting! http://golang.org/doc/go_spec.html

As has been pointed out already, your comparison between Go and CoffeeScript is not illustrative of much. Go is typed, CoffeeScript is not. The "cat" comparison is very strange. Your (very unidiomatic, and in some places plain wrong) Go program re-implements everything from a syscall level, while the CoffeeScript example uses library calls. Why?

Here's how one might write a similar "cat" in Go:

    package main

    import (
        "io"
        "log"
        "os"
    )

    func cat(name string) os.Error {
        f, err := os.Open(name)
        if err != nil {
            return err
        }
        defer f.Close()
        if _, err = io.Copy(os.Stdout, f); err != nil {
            return err
        }
        return nil
    }

    func main() {
        for _, arg := range os.Args[1:] {
            if err := cat(arg); err != nil {
                log.Print(err)
            }   
        }
    }
This handles multiple files specified on the command line, and handles errors. (The CoffeeScript one just throws them, right?) Not bad for 24 lines of code.


If you considered them it's even worse - by keeping the language simple you've made it more unintuitive and less readable for the programmer. IMHO the primary beneficiaries of Go are the compiler writers, not the programmers having to read and write source code.

Your example is not the same, this is just a C-style single method. The whole point of my example was using Go's own sample source code to showcase the hacks needed around structs to get around the deficiencies in not having classes. The resulting struct method signatures are ugly, verbose and unintuitive - it's not nearly as readable and wrist friendly as grouping them in a single class definition.

In following this pattern the defer keyword is a magic method that doesn't visually demonstrate its behaviour - compare that with C#'s using statement which does.


If that's what you were trying to demonstrate then you were pretty far off the mark. The two programs are far from equivalent, and your Go code is just bizarre.

I think this statement of yours is quite revealing: "Your example is not the same, this is just a C-style single method." It's not a "single method," it's a function. Not everything is or should be about object orientism. It's not always the right choice, and people who obsess over making everything an object (those who think functions are a special type of method) are doomed to overcomplicate their design. (For example, there is no reason you should need to construct new objects to write cat.)

I'm confused as to why someone who clearly doesn't know Go would try so hard to discredit it. What's your motivation?


The Go code is bizarre? That's the introductory Go tutorial showing off Types in Go (http://golang.org/doc/go_tutorial.html) Not a single line of the Go code is mine (I just copy and pasted the entire tutorial in a single file). If you want to blame someone for making Go look bad - blame the author of the tutorial - or better yet the inventors of the Go Language.

If you think OOP is not important for building and encapsulating large software code bases, then we operate in different worlds and Go wasn't designed for my purposes in mind. Feel free to keep using Go as a better C and I'll stick to mainstream languages without these deficiencies (aka trade offs).


Just to play devil's advocate, here's what that example would look like with exceptions and something like `using()` in C# (here, any curly block can implicitly be treated like a try block, like in Ruby):

    package main

    import (
        "io"
        "log"
        "os"
    )

    func cat(name string) {
        using (f := os.Open(name)) {
            io.Copy(os.Stdout, f)
        }
    }

    func main() {
        for _, arg := range os.Args[1:] {
            cat(arg);
        } catch (err os.Error) {
            log.Print(err)
        }
    }


That's a terribly biased comparison. The go example defined stdin/stdout/stderr from scratch and much else besides, while the coffeescript version basically called a library function.

It's very hard to compare statically-typed system languages with dynamically-typed HLLs. And it's utterly misleading to judge one by the standards of the other.


Your comparison is unfair, because CoffeeScript and Go try to do vastly different things. Go is a fairly low level systems language, while CoffeeScript is as high level as it gets.

That said, what Go achieves with its syntax is remarkable, imho.

Consider this: How do you add another function (e.g. "close()") to your file class in CoffeeScript? By extending the existing class into a "MyFile" class? But then you have to make sure all your "File" instances are actually instances of "MyFile", so you can call your newly defined function on them.

In Go you just define the new function.


Not to detract from your point of vastly different things, but you picked a bad example. You add a method to the prototype:

    File::close = ->
Et voilà, all Files are closeable.


Nice, I didn't know that CoffeeScript has a shorthand for .prototype.

So, to revise my point: with "proper" classes (i.e. Java or C++) this wouldn't be possible, or at least more complicated and not the way to do things. Classes are not the ultimate solution and it's a good thing that Go tries a different approach to OOP.


Nice logic! Shell is better than CoffeeScript or Go:

    #!/bin/sh
    cat file.txt


I always liked Perl's version:

    perl -e 'while (<>) { print; }' file.txt


I like Perl's other version:

  perl -p file.txt




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: