So I tried Go the other day


  • Banned

    @JBert said in So I tried Go the other day:

    @Gąska said in So I tried Go the other day:

    either due to incompetence or just laziness; alternatively, corporate overloads not allowing enough man hours to be spent on proper design - either way, Java sucks

    It's a combination of things, but don't forget to also add "design by committee". There are at least 3 big JVM vendors which thus have to vet bytecode changes, similarly there are a few compiler vendors.

    There's Oracle's HotSpot, there's Oracle's OpenJDK... and what's the third?


  • Fake News

    @Gąska Hotspot and OpenJDK is pretty much the same. I was thinking of BEA JRockit but they got bought by Oracle, which leaves IBM J9 that they gave to the Eclipse community as OpenJ9.

    I'm sure the committee still exists though, and Wikipedia keeps a list of Java Virtual Machine implementations.


  • ♿ (Parody)

    @Kian said in So I tried Go the other day:

    So what is the point of checked exceptions? To ask the caller to please take care of that error? A function should declare what it needs to work, and the result of the work it does. It shouldn't mandate how the caller reacts to the result, because it creates a stronger binding between the caller and callee than there needs to be. If I don't handle the checked exception, then I have to pass it along to my parent, and they to theirs, and so on, and now my caller's implementation for some reason depends on who I call.

    It already depended on that. I used to be lazy and didn't like checked exceptions. I've totally changed my mind. The analogy to static typing made earlier is excellent.


  • ♿ (Parody)

    @pie_flavor said in So I tried Go the other day:

    iterable that isn't a collection

    Nope thread is :arrows:


  • Banned

    @boomzilla you don't like generators?


  • ♿ (Parody)

    @Gąska said in So I tried Go the other day:

    @boomzilla you don't like generators?

    Never used them in java.



  • @Gąska said in So I tried Go the other day:

    @JBert said in So I tried Go the other day:

    @Gąska said in So I tried Go the other day:

    either due to incompetence or just laziness; alternatively, corporate overloads not allowing enough man hours to be spent on proper design - either way, Java sucks

    It's a combination of things, but don't forget to also add "design by committee". There are at least 3 big JVM vendors which thus have to vet bytecode changes, similarly there are a few compiler vendors.

    There's Oracle's HotSpot, there's Oracle's OpenJDK... and what's the third?

    JVM.go :trollface:
    In all seriousness though, it seems that the JVMs I've had any contact with apart from the Sun/Oracle one is now no longer active. Not that strange, considering that Oracle gave a solid boot in the rump of the Java development efforts, and got things moving, making all the alternative implementations largely unnecessary.



  • @boomzilla said in So I tried Go the other day:

    I used to be lazy ... I've totally changed my mind.

    But :kneeling_warthog: ❗


  • Discourse touched me in a no-no place

    @Carnage said in So I tried Go the other day:

    In all seriousness though, it seems that the JVMs I've had any contact with apart from the Sun/Oracle one is now no longer active.

    Well, that's also basically the OpenJDK one. The Oracle one has some extra pieces that they didn't make open (advanced service debugging tools?) but most code should be just fine with OpenJDK, especially if not deployed in very high load environments.


  • area_can

    Thread summary: Go sucks because Java has checked exceptions


  • Considered Harmful


  • Considered Harmful

    @pie_flavor said in So I tried Go the other day:

    @Gąska Yeah, we'll just say new ThrowingStream



  • @dkf said in So I tried Go the other day:

    @ben_lubar said in So I tried Go the other day:

    @dkf said in So I tried Go the other day:

    @ben_lubar Looking at all that reinventing of exceptions and try…finally is painful.

    finally already exists in the form of defer someFunction().

    I didn't grasp what the nature of the conditions under which a deferred callback is run really is. Is it scoped to anything less than a function? Can it be cancelled?

    Use case: I'm trying to think how a database transaction would be handled; mechanisms to scope those to a particular section of code with success-exits committing the transaction and erroring-exits automatically triggering rolling back are superb for ensuring that data access semantics are correct, and are hugely simpler than doing it by hand. In truly sensible languages, I can do this by just giving a block to something (that depends on the language) that says “I'm scoping a transaction to this block”, and you can simulate it with various techniques in other languages (I've got utility code for Java that makes this fairly easy even without a framework like Spring; there's still little syntactic overhead). The more code it takes at each use, the more likely programmers will get this wrong.

    defer tx.Rollback() will just produce an error (which is ignored) if the transaction was already committed or rolled back if you're using the Go standard library SQL API.

    If you want to scope to a block within a function, you can use the equivalent of everyone's favorite JavaScript syntax:

    func() {
         defer something()
    
         stuff()
    }()
    

    Alternatively, you can just split out that part into its own function, which is usually the best plan for anything that opens files in a loop as calling defer file.Close() within that loop will call all the Close methods when the function is exiting (and also keep the file objects from being garbage collected, so it's double-not-what-you-want)



  • @Zecc said in So I tried Go the other day:

    @cartman82 said in So I tried Go the other day:

    In the new code-base, I use Promises. And I am NEVER going back.

    Promise?

    What took hours of careful orchestration and error juggling is effortless with promises.

    I wish you good luck with stack traces and never forgetting .catchs and returns.

    Stack traces for promises in JS are way better than the callback hell stack traces that usually don't even contain what you want to know.


  • Discourse touched me in a no-no place

    @ben_lubar said in So I tried Go the other day:

    defer tx.Rollback() will just produce an error (which is ignored) if the transaction was already committed or rolled back if you're using the Go standard library SQL API.

    Ah yes, the Ignore That Error Behind The Curtain “pattern”. It's bad with exceptions, and it is bad here too.



  • @dkf said in So I tried Go the other day:

    @ben_lubar said in So I tried Go the other day:

    defer tx.Rollback() will just produce an error (which is ignored) if the transaction was already committed or rolled back if you're using the Go standard library SQL API.

    Ah yes, the Ignore That Error Behind The Curtain “pattern”. It's bad with exceptions, and it is bad here too.

    The only cases you'd be exiting the function would be one of:

    1. you committed the transaction
    2. you rolled back the transaction
    3. an error occurred

    In zero of these cases the result of calling Rollback (a second time) would be useful.


  • 🚽 Regular

    @Zecc said in So I tried Go the other day:

    I wish you good luck with stack traces and never forgetting .catchs and returns.

    So I tried Flutter the other day.

    Paying for my big mouth I didn't think to add a .catchError to the returned promise of a very simple placeholder method, which was basically:

    Future<void>  _open() async{
        _things.add(Thing(present: true, code: 'Present', name: 'Present thing'));
        _things.add(Thing(present: false, code: 'Absent', name: 'Absent thing'));
        _things.add(Thing(present: true, code: 'Placeholder', name: 'Don\'t mind me'));
    }
    

    For whatever reason the equivalent of a null reference exception (forgot to set _things to an empty list first) did not surface. I had to go around digging to find out why a then callback wasn't being called.

    I hadn't set a .catchError anywhere. Apparently Dart's or Flutter's default behaviour is to just silently swallow exceptions. 💢 This isn't completely true. I've had a couple of red screens when exceptions were thrown. What I meant was promises do not rethrow exceptions when they are missing a catch callback.



  • @dkf The idea that you should handle all errors in your code is complete nonsense. You should handle "recoverable" errors, like failing to connect to the server or configuration files not being there (probably because it's the first launch).

    But for any real errors, like a basic system call not returning what it should return or a necessary program file not being there, the only thing you can do is save the details somewhere for debugging, show a "oh no something went wrong :(((((" to the user and exit. And that's precisely what exceptions do!


  • Banned

    @anonymous234 said in So I tried Go the other day:

    @dkf The idea that you should handle all errors in your code is complete nonsense.

    It is. That's why no one was proposing it.

    You should handle "recoverable" errors, like failing to connect to the server or configuration files not being there (probably because it's the first launch).

    You shouldn't recover from most "recoverable" errors either, most of the time. But there are times when you have, and it's absolutely critical for libraries to allow recovering from all recoverable errors when you need to do so. And unchecked exceptions make it very hard to do, because (1) you don't actually know what kinds of exceptions a given function might throw - in particular, you can never say with absolute certainty about any function that it will never throw; and (2) in most languages in unchecked exception, it's impossible to tell if the exception is from recoverable or unrecoverable error, and you're forced to either treat unrecoverable errors as recoverable, or recoverable errors as unrecoverable. And people do both all the time, and it sucks.


  • Discourse touched me in a no-no place

    @Gąska said in So I tried Go the other day:

    You shouldn't recover from most "recoverable" errors either, most of the time.

    That really depends on the application, and what “recover” means to you. For example, I'd definitely like web services to not crash the service process when an error occurs due to something in the user's request. Or at all really.



  • @Gąska said in So I tried Go the other day:

    That's why no one was proposing it.

    Yet C and, as I understand, Go, require me to check the return values of all functions I call just to exit if something goes wrong, because exceptions bad. Which is unnecessary extra work.


  • Considered Harmful

    @anonymous234 Precisely. Go did the Rust thing but forgot to make it usable.


  • Banned

    @dkf said in So I tried Go the other day:

    @Gąska said in So I tried Go the other day:

    You shouldn't recover from most "recoverable" errors either, most of the time.

    That really depends on the application, and what “recover” means to you.

    Yes it does. And it just so happens that in most applications, most of the time, crashing to desktop (or a generic "something went wrong" error handler that leaves you at main screen and destroys all work since you last clicked "save") is perfectly acceptable for almost every kind of error.

    But if you can't do that (and there's plenty of cases when you can't do that, like your service process example), then it becomes critical to know literally every possible error that might ever happen in your program, and then you see the benefit of checked exceptions.

    @anonymous234 said in So I tried Go the other day:

    @Gąska said in So I tried Go the other day:

    That's why no one was proposing it.

    Yet C

    Nope - you can ignore all C errors just fine. It's actually the default. In fact, you must really go far out of your way to do even basic error handling. This is the main problem with C - that ignoring errors is way too easy.

    and, as I understand, Go, require me to check the return values of all functions I call just to exit if something goes wrong

    I meant, no one in this topic. I thought it was common knowledge by now that Go designer are retarded fuckheads who know nothing about programming, and nothing they say or do should be taken seriously.

    because exceptions bad.

    This has nothing to do with exceptions. You could have the same fucked up design with exceptions. You could have no exceptions and still let the user ignore all errors most of the time. In fact, Rust does exactly that - you just slap ? after function call and it automatically does the check-error-and-return-if-there's-one (assuming your function has appropriate return type), so you don't have to worry about it yourself. Then the rest of the function can pretend that the error never happened and couldn't possibly happen. And when you need to handle the error, you just don't use ? and do regular if/else or whatever.


  • Discourse touched me in a no-no place

    @Gąska said in So I tried Go the other day:

    In fact, Rust does exactly that - you just slap ? after function call and it automatically does the check-error-and-return-if-there's-one (assuming your function has appropriate return type), so you don't have to worry about it yourself. Then the rest of the function can pretend that the error never happened and couldn't possibly happen. And when you need to handle the error, you just don't use ? and do regular if/else or whatever.

    If they had swapped the syntax so that the “let the error bubble on out” was the default and you required extra stuff to say when you wanted to trap it, you'd end up with (close to) what exceptions look like. The key is that you want to make doing the right thing be the most syntactically minimal one so that programmers' natural laziness works in their own favour most of the time.

    Implementation strategies for exceptions are a whole 'nother thing. And quite varied too.


  • Banned

    @dkf what you said is particularly interesting in context of Rust, because errors are done through a generic Result<T, E> type, which isn't magical in any way - it's just regular tagged union with values Ok(T) and Err(E). You could've written it yourself and have identical effect. And until you use ?, it behaves exactly like all other types - you can have a function taking Result as argument, you can make a vector of Results, and so on. And ? itself can be implemented for any type you want by implementing its associated magic trait, just like you do with all other operators. If they somehow found a way to make the errors bubble up automatically, the result would be a much, much, much more complex language, with a whole lot more of special cases and magical stdlib types impossible to reimplement in user code.


  • Discourse touched me in a no-no place

    @Gąska I understand what you're saying, but error handling is the kind of thing where getting it right is absolutely essential so compromising purity may be required. Also, you end up with special cases anyway as you need to integrate error handling with the interface to the OS — (almost?) every system call can fail — and that's something you only really want to write at most once per language…



  • @Gąska said in So I tried Go the other day:

    And unchecked exceptions make it very hard to do, because (1) you don't actually know what kinds of exceptions a given function might throw - in particular, you can never say with absolute certainty about any function that it will never throw; and (2) in most languages in unchecked exception, it's impossible to tell if the exception is from recoverable or unrecoverable error, and you're forced to either treat unrecoverable errors as recoverable, or recoverable errors as unrecoverable. And people do both all the time, and it sucks.

    Here's one problem with checked exceptions, wondering how you would resolve it. I call a function, such as "parse number", that takes a string and returns a number, and only throws if the number is out of range or the string is not a number. Now, let's say I have checks that ensure the string already matches the requirements of the function, such that it is impossible, short of a cosmic ready flipping a bit in memory, for the function to throw. So from my function, it is always a no throw operation. But because the function has the throw specification, I now have to add its specification to my own, despite my function not throwing that, or wrap it in a nonsensical catch for an exception that will never happen.

    In C++, I can declare my function noexcept, regardless of what I call. It's my job to adhere to the contract and not throw. If I was unlucky enough to have a cosmic ready flip the wrong bit and the function did throw, breaking the noexcept specification, it would result in my application calling std:: terminate and killing the process.

    So basically, you accept that any call may fail for any reason (although documentation hopefully provides indications as to what exceptions it will throw under what circumstances, same as functions detailing different error results), except for noexcept functions that will never throw (but may result in the program crashing instead, but they really shouldn't unless there's a serious bug).


  • Considered Harmful

    @dkf said in So I tried Go the other day:

    @Gąska I understand what you're saying, but error handling is the kind of thing where getting it right is absolutely essential so compromising purity may be required. Also, you end up with special cases anyway as you need to integrate error handling with the interface to the OS — (almost?) every system call can fail — and that's something you only really want to write at most once per language…

    And Rust gets it right. I'm not sure how you imply it doesn't, although you're implying such an implication.


  • Discourse touched me in a no-no place

    @pie_flavor said in So I tried Go the other day:

    And I think that Rust gets it right.

    FTFY. I bet that other language designers would disagree. (They often do, so having another disagreement isn't surprising…)


  • Discourse touched me in a no-no place

    @Kian said in So I tried Go the other day:

    Here's one problem with checked exceptions, wondering how you would resolve it.

    Catch the exception that shouldn't happen and rethrow it as a wrapped unchecked exception (probably a “this unreachable case was reached” exception, whatever you want to call it). It's a Programmer Dun Fukd Up case.


  • Considered Harmful

    @dkf Why? What's wrong with it?
    Rust forces you to handle the error, even if it's just saying 'yeah, there's an error, shaddup'. It avoids the pitfalls of both kinds of error handling, and it's not even slow like Go's because the error path is marked 'cold'.


  • 🚽 Regular

    @dkf said in So I tried Go the other day:

    If they had swapped the syntax so that the “let the error bubble on out” was the default and you required extra stuff to say when you wanted to trap it, you'd end up with (close to) what exceptions look like

    But they haven't an IMO it's a good thing. You have to deal with the error explicitly. Either you deal with it "properly", explicitly inside your function; or you add an unobstrusive-yet-niggling ? .

    Being able to use ? brings its own set of requirements: your own function needs to return Result as well, and the Error subtype inside that Return needs to be convertible from the error you aren't "catching".


  • Banned

    @Zecc said in So I tried Go the other day:

    and the Error subtype inside that Return needs to be convertible from the error you aren't "catching".

    It's worth adding there exist libraries that allow you to create new error types that are convertible from literally every other error type with minimal effort. I haven't been following Rust trends for quite some time, but from what I see, the current leading solution is failure crate ( @pie_flavor fact check me on this).


  • Considered Harmful

    @Gąska libfailure looks interesting, but I really don't know as I don't maintain any libraries, or projects large enough to care about error handling. When I need ? I just use Box<Error>.


  • Banned

    @pie_flavor said in So I tried Go the other day:

    Box<Error>

    Dynamic allocation! :doing_it_wrong:


  • Considered Harmful

    @pie_flavor said in So I tried Go the other day:

    because the error path is marked 'cold'.

    This by the way is a big problem with Go. Exceptions might be slow to throw but don't require any handling code in the non-exceptional case, whereas an if-then on every single error bubble has an impact, small or no. This is why exceptions have any use at all. Rust solves this problem by making the error path cold, so CPUs can predict the non-exceptional case and eliminate the conditional jump. But in Go error handling is just done with regular tuples, so you have useless conditionals everywhere.


  • Considered Harmful

    @Gąska Like I said, I'd change it if it got bigger.
    e: And you know failure::Error is dynamically allocated too, right?


  • Discourse touched me in a no-no place

    @pie_flavor said in So I tried Go the other day:

    Rust solves this problem by making the error path cold, so CPUs can predict the non-exceptional case and eliminate the conditional jump.

    Knowing how the Rust back-end (LLVM) works, that's not what is going on. Inlining and jump threading are far more important. Keeping the error path as the cold one is the right decision, sure, but it doesn't have nearly as big an impact as making sure that the jumps simply aren't there in the first place. The generated machine code really does not need to have the same structure as the input program normally.

    Which can make debugging from assembly back into your original program a bit tricky…



  • Okay so today was looking at a golang thread and I was thinking maybe I should learn it. Downloaded the installer and then I wanted to check what's the consensus here and HOLY SHIT!!

    It looks like Go is fucked up from what y'all are saying.

    The only reason why I wanted to pick this up was supply of devs who know golang here is pretty low. Thought I could make some money out of it by getting a golang gig someday. I'm so confused right now.


  • Considered Harmful

    @Gąska said in So I tried Go the other day:

    all the function that ARE NOT marked as raising errors are GUARANTEED to never raise any errors

    Guaranteed, huh? Neat. So they literally must do nothing that could fail. Not even allocate any memory.


  • Considered Harmful

    @stillwater said in So I tried Go the other day:

    Okay so today was looking at a golang thread and I was thinking maybe I should learn it. Downloaded the installer and then I wanted to check what's the consensus here and HOLY SHIT!!

    It looks like Go is fucked up from what y'all are saying.

    The only reason why I wanted to pick this up was supply of devs who know golang here is pretty low. Thought I could make some money out of it by getting a golang gig someday. I'm so confused right now.

    These aren't mutex.


  • Banned

    @Gribnit said in So I tried Go the other day:

    @Gąska said in So I tried Go the other day:

    all the function that ARE NOT marked as raising errors are GUARANTEED to never raise any errors

    Guaranteed, huh? Neat. So they literally must do nothing that could fail. Not even allocate any memory.

    They can do whatever they want. They just can't let those errors escape their stack frame.


  • Banned

    @stillwater said in So I tried Go the other day:

    The only reason why I wanted to pick this up was supply of devs who know golang here is pretty low.

    Usually that's a reason to avoid the language.


  • BINNED

    @Gribnit said in So I tried Go the other day:

    @Gąska said in So I tried Go the other day:

    all the function that ARE NOT marked as raising errors are GUARANTEED to never raise any errors

    Guaranteed, huh? Neat. So they literally must do nothing that could fail. Not even allocate any memory.

    Are we still talking about Java style exception specifications? There, failure to allocate memory would be a runtime exception, which belongs to the "not checked" class of exceptions. But of course you could make a system without such an escape hatch.
    Then, any functions marked as not raising errors will either be intrinsically safe from errors, handle all errors itself, or not return (e.g. terminate the program).


  • Considered Harmful

    @topspin said in So I tried Go the other day:

    not return (e.g. terminate the program).

    This escape hatch being irremovable. This is where I have problems with wording like "guaranteed".


  • BINNED

    @Gribnit said in So I tried Go the other day:

    @topspin said in So I tried Go the other day:

    not return (e.g. terminate the program).

    This escape hatch being irremovable. This is where I have problems with wording like "guaranteed".

    Guaranteed as far as the semantics of the language go. Your software can't guarantee there's no hardware outage, either.


  • Considered Harmful

    @topspin said in So I tried Go the other day:

    @Gribnit said in So I tried Go the other day:

    @topspin said in So I tried Go the other day:

    not return (e.g. terminate the program).

    This escape hatch being irremovable. This is where I have problems with wording like "guaranteed".

    Guaranteed as far as the semantics of the language go. Your software can't guarantee there's no hardware outage, either.

    yet there's people writing finallys against it right now...


  • Banned

    @Gribnit said in So I tried Go the other day:

    @topspin said in So I tried Go the other day:

    not return (e.g. terminate the program).

    This escape hatch being irremovable. This is where I have problems with wording like "guaranteed".

    Well, I have a problem with not understanding what the word "raise" means. No, it doesn't mean every instance of error happening. It only means instances where this error is signaled to the caller in some way. Functions not marked as raising errors are guaranteed to never raise any errors. Literally. In all cases. No exceptions. That errors still can happen is another matter entirely.


  • Notification Spam Recipient

    @bb36e said in So I tried Go the other day:

    Thread summary: Go sucks because Java has checked exceptions

    I was thinking the same thing!



  • There are also plenty of threads going around where someone says "I went back to Go after working on Rust and didn't realise how good Go was. Thank God I'm back" and Rust users who worked on Go coming back to Rust and saying the same.

    Paging the resident Rust evangelist @pie_flavor for opinions based on first hand experience


Log in to reply