Live data from Hacker News

Why I’m not leaving Python for Go

uberpython.wordpress.com

241–245 of 245 posts

Re: Why I’m not leaving Python for Go

#241

Earlier quoted context omitted.

Sure, you can handle errors and you can explicitly pass the buck. That's no different than what we do in C. Exceptions are out-of-band (from a regular return value), and what you're talking about is entirely in-band. What you're doing, functionally, is returning a tuple. This is as old as the sun and nothing at all like exceptions. I'm not sure what you think idiom means ( Hello, my name is Inigo Montoya ), but you n…

Idiom just means "a standard way to do things, that everyone recognizes and uses". Normal exceptions, the kind that unroll the stack (and not deep magic like call/cc) are only "out of band" as an optimization. There is no behavioral difference between "save the last place you decided to handle errors, and jump there directly unrolling the stack at once" versus "unroll the stack by a series of buck-passing in band err…

In particular idiom does not mean something deliberately entered into the language to solve a particular problem—that's just regular semantics. Idioms are by nature emergent. For example I might be conscious of 3 idioms among all the languages I know (which is much more than 3), yet I write idiomatic code because I know the languages well. In fact, outside of Go circles no one talks of idioms, they talk of idiomatic code.

Who cares about compiler transformations? The issue is the semantic difference between return codes and exceptions. Nobody is asking for exceptions because they can't or don't know how to get to the correct scope to handle their errors, they're asking for them because they don't want to write all the boilerplate necessary to do so.

And yes, you can transform exceptions to chained returns. That would be a lot of work for terrible performance. You can't do the other transformation though. It would require being able to statically analyze the code path to determine where the errors are eventually handled, which is impossible in the general case.

Re: Why I’m not leaving Python for Go

#242
post #235

Earlier quoted context omitted.

Doing exactly the opposite from what I asked, you omitted all the declarations of all the classes you use. Note that if I use C++ I can also use the classes with the same semantic and that also contain error messages. The stack trace you mention is a debugger feature, not something your classes do by the language definition (I speak about C++, I don't know what's in Java). If you'd include all the code needed for you…

The example code is not using a new exception, it's handling the callee's, the same way that your code does not use a new return code but relies on whatever the callee returns and does not include the code for "callSql". I assume you are right about C++ exceptions (the little C++ I do doesn't use them). Modern managed languages incorporate the stack trace in the exception (including Java). I'm not sure how you propos…

I'm sorry but I firmly believe you completely missed the point. I wrote "If you can, write a more concise code with exceptions which will automatically show you which call failed and what the error was. If we include all the declarations, I claim that your solution wouldn't be shorter or more readable than my C variant I'll write" and you managed to omit everything I proposed as needed in order to demonstrate what is actually involved in exceptions -- not the use, but all the classes etc needed. In short, if you actually use library exceptions, there are thousands of lines of declarations. You can claim "but they are already there, I don't have to write them" still it's a library thing, not the "language as such" thing.

Errors can be handled at different layers (using normal control flow the same way as I already demonstrated -- simply writing ifs) and the error declaration can be checked at compile time in C++ exactly as C++ has (who would have thought that!) classes. Java also uses class infrastructure for that, exceptions are only "out of normal flow path" mechanism.

Re: Why I’m not leaving Python for Go

#243
post #102

Earlier quoted context omitted.

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...

You did not carefully read the GP. IO read/write functions are not limited to the net package. net.Conn supports a subset of these (interface types) and it is entirely idiomatic and possible for a net.Conn flavor to endup at some deep layer of your code in a function accepting generic io in args. Functions taking non-net "in args" returning "error" can not be assumed to always return "net.Error". You will need to tes…

To be clear, the two-valued cast I used in my example never panics. It returns (casted value, true) or (nil, false). No need to write any reflective functions.

As to your example of io.ReadFull: what about it? If it gets an EOF before filling the buffer you passed in, it'll return ErrUnexpectedEOF per the documentation. If it gets any other error, it'll return it instead. I haven't actually looked at the source in a while but that's how almost all of the byte stream functions work.

Re: Why I’m not leaving Python for Go

#244
post #242

Earlier quoted context omitted.

The example code is not using a new exception, it's handling the callee's, the same way that your code does not use a new return code but relies on whatever the callee returns and does not include the code for "callSql". I assume you are right about C++ exceptions (the little C++ I do doesn't use them). Modern managed languages incorporate the stack trace in the exception (including Java). I'm not sure how you propos…

I'm sorry but I firmly believe you completely missed the point. I wrote "If you can, write a more concise code with exceptions which will automatically show you which call failed and what the error was. If we include all the declarations, I claim that your solution wouldn't be shorter or more readable than my C variant I'll write" and you managed to omit everything I proposed as needed in order to demonstrate what is…

Thousands of lines of declarations?

  import com.foo.SomeOtherException;

  public class MyException extends SomeOtherException {
    public MyException(String message) {
      super(message);
    }
  }
That's about as complicated as it gets (considering the example extends a custom exception instead of inheriting from java.lang.Exception). I'll note that your example doesn't declare any return code anywhere. Now, I'm curious to know how you would do the equivalent of this with error codes:

  public class MigrationException extends Exception {
    public MigrationException(String msg) { super(msg); }
  }
  
  public class SqlException extends Exception (
    public SqlException(String msg) { super (msg); }
  }

  public class Migration {
    public void migrate(Statement stat, int migrationNumber)
      throws MigrationException, SqlException{
      if (migrationNumber  5");
      // throws SqlException
      stat.executeNonQuery("INSERT foo INTO bar");
    }
  }

  public class MigrationRunner {
    public void run(Statement stat, Migration migration, int migrationNumber) {
      try {
        migration.migrate(stat, migrationNumber);
      }
      catch(MigrationException ex) {
        migrationLogger.error("Bad migration", ex);
      }
      catch(SqlException ex) {
        migrationLogger.error("DB error", ex);
        sqlLogger.error("Error during migration", ex);
      }
    }
  }
I'm on purpose not reimplementing an SQL driver here :)

I'm not quite sure why you are arguing about "error declarations which can be checked at compile time in C++". Sure, C++ has exceptions, but I thought you were trying to make a point about return codes, not C++ exceptions vs language X exception. My point, on the other hand, is that it's very easy to do this:

  #define SQL_ERROR 1
  // whoops, same error code due to copy-paste
  #define MIGRATION_ERROR 1

  void handleError(int errorCode) {
    // Too bad, this was actually an SQL error
    if (errorCode == MIGRATION_ERROR) {
      ...
    }
    else {
      // We'll never enter this branch
      ...
    }
  }
No compile-time check for that. Or even:

  #define MIGRATION_ERROR 1
  #define SQL_ERROR 2

  void handleError(int errorCode) {
    // I actually meant 2 here
    if (errorCode == 1) {
      logSqlError();
    }
  }

Re: Why I’m not leaving Python for Go

#245
post #227

Earlier quoted context omitted.

When I just do a simple hello world app, I get this error ghc helloworld.hs -o helloworld ./helloworld ./helloworld: error while loading shared libraries: libgmp.so.10: cannot open shared object file: No such file or directory However if I compile statically, I get a different error ghc helloworld.hs --make -optc-static -optl-static -optl-pthread -static -o helloworld ./helloworld FATAL: kernel too old Segmentation f…

How old is your kernel, anyway?

Running 2.6 I believe, but these servers are not managed by me, they're owned and administered by my workplace, so I don't have any say on upgrades etc
Post reply on HN