Hacker News new | past | comments | ask | show | jobs | submit login

Joe Doffy argued, in my view persuasively, that Go missed an crucial opportunity by not requiring that users actually do something with returned error codes.

http://joeduffyblog.com/2016/02/07/the-error-model/#forgetti...

> It’s surprising to me that Go made unused imports an error, and yet missed this far more critical one. So close!

Result/Option/Maybe types force unwrapping, which makes ignored return codes auditable and allows you to manage technical debt.

This doesn't speak to Go's simplicity so much as it does to Go's conservatism. Having the Go standard library use sum types, establishing a precedent and a culture, would be no more complex in the absolute, but would have been more of a stretch for its initial target user base.




> It’s surprising to me that Go made unused imports an error, and yet missed this far more critical one. So close!

The most egregious to me has always been that unused imports are an error but variable shadowing is not.

Even in languages with dynamic side-effecting imports (like Ruby or Python) I've never seen a bug caused by an unused import. Not so for shadowing (don't get me wrong, it's a convenient feature, but if you're going to remove this sort of things because reasons it's a much bigger pitfall than unused imports).


Variable shadowing is actually a pretty clever thing that I'd like to see in other languages.

For example I often write code like this in Java:

    String ageString = request.getParameter("age");
    int ageInt = parseInt(ageString);
because I can't re-use name `age` twice and forced to distinguish between those names.

Now I agree with you about imports. I often want to comment a line and run program. Now I have to comment a line, run a program, encounter compilation error, find import, comment that import, run again. And uncomment two lines later. With Java my IDE optimizes import and removes all unused imports when I'm commiting my code. While I'm working on my code, I'm absolutely fine with any warnings. I would say even more: back then when I used Eclipse, it had awesome ability to compile even code with errors. This code just throws exception on runtime. But if I'm not really interested in that snnippet and working on other part, I can run it just fine. Probably that feature is the only thing that I'm missing from Idea.


> Variable shadowing is actually a pretty clever thing that I'd like to see in other languages.

Shadowing exists in most languages, the biggest difference being the allowed scope relationships between the shadower and the shadowee: most languages allow inter-function and inter-block shadowing (if they have actual block-level scope so e.g. not Python).

Intra-block shadowing is a much rarer feature, and one which Go doesn't have.


I agree with you. And it would even be fine to allow shadowing but require an explicit declaration to allow it to happen in a particular case. e.g.

    import "foo"
    func other() {
        shadow var foo string = "bar";
    }


Or only allow shadowing for `var` and forbid it for `:=`[0]. Though forbidding it entirely would work just as well.

[0] and go is actually weirder than that — and the opposite way 'round — as `var` doesn't allow any shadowing in the same scope:

    var a, b int
    var a, c int // fails because it redeclares a in the same block
while `:=` allows same-scope shadowing as long as the overlap is not complete:

    a, b := foo()
    a, b := foo() // fails because no new variable on the left side
    a, c := foo() // succeeds
both allow arbitrary shadowing in sub-scopes.


There's no shadowing in the latter case. The second case is the same thing as

    a := 2
    a = 3
By definition you must have nested scopes to have shadowing. Within the same scope, it's only ever assignment.


Well, in Rust you could do:

    let a = 2;
    let a = 3;
I think you would say the latter shadows the former...


Indeed, because semantically there is a syntactically implicit scope for every let binding. For example, in that case, the outer a is dropped after the inner a, just as if the second a had been inside of a block. There may be multiple syntactic ways to introduce a new scope.


That last one isn’t shadowing. := reuses a variable of the same name in the same scope.


I'm honestly of the opinion that this shouldn't be allowed either. Accept that you need to name the variable 'fooErr' and just ban all shadowing


I really like this syntax. I wonder if it has ever been proposed for Rust? It should be compatible with the existing semantics and could be phased in and then made mandatory in a new "edition".


It has, but hasn’t gained much traction.

There is already a “let” to show you that a variable is being created, adding more verbosity to a feature that, in some sense, is about removing verbosity kinda misses the point, in my opinion.

That said, never say never, but if I was a betting kind of person, I’d bet against it ever being accepted.


> This doesn't speak to Go's simplicity so much as it does to Go's conservatism.

I think this really hits the nail on the head. There are benefits to a conservative approach, but it's not the same as simplicity.


The errcheck linter is very popular for checking that you looked at every error return: https://github.com/kisielk/errcheck

I use it in most of my open source projects.


An indication that something is missing.


Not necessarily, insofar as “Go where you always use the (result T, err error) return type” is a dialect of Go rather than Go itself.

You could give this dialect a name and then maybe the compiler could enforce rules on projects that declare that they’re using that dialect (like C compilers do with dialects like “c19” vs “gnu99”), but it’s not strictly necessary; you can also just create “dialect tooling” that wraps the language’s tooling and adheres to those rules (like Elixir’s compiler wraps Erlang’s compiler.)

And a CI shell-script, or git pre-commit hook, that runs a linter before/after running the compiler, is an example of just such “wrapped tooling.”




Consider applying for YC's Spring batch! Applications are open till Feb 11.

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

Search: