Live data from Hacker News

Why I’m not leaving Python for Go

uberpython.wordpress.com

101–110 of 245 posts

Re: Why I’m not leaving Python for Go

#101
post #50

Earlier quoted context omitted.

I guess you are super lucky: https://developers.google.com/appengine/docs/go/datastore/re... or even https://developers.google.com/appengine/docs/go/datastore/re... err := datastore.Get(c, key, record) if err == ErrNoSuchEntity { // entity not found return } else if err != nil { // some other error return } Don't really see the hassle you are referring to.

I think this is exactly the point. You have to read the comment to get the error types (isn't compiler accessible), it doesn't list what all the possible error types are (doesn't say the ones documented are exhaustive), and the code returns a singleton error (no state) presumably so the caller doesn't have to do a bunch of casts..

> You have to read the comment to get the error types (isn't compiler accessible), it doesn't list what all the possible error types are (doesn't say the ones documented are exhaustive)

You're absolutely right. People should be able to use libraries without reading their documentation, and instead rely on compile failures to slowly iterate their code towards perfection. /s

Seriously, though, I believe expecting programmers to read documentation of a library they're using is a pretty low bar.

Also, no it doesn't list what all the possible error types are. To do this would require what amounts to checked exceptions in Java. The issues with these are relatively well known.

First, it complicates versioning as adding a new error type is a breaking change for all clients. When they get an error from an API, most clients either return that error verbatim, decorate that error slightly and return the decorated error, or handle a few specific error situations and return an error in all other cases. Declaring all possible error types makes your programs brittle, as it is easy for libraries you are using to break your code.

Second, they are a hassle for larger programs that touch many systems. It is easy to declare that you return an EntityNotFound error. But it is not so easy to declare that you return an EntityNotFound, MemcacheCASConflict, FileNotFound, FileExists, PermissionDenied, Timeout, InvalidJSON, ConnectionClosed, or TemplateRenderingFailed error. This is perfectly reasonable set of errors for a simple method that gets a value from datastore (possible caching it) decoding a field as json, and writing a template to an HTTP connection. Any 'simple' wrapper of this method then inherits all of these declarations. Now certainly with Java, IDEs will "fill in all the forms" for you, so this problem is a little more palatable, but Go does not require programmers to use (often heavyweight) tools to make them productive.

> code returns a singleton error (no state) presumably so the caller doesn't have to do a bunch of casts

This is a little disingenuous, as you don't really know why they made it a singleton error. I can't think of any state that would be useful in this situation, can you?

The Java version of this API throws an exception with a single field, the Key that could not be found. I think this is supremely unhelpful and just adds clutter to the documentation, as the user of this method clearly already has this information in hand.

Re: Why I’m not leaving Python for Go

#102
post #66

Earlier quoted context omitted.

I respectfully disagree. You almost never cast the error. Two approaches are common in the go community. 1. Error constants. These you can use == or a switch statement to do control flow with. 2. Custom Error Types. These you typically use a type switch which uses reflection to do dispatch off. In this case you might also then cast it if you need specific data off of the error but most of the time you don't need any…

I respectfully disagree: http://golang.org/src/pkg/net/timeout_test.go#L39 edit: You should note that the above test code is actually far less verbose than the analogous end-user code, given that the timeout_test.go clearly expects the 'err' var to be a net.Error. Now consider the case of a network subsystem, with funcs having in args of type 'bufio.Reader' and/or 'bufio.Writer'. At some prior point you may have set…

Not sure what buffer overruns you are referring to, or why this case requires reflection at all.

  err := readMessage(reader)
  if n, ok := err.(net.Error); ok && n.Timeout() {
      // handle timeout
  } else if err != nil {
      // handle other errors
  }
You can see an example of exactly this pattern here: http://golang.org/src/pkg/net/http/server.go?s=29962:30008#L...

Re: Why I’m not leaving Python for Go

#103
post #68
post #53

Earlier quoted context omitted.

I would guess that most (99%) of C programmers are lazy or has an rapid programming style then. Its a rare thing to see C source code that even do the simple thing like wrapping every write/read/print call with a loop that detects eintr. In my years of programming, I have yet to stumble on a other programer who even knows that one should be doing this. Looking at c libraries and their example code, almost every time,…

That's true but also C's error reporting differs greatly between libraries. Each library has a learning curve in how it wants it's errors checked. From the top of my head, 10 years after writing any C code there is check against NULL - guess the error, check against minus values - lookup minus values in a table, check against 0 - call method to get error string and many more. Go standardises this in a super clean way…

I don't doubt that Go is usable and reflects an attempt to rationalize C's (non) conventions, which is a goal I appreciate. but it certainly isn't false for Python that 'the result - as anyone who has been writing [Python] for a few months can tell you - is something that works incredibly well.'

Re: Why I’m not leaving Python for Go

#104

If you use a language that uses error codes, then you're forced to explicitly think about what to do in every single error case (or not, and accept the consequences). This can add a lot of mental overhead, but can result in a much more robust and well-thought-out program. But because more logic is involved period (to handle the robustness), the program is necessarily more complex. If you use exception handling, then…

I basically agree with you. I think return codes are simpler, and exceptions appear simpler because we're used to them. In reality they are a magical, out-of-band mechanism compared to plain old return. I contend that local and explicit is more strongly correlated with simplicity than remote and implicit. Put another way, verbose code can be simpler if it is direct and explicit — what happens is what's on the page —…

I used return codes before I ever used exceptions, and even chafed at exceptions. Exceptions CAN be simpler. It's just an expressive tool, it matters more what you do with it.

I do hate to read code which uses exceptions as a normal part of program flow, it's very GOTO-like and remote and implicit.

But I don't write code that way and nothing is forcing me to write code that way. When exceptions are reserved for really exceptional conditions where a requested performance CANNOT continue, they are used much less frequently, and more locally and explicitly.

In short I think the problem is a matter of philosophy more than language facilities, and the big differences are within-language rather than between-language.

The reason I like to have exceptions used as a convention is that I think a better default for programs which have not yet covered some corner case is for them to decline to run, rather than to run in dishonor.

Re: Why I’m not leaving Python for Go

#105
post #29

I'm not in love with this aspect of Go either, and I also find that the idiom for dealing with it (multiple return values and multi-statement if conditional clauses) doesn't play well with Go's scoping rules, so that I find myself regularly having to decide between cleaner conditional or an explicit variable declaration. I also don't love how it makes my code look like my teenage-years C code. But I also think this i…

No other approach to error handling is less fraught.

CL's condition system is less fraught: http://www.gigamonkeys.com/book/beyond-exception-handling-co...

Re: Why I’m not leaving Python for Go

#106

If you use a language that uses error codes, then you're forced to explicitly think about what to do in every single error case (or not, and accept the consequences). This can add a lot of mental overhead, but can result in a much more robust and well-thought-out program. But because more logic is involved period (to handle the robustness), the program is necessarily more complex. If you use exception handling, then…

The difference for me is whether I'm trying to reduce MTBF (mean time between failures) or MTTR (mean time to recovery).

I'm in the first mode when I'm writing high-quality code to solve stable, well-understood problems.

I'm in the latter when I'm doing almost anything else. E.g., prototyping, exploring, pushing out a MVP for user testing, adding a quick-and-dirty version of a feature to get real-world feedback.

In the latter mode, I'm very tolerant of errors just as long as I can diagnose the problem quickly. The way I start is to catch exceptions at a very high level, tell the user something nice, and have myself paged. If something blows up, I fix it quickly. There's no sense in making code robust if I don't know if it will exist next week.

Basically, the two approaches are the same only if you have infinite time and money. Google does, so I guess Go makes sense for them. But if this fellow's take is correct, Go's much less interesting to me as a general-purpose language.

Re: Why I’m not leaving Python for Go

#107
post #105
post #29

I'm not in love with this aspect of Go either, and I also find that the idiom for dealing with it (multiple return values and multi-statement if conditional clauses) doesn't play well with Go's scoping rules, so that I find myself regularly having to decide between cleaner conditional or an explicit variable declaration. I also don't love how it makes my code look like my teenage-years C code. But I also think this i…

No other approach to error handling is less fraught. CL's condition system is less fraught: http://www.gigamonkeys.com/book/beyond-exception-handling-co...

Do you mean that restarts help the clutter and distraction that error handling brings? Or is there something else that makes the condition system less fraught than exceptions?

Re: Why I’m not leaving Python for Go

#108

Earlier quoted context omitted.

http://www.gigamonkeys.com/book/beyond-exception-handling-co... Think exceptions, but instead of blowing away the stack on the way up to your exception handler, it gives you the option of resuming execution in some way where you left off. It also lets you encapsulate error handling better.

I am glad to see some CL condition system pop up here. This article basically turned me off from Go and reading peoples support for C style error handling has made me question what the heck they are thinking. There are actually several nice things about the CL system, but nothing there is going to convince someone that actually thinks not only that having every return value in your language serve the role of an error…

Instead of insulting people and declaring that you can't convince them, try posting some useful information about CL condition system and why you think it's better than everything else.

Re: Why I’m not leaving Python for Go

#109
post #71

Exceptions are like garbage collection. Garbage collection relieves you from the drudgery, accounting and bureaucracy of manual memory management and indirectly leads to more expressive forms of programming once function boundaries are freed from having to specify who owns the data being passed back and forth. But you still need to be aware of space vs time usage, you still need to know where memory is being allocate…

>In the hands of someone who knows what's going on, programs get much simpler I never really got this argument. With RAII types that have value semantics (ala shared_ptr) what is so difficult about memory management in C++? I guess there are reference cycles, but weak_ptr can help there. Manual ref-counting (like a COM AddRef/Release pattern) can be tricky, but that is where attention to detail, code reviews and basi…

> With RAII types that have value semantics (ala shared_ptr) what is so difficult about memory management in C++?

For me, C++ memory management becomes challenging in the face of concurrency. Particularly when you write applications that are event-driven, instead of thread-based, and you've surrendered to an event loop. It becomes challenging to keep track of object lifetimes.

Just my 2c.

Post reply on HN