Live data from Hacker News

Borgo is a statically typed language that compiles to Go

github.com

321–330 of 559 posts

Re: Borgo is a statically typed language that compiles to Go

#321
post #240

Earlier quoted context omitted.

It doesn't not use exception handlers as a primary way of handling errors either, though. Go doesn't specify any error handling mechanism. Using exception handlers is just as valid as any other, and even the standard library does it, as noted earlier. The only error-related concept the Go language has is the error type, but it comes with no handling semantics. Which stands to reason as there is nothing special about…

You're absolutely technically correct, in the "spherical cow in a vacuum" sense. In reality though, essentially all Go code out there handles errors through the pattern of checking if the error in a `(value, error)` tuple returned from a function is `nil` or not. That is what the discussion here is about - the way errors are handled in a language in practice, not in theory. Therefore, pedantry. Basically, discussions…

    "spherical cow in a vacuum"
I only learned about this recently. Very funny to me, and appropriately used here. Ref: https://en.wikipedia.org/wiki/Spherical_cow

Re: Borgo is a statically typed language that compiles to Go

#323

This looks like an interesting sweet spot. Rust is often praised for the borrow checker, but honestly I really only like rust for the type system and error handling. Go is praised for it's simplicity, but hated for it's error handling.

You can get Rust's type system in most ML derived languages, some of them even go beyond what Rust is capable of today.

Re: Borgo is a statically typed language that compiles to Go

#324

Wow, this is everything I want from a new Go! Having worked on multiple very large Go codebases with many engineers, the lack of actual enums and a built-in optional type instead of nil drive me crazy. I think I'm in love. Edit: Looks like last commit was 7 months ago. Was this abandoned, or considered feature complete? I hope it's not abandoned!

An Enum type has to be on the core Go team's radar by now. It's got to be tied with a try/catch block in terms of requested features at this point (now that we have generics).

How the fuck do you release a language without enums?

Re: Borgo is a statically typed language that compiles to Go

#325

Earlier quoted context omitted.

> sounds good on paper, but seeing "if err!=nil" repeated million times in golang codebases does not create positive impression at all Okay, but other than exceptions, whats the alternative?

The ? Operator in Rust?

Good point.

I only briefly tried Rust and was turned off by the poor ergonomics; I don't think (i.e. open to correction) that the Rust way (using '?') is a 1:1 replacement for the use-cases covered by Go error management or exceptions.

Sometimes (like in the code I wrote about 60m ago), you want both the result as well as the error, like "Here's the list of files you recursively searched for, plus the last error that occurred". Depending on the error, the caller may decide to use the returned value (or not).

Other times you want an easy way to ignore the error, because a nil result gets checked anyway two lines down: Even when an error occurs, I don't necessarily want to stop or return immediately. It's annoying to the user to have 30 errors in their input, and only find out about #2 after #1 is fixed, and #3 after #2 is fixed ... and number #30 after #29 is fixed.

Go allows these two very useful use-cases for errors. I agree it's not perfect, but with code-folding on by default, I literally don't even see the `if err != nil` blocks.

Somewhat related: In my current toy language[1], I'm playing around with the idea of "NULL-safety" meaning "Results in a runtime-warning and a no-op", not "Results in a panic" and not "cannot be represented at all in a program"[2].

This lets a function record multiple errors at runtime before returning a stack of errors, rather than stack-tracing, segfaulting or returning on the first error.

[1] Everyone is designing their own best language, right? :-) I've been at this now since 2016 for my current toy language.

[2] I consider this to be pointless: every type needs to indicate lack of a value, because in the real world, the lack of a value is a common, regular and expected occurrence[3]. Using an empty value to indicate the lack of a value is almost certainly going to result in an error down the line.

[3] Which is where there are so many common ways of handling lack of a value: For PODs, it's quite popular to pick a sentinel value, such as `(size_t)-1`, to indicate this. For composite objects, a common practice is for the programmer to check one or two fields within the object to determine if it is a valid object or not. For references NULL/null/nil/etc is used. I don't like any of those options.

Re: Borgo is a statically typed language that compiles to Go

#326

Wow, this is everything I want from a new Go! Having worked on multiple very large Go codebases with many engineers, the lack of actual enums and a built-in optional type instead of nil drive me crazy. I think I'm in love. Edit: Looks like last commit was 7 months ago. Was this abandoned, or considered feature complete? I hope it's not abandoned!

While I have no particular beef with Rust deciding to call its sum types "enum", to refer to this as the actual enum is a bit much. Enumerated types are simply named integers in most languages, exactly the sort you get with const / iota in Go: https://en.wikipedia.org/wiki/Enumerated_type Rather than the tagged union which the word represents in Rust, and only Rust. Java's enums are close, since they're classes and o…

> While I have no particular beef with Rust deciding to call its sum types "enum", to refer to this as the actual enum is a bit much.

I didn't read GP as saying "Actual enums are what Rust has", I read it more as "Go doesn't have actual enums", where "enum" is a type that is constrained to a specified set of values, which is what all mainstream non-Rust languages with enums call "Enums".

I mean, even if Rust never existed, the assertion "Go doesn't have actual enums" is still true, no?

Re: Borgo is a statically typed language that compiles to Go

#327
post #317
post #202

Earlier quoted context omitted.

No one wants try/catch/exception in Go.

Because if err != nil { return err } repeated all over the place, is the epitome of productivity!

It actually is when debugging, because it makes control flow explicit.

In JS, for example, people don‘t even know which functions could throw exceptions, and just ignore them, most of the time. Fast to write and looks nice, but is horrible quality and a nightmare to debug.

Re: Borgo is a statically typed language that compiles to Go

#328

Earlier quoted context omitted.

The ability to quickly parse, understand and reason about code is not superficial, it is essential to the job. And that is essentially what those verbose blocks of text get in the way of.

As an experienced Go dev, this is literally not a problem. Golang code has a rhythm: you do the thing, you check the error, you do the thing, you check the error. After a while it becomes automatic and easy to read, like any other syntax/formatting. You notice if the error isn't checked. Yes, at first it's jarring. But to be honest, the jarring thing is because Go code checks the error every time it does something, n…

Just because you can adapt to verbosity does not make it a good idea.

I've gotten used to Javas getter/setter spam, does that make it a good idea?

Moreover, don't you think that something like Rusts ? operator wouldn't be a perfect solution for handling the MOST common type of error handling, aka not handling it, just returning it up the stack?

  val, err := doAThing()
  if err != nil {
    return nil, err
  }
VERSUS

  val := doAThing()?

Re: Borgo is a statically typed language that compiles to Go

#329

Earlier quoted context omitted.

I am so tired of reading Java/C++/Python code that just slaps try/catch around several lines. To some it might seem annoying to actually think about errors and error handling line by line, but for whoever tries to debug or refactor it's a godsend. Where I work, try/catch for more than one call that can throw an exception or including arbitrary lines that don't throw the caught exception, is a code smell. So when I lo…

Yes, it's the ability to unwind the stack to an exception handler without having to propagate errors manually. Go programs end up doing the exact same thing as "try/catch around multiple lines" with functions that can return an error from any point, and every caller blindly propagating the error up the stack. The practice is so common that it's like semicolons in Java or C, it just becomes noise that you gloss over.

Go programs generally do not “blindly prepare the error up the stack”. I’ve been writing Go since 2011 and Python since 2008, and for the last ~decade I’ve been doing DevOps/SRE for a couple of places that were both Go and Python shops. Go programs are almost universally more diligent about error handling than Python programs. That doesn’t mean Go programs are fre from bugs, but there are far, far fewer of them in the error path compared to Python programs.

Re: Borgo is a statically typed language that compiles to Go

#330
post #270
post #261

Earlier quoted context omitted.

> but I love Option/Result types more than Go's error approach The thing is, these don't add much on their own. You'd have to bring in pattern matching and/or a bunch of other things* that would significantly complicate the language. For example, with what's currently in the language, you could definitely have an option type. You'd just be limited to roughly an api that's `func (o Option[T]) IsEmpty() bool` and `func…

Using an Option instead of a pointer buys you the inability to forget to check for nil. Just need to make sure the Option exposes the internal value only through: func (o Option[Value]) Get() (Value, bool) { return o.value, o.exists } Accessing the value is then forced to look like this: if value, ok := option.Get(); ok { // value is valid } // value is invalid Thus, there's no possibility of an accidental nil pointe…

How is that better than

    if value != nil {
        // value is valid
    }
    // value is invalid
?

Of course, this is often left out, but you can just as easily do:

    value, _ := option.Get()
So this is just not true:

> Using an Option instead of a pointer buys you the inability to forget to check for nil.

Post reply on HN