top | item 38458802

Show HN: Error return traces for Go, inspired by Zig

133 points| abhinavg | 2 years ago |github.com

84 comments

order

Kharacternyk|2 years ago

The logo is awesome. Has an artist been hired to create it?

abhinavg|2 years ago

Thanks! No, just one of the maintainers with a free evening.

da39a3ee|2 years ago

I read the README but I'm not understanding yet why the return path might be what you want. The stack trace at error creation sounds more useful.

prashantv|2 years ago

The stack trace and return path are pretty similar if the flow goes through function calls on a single goroutine, but if errors propagate across goroutines or across different stacks (E.g., via channels), then it can miss some useful details.

Here's an example that compares them: https://pkg.go.dev/braces.dev/errtrace#readme-comparison-wit...

Since the HTTP library uses a separate goroutine to create connections, the stack trace at creation time doesn't have details about the user request that triggered the connection.

Vanclief|2 years ago

While from a first instance, this package seems a bit overkill, I think the idea is interesting and is something that can be improved for Go.

I also felt that Go errors where too bare-bones, so I developed a small package (https://github.com/Vanclief/ez) based on an awesome post that I saw here once. I use this package in all Golang code I touch.

stirante|2 years ago

We actually did something similar in Go here: https://github.com/Bedrock-OSS/go-burrito

I guess the difference we try to make is that we really wanted to make errors that are understandable by users. Each time the error is returned we try to wrap it with an information where and why.

pixelpoet|2 years ago

(Aside about Zig, sorry. Although this applies to Go as well, I think?) Urgh I am so keen to switch to Zig but their attitude towards having vector operators just completely kills the viability for me as a graphics programmer.

I've asked in their Discord, Andrew Kelley himself passed on commenting (I know his stance, every C++ dev wants their fav feature), but the reality remains that it's just infeasible to do with a DSL so it's just the wrong language for writing graphics code.

zoogeny|2 years ago

I was watching a recent talk about the new Mojo language [1]. There is a section on SIMD and how they treat scalar values as a special case of vector operations (around the 33 min time).

It does seem that tensors are one of the core abstractions for modern ML systems. I've heard people joke that AI is just matrix multiplication. Python is such a flexible language that creating abstractions around its syntax was super easy. I believe that was part of the reason Python has come to dominate this space (not the only reason obviously).

I too felt the same as you, but as a distant admirer of Zig. I totally understand that operator overloading can be misused. But I have an intuition that at least providing operators for linear algebra (and probably complex/quaternion) is a really important feature for any languages from this point in history going forward.

1. https://www.youtube.com/watch?v=SEwTjZvy8vw&ab_channel=LLVM

ForkMeOnTinder|2 years ago

That's one of the downsides of a BDFL. Zig is like 98% amazing, and 2% strange decisions that I think could have been avoided if the creator had more experience with languages other than C and Javascript.

I'm still a happy Zig user though, and hey, there's still time before 1.0.

truckerbill|2 years ago

It is strange that we stop at scalars for algebra in most languages. Odin’s approach is almost more frustrating, allowing for quaternion types, but not clifford algebra which can elegantly describe them and much more(though i know it’s a comically niche request at this point in time)

el_oni|2 years ago

Odinlang is a language in a similar space that seems to have first class support for matrix and vector operations. As well as having built in support for various graphics apps [0].

Seems like there is a bunch of interesting low level languages gaining steam at the moment.

[0] https://odin-lang.org/news/major-graphics-apis/

crest|2 years ago

Didn't Zig "just" decide to permanently stay irrelevant for performance critical code by replacing LLVM by a yet to be written home grown optimiser and code generator? Don't get me wrong LLVM has lots of warts, but the a good multi architecture optimiser and code generator is a larger project than the frontend and standard library for any reasonable language.

renox|2 years ago

What's really sad is that not having overloading "ON" by default is a good idea, but it doesn't mean that language has to stop there, it's really simple to have a small language feature which would say that

a #everything_until_the_next_space b is rewritten in #everything_until_the_next_space(a,b)

So you'd have:

-a #foo b #foo c is foo(foo(a,b),c)

-a #foo b #bar c is forbidden, use parenthesis.

-and maybe #: for the inverse composition where a #:foo b #:foo c is foo(a, foo(b,c))

It's explicit, no hidden overloading, yet it's "short" enough to be usable: (a #* b) #+ c isn't that much worse than a*b+c and is much more readable than madd(mmul(a,b),c)..

If there is no implicit conversion name clashes shouldn't be too bad (both #+ could be usable for matrix and for graphic libraries).

__loam|2 years ago

Am I crazy or is there nothing stopping us from writing functions that work with vectors? I don't really understand why this is a big headache for graphics programming other than it not being your preferred syntax.

Night_Thastus|2 years ago

I'm a C++ dev, could you explain a bit of what is missing in Zig for vector operations? Does Zig not have operator overloading?

Eun|2 years ago

Can you explain why we should this over https://github.com/pkg/errors?

abhinavg|2 years ago

The README covers the idea behind errtrace in more details, but the primary difference is in what is captured:

pkg/errors captures a stack trace of when the error occurred, and attaches it to the error. This information doesn't change as the error moves through the program.

errtrace captures a 'return trace'--every 'return' statement that the error passes through. This information is appended to at each return site.

This gives you a different view of the code path: the stack trace is the path that led to the error, while the return trace is the path that the error took to get to the user.

The difference is significant because in Go, errors are just plain values that you can store in a struct, pass between goroutines etc. When the error passes to another goroutine, the stack trace from the original goroutine can become less useful in debugging the root cause of the error.

As an example, the Try it out section (https://github.com/bracesdev/errtrace/#try-it-out) in the README includes an example of a semi-realistic program comparing the stack trace and the return trace for the same failure.

Groxx|2 years ago

At the very least:

>This repository has been archived by the owner on Dec 1, 2021. It is now read-only.

It's largely complete so it is essentially fine at the moment, but it won't be adapted to future language or community changes. A future landmine.

para_parolu|2 years ago

Even this package is not needed anymore

zgk7iqea|2 years ago

go is step by step reinventing exceptions

alphazard|2 years ago

Exceptions typically unwind the stack, producing a stack trace similar to what certain Go error types already do. Go's panic does actually unwind the stack. In a sense, Go has had Java/Python style exceptions, from the beginning, through panic and recover. This project distinguishes itself from that pattern in the README.

As far as error handling is concerned, errors as values is the modern thinking. Go is not behind the times here. If you squint, the `(T, error)` return type is very similar to Rust's `Result`, and the `if err != nil` idiom is basically Monadic control flow.

wwarner|2 years ago

go basically has exceptions with panic & recover. and it’s perfectly simple to add stack traces to errors, should you want it.

kaba0|2 years ago

[deleted]

packetlost|2 years ago

Exceptions are only better than C style error return numbers but worse than pretty much every other model of error handling we have today.