News for hackers. Stuff that matters.
Re:Golang landmines by Animats on Sunday September 18, 2016 @01:34AM (#12524064)
Languages probably shouldn't allow shadowing, certainly not within a single module. Think of the maintenance programmers.

"Defer" was probably a bad idea. It's a run-time construct - you're adding to a to-do list run at the end of the function. It's not scope oriented. Something like Python's "with" clause would have been both simpler and more useful. "with" calls "_enter" on an object when you enter a scope, and "_exit" when you leave, no matter how you leave. All the file-like and lock-like objects support "with". Python's "with" even supports exceptions properly - if you're handling an exception when "_exit" is called, the "_exit" function gets told about the exception, so it can clean up and then re-raise the exception. If an "_exit" itself needs to raise an exception, that works, too.

"Defer" is blind. With "defer", nobody ever finds out that the close failed to write the end of the file.

Re:Golang landmines by donatj on Sunday September 18, 2016 @05:48AM (#12524635)
> "Defer" is blind. With "defer", nobody ever finds out that the close failed to write the end of the file.

This is simply false and a misconception held by people who haven't spent a lot of time with the language. You not only can, but absolutely SHOULD handle errors in defers.

Using named return parameters on your method, your error return is still in scope and can be set. This is how you properly handle errors on defers.

See: https://play.golang.org/p/kPx3ipkMhF

Re:Golang landmines by pcwalton on Sunday September 18, 2016 @12:41PM (#12525943)
> This is simply false and a misconception held by people who haven't spent a lot of time with the language.

If you've spent a lot of time with the language, then you've surely noticed that people rarely do this (because it's extremely verbose). The language encourages ignoring errors in defer.

(Contrary to the parent post, I'm not sure this is a real problem, however.)

Re:Golang landmines by Animats on Sunday September 18, 2016 @06:12PM (#12527468)
That is so cool. And confusing. And likely to lead to errors.

Error handling should not require l33t features. (This is my big argument with both Go and Rust. The stuff they use to get around not having exceptions is worse than exceptions.)

Re:Golang landmines by donatj on Monday September 19, 2016 @03:46PM (#12534145)
I wouldn't really call "return values" a "l33t feature".

Exceptions are absolutely a "l33t feature". They break whatever is currently happening. They are an uncontrolled return working its way up your structure.

While you're attempting to recover from that Exception I gracefully catch my error and can even use the multiple return values that came back successfully from my function, despite there being an error.

Re:Golang landmines by kibwen on Monday September 19, 2016 @02:23AM (#12529372)
As though exceptions themselves are somehow not a "l33t feature". :P
Re:Golang landmines by themihai on Monday September 26, 2016 @02:13PM (#12584193)
That's right but you are not returning the error. Here is the corrected snippet https://play.golang.org/p/A3YRSTg-7K

Edit: your example works too, though I find it weird...

Re:Golang landmines by smarterclayton on Sunday September 18, 2016 @01:47AM (#12524100)
To be fair I think most Go programmers are exposed to defer .Close() on files via example, and it's possible every copied example can be traced back to some proto-example in the very early days of Go. It is extremely pernicious in the ecosystem - Docker, Kubernetes, and etcd all had rounds of cleaning it up over the last year or two. I would expect linters to flag Close without checking the error value (if they don't already).
Re:Golang landmines by Animats on Sunday September 18, 2016 @02:13AM (#12524168)
What can you do if you detect an error in a "defer" clause? Besides panic?
Re:Golang landmines by amscanne on Sunday September 18, 2016 @03:58AM (#12524366)
With named return values, the defer can modify them. For example:

func Foo() (err error) { defer func() { err = errors.New("some error") }() }

The function will return the "some error" error.

Re:Golang landmines by ansible on Sunday September 18, 2016 @02:54AM (#12524251)
Well, I don't know if panic is the right option.

However, checking the return value is always a good idea, and any errors should at least be logged.

I too wish it was less cumbersome to use defer properly.

Re:Golang landmines by giovannibajo1 on Sunday September 18, 2016 @03:07AM (#12524285)
One thing you can do is simply use BOTH a defer Close and a straight-path Close with error-checking.
Re:Golang landmines by catnaroek on Sunday September 18, 2016 @05:01AM (#12524505)
The problem isn't shadowing. The problem is capturing by reference. It's utterly confusing, because it means that all closures that you create in the same environment share the same mutable state - delicious action at a distance!

Languages where closures capture by value (ML, Haskell) or where the programmer explicitly chooses between capturing by value and by reference (C++, Rust) are free of these complications.

Re:Golang landmines by eternalban on Sunday September 18, 2016 @12:19PM (#12525848)
That terminal '}()' is there for a reason.

https://play.golang.org/p/zyMbmJsnUz // minor mod of donatj's example.

Re:Golang landmines by catnaroek on Sunday September 18, 2016 @01:35PM (#12526185)
This is reminiscent of the common Python hack `lambda n=n: whatever`. Well, it's a hack.
Re:Golang landmines by Peaker on Sunday September 18, 2016 @03:33PM (#12526774)
Haskell doesn't necessarily capture by value or by reference since you cannot distinguish between the two when all values are immutable.
Re:Golang landmines by catnaroek on Sunday September 18, 2016 @03:36PM (#12526786)
When I say ”by value”, I mean the abstraction the programmer is exposed to, not the internal implementation detail. In a Haskell implementation, the environment may well be internally represented as a pointer, but the programmer doesn't need to worry about that. On the other hand, a Go, Python or Lisp programmer is constantly and painfully reminded of the difference between copying an object and pointing to a pre-existing object.
Re:Golang landmines by Peaker on Sunday September 18, 2016 @03:47PM (#12526845)
Haskell programmers do have to think about it as being by-reference if they want to understand the performance/memory-use due to sharing.

But for correctness, yeah, you just don't have to think about it. So you don't think "by value" or "by reference", it just becomes something obvious that you don't need to think about.

Re:Golang landmines by catnaroek on Sunday September 18, 2016 @03:49PM (#12526856)
> Haskell programmers do have to think about it as being by-reference if they want to understand the performance/memory-use due to sharing.

Oh, right.

Re:Golang landmines by continuational on Sunday September 18, 2016 @10:40AM (#12525478)
No need to build this into a language. It can be provided as a simple library function:

    with<T>(resource : T, body : T => Void) where T <: Resource

    with(file, f => { ... })
Re:Golang landmines by Animats on Sunday September 18, 2016 @06:11PM (#12527465)
Adding control semantics via library extensions seems to be a thing now. It has a bad history, though, from the extensible languages of the 1970s, when people first discovered that you could do fancy things with macros. That didn't end well.

You don't need many control constructs, and the list is pretty well known, so you may as well design them into the language.

Re:Golang landmines by pjmlp on Sunday September 18, 2016 @12:23PM (#12525859)
Which is yet another reason for a modern language to handle generics.