Live data from Hacker News

Why I’m not leaving Python for Go

uberpython.wordpress.com

201–210 of 245 posts

Re: Why I’m not leaving Python for Go

#201
post #181
post #80

As usual in these threads about Go, I really wish people would consider Haskell as a nice alternative. A lot of people write Haskell off as "academic" or "impractical", which I feel is not an entirely fair assessment. Particularly: Haskell is fast, concurrent by design (whatever that means, I'm sure Haskell is :P), typed but not cumbersome or ugly (less cumbersome and ugly than Go's types, even) and--most importantly…

> As usual in these threads about Go, I really wish people would consider Haskell as a nice alternative. A lot of people write Haskell off as "academic" or "impractical", which I feel is not an entirely fair assessment. As someone with 10+ years of programming experience in the industry but no formal college education, I see the problem with Haskell (and other, similar functional programming languages) that in order…

That's true, and there's no shame in not knowing a language yet, but I'd still recommend you check it out. It's almost like relearning CS.

Re: Why I’m not leaving Python for Go

#202
post #197

Earlier quoted context omitted.

There's also the option of doing it on an explicitly tagged union, Erlang-style: `something` returns not `Value` or `Either(Error, Value)` but `{ok, Value} | {error, Reason}`. This means you can handle the error: case something() of {ok, Value} -> %%; {error, Reason} -> %% end or you can "ignore" it {ok, Value} = something() but (and this is important) the latter *will not pass silently if `something()` returns an er…

That's just a slightly different syntax for Either as far as I can see.

It's similar but without type system support, in Erlang's case because the language is dynamically typed.

So the union is implemented via a tuple field rather than the type system.

Re: Why I’m not leaving Python for Go

#203

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 t…

That's an interesting idea: to only catch exceptions at a very high level (for fast prototyping). I tried it out with this test program:

http://pastie.org/4791686

Though it works, one potential issue I found with it is that it does not give enough context as to where in the program the exception occurred. E.g. if I have more than one open() call (all for read mode) in the code, it will give the same error message for an exception occurring on any of those open() calls (as long as the exceptions all happen for the same underlying reason, such as "file not found". E.g.:

Exception occurred: IOError(2, 'No such file or directory')

Had you come across this and found any way to handle it? I though of passing some unique code for each case, but there seems to be no way to do it, because we are not calling the except clause ourselves - Python does it.

Edit: just thought of a (crude) way to handle that issue: declare a global variable, say, "location", and set it to a different numeric or string value at each place in the code where an exception may be thrown, or at least at one place, say the top of the function, in each function or method. And then in the single except clause, print the value:

print "location=", location

This will at least help narrow down the area of code in which the exception was thrown.

Re: Why I’m not leaving Python for Go

#204
post #80

As usual in these threads about Go, I really wish people would consider Haskell as a nice alternative. A lot of people write Haskell off as "academic" or "impractical", which I feel is not an entirely fair assessment. Particularly: Haskell is fast, concurrent by design (whatever that means, I'm sure Haskell is :P), typed but not cumbersome or ugly (less cumbersome and ugly than Go's types, even) and--most importantly…

"So you can actually just write code like this: do val1 I have seen this (the error monad) mentioned before as a "nice" way of handling errors, even with explicit error returns. I beg to differ - the error messages produced by such a program will be obscure, as all the context is lost - if the first call to someFunction fails, for example, there's not necessarily any indication that the error came from that call rath…

In theory the lack of context problem only happens if you use Maybe's Nothing to signal errors. Something else such as Either should allow you to include extra data on the error case.

As for the error collecting bit I think Haskell can do that as well. Errors are just regular values in Haskell and its just a matter of not using do notation or using a diferent error monad if you want to create a list of errors instead of getting out when the first one occurs.

Ill have to agree with you on the control-flow at a glance issue though. This gets really tricky in Haskell, especially when you take lazy evaluation into account.

Re: Why I’m not leaving Python for Go

#205
post #187

Earlier quoted context omitted.

So the haskell RTS requires the same version of glibc on both machines to make it work? This wouldn't be too much of a problem but I don't have administrative privileges to these servers. So when I want to write throwaway scripts or programs, I find myself turning to Go or D and they work without any quibbles.

Nope. In theory you'd have exactly the same problem with any statically-linked binaries compiled on that machine and run on that server, regardless of what language they're written in. glibc has a minimum kernel version requirement and the glibc you're statically linking against just plain isn't compatible with the kernel on the machine you're running it on. Dynamically linking to a newer glibc and running against an…

I don't believe Go's GC suite of compilers use glibc at all, for the record.

Re: Why I’m not leaving Python for Go

#206
post #189

Earlier quoted context omitted.

> given that it can be implemented pretty much like this in Ruby, and "(begin) .. ensure .." is pretty much equivalent to "try ... finally ..": Note that there's a difference in the handling of exceptions: if an exception is triggered from the `with` block, it is intercepted, provided to __exit__ and can be silenced if needed or desired (by returning a truthy value). So a closer approximation would be: def with r r._…

Ah. Wasn't aware of the ability to silence the Exceptions. Thanks.

Yeah, I don't expect it would be very useful in Ruby, but it's not uncommon for Python (and its users) to use exceptions for flow control (see GeneratorExit and StopIteration)

Re: Why I’m not leaving Python for Go

#207
post #154
post #151

Earlier quoted context omitted.

So, I rarely see eg Java code that actually handles the exceptions it receives. Usually its just "Oh, I got an exception, so I'll print an error (or silently fail) and blindly keep going". Given this, I don't see how Go is any worse with respect to sloppy programmers. They'll Always Find A Way. Also, why couldn't your second example be nested? It seems like either of those two examples could be structured identically…

I find Java exceptions quite good for cases where you want to fail at a much coarser level than the specific problem, but finer than the whole program. E.g. my previous^2 job was essentially a message-processing system; it had a bunch of loops that took messages off queues and processed them one at a time. If processing any given message threw an (uncaught) exception, it marked that message for retry or as failed and…

> You could certainly argue for handling each message in a separate process a la erlang, but this approach worked well for us.

I'm pretty sure you wouldn't do that. You'd have a shallow tree of processes, each leaf process would be tasked with doing message processing e.g. provided by its supervisor. The supervisor would "manage the queue" so to speak, and depending on the semantics of the queue it would have 1 to n children; and it would be tasked with marking failed messages when a child process would blow up (and restarting a new child).

Modelling messages as processes would likely be impractical.

Re: Why I’m not leaving Python for Go

#208

I'll agree that this is perhaps the single thing that I don't like about Go. Now, you can argue it helps with "explicit error handling" and all that, but in that case you might as well have must-be-caught exceptions. Anyone want to fork Go?

"in that case you might as well have must-be-caught exceptions" Errors aren't the same things as exceptions.

Exceptions are a way of handling error conditions.

Re: Why I’m not leaving Python for Go

#209

Earlier quoted context omitted.

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 t…

That's an interesting idea: to only catch exceptions at a very high level (for fast prototyping). I tried it out with this test program: http://pastie.org/4791686 Though it works, one potential issue I found with it is that it does not give enough context as to where in the program the exception occurred. E.g. if I have more than one open() call (all for read mode) in the code, it will give the same error message for…

Huh? Most languages with exceptions provide stack traces, so you can find which function (and line) caused the exception and also what functions were called up to the function that caused the exception. This makes it pretty easy to find out which call to open() caused the exception.

Re: Why I’m not leaving Python for Go

#210

Earlier quoted context omitted.

That's an interesting idea: to only catch exceptions at a very high level (for fast prototyping). I tried it out with this test program: http://pastie.org/4791686 Though it works, one potential issue I found with it is that it does not give enough context as to where in the program the exception occurred. E.g. if I have more than one open() call (all for read mode) in the code, it will give the same error message for…

Huh? Most languages with exceptions provide stack traces, so you can find which function (and line) caused the exception and also what functions were called up to the function that caused the exception. This makes it pretty easy to find out which call to open() caused the exception.

Heck, I commented in a hurry without thinking :( I did know about stack traces (used so many times), and you're right, of course. Thanks for pointing it out, though :). Now that I think of it more, since stack traces exist, there isn't even a need for that top-level try/except, for early prototypes. You can just write your main code, run it and let it fail, and fix the errors as you find them, by using try/except/finally etc.
Post reply on HN