[HN Gopher] Show HN: Error return traces for Go, inspired by Zig
___________________________________________________________________
Show HN: Error return traces for Go, inspired by Zig
Author : abhinavg
Score : 76 points
Date : 2023-11-29 13:01 UTC (9 hours ago)
(HTM) web link (github.com)
(TXT) w3m dump (github.com)
| Kharacternyk wrote:
| The logo is awesome. Has an artist been hired to create it?
| abhinavg wrote:
| Thanks! No, just one of the maintainers with a free evening.
| Eun wrote:
| Can you explain why we should this over
| https://github.com/pkg/errors?
| para_parolu wrote:
| Even this package is not needed anymore
| dagss wrote:
| How do you get stack traces of errors?
| randomdata wrote:
| The same way you get stack traces of names, email
| addresses, random numbers, etc. It is funny how the word
| 'error' leaves some suddenly forgetting how to write
| software.
| abhinavg wrote:
| 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.
| avg_dev wrote:
| How does one go about implementing something like this? I am
| quite curious.
| yalue wrote:
| Judging by the project, it's implemented by instrumenting
| the source code; either manually modifying error returns
| with a wrapper function, or by running source files through
| an automated tool that will find and modify the return
| statements for you.
| marhee wrote:
| I suspect it is based on https://pkg.go.dev/runtime#Caller
| Groxx wrote:
| 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.
| oefrha wrote:
| It's archived mainly because it's been superseded by
| fmt.Errorf() with the %w directive. Go 1.20 also introduced
| errors.Join() and multi-%w which github.com/pkg/errors lack,
| so using for green field projects is very ill-advised.
| Groxx wrote:
| Except for the stack trace part, which is a gigantic reason
| why it was popular.
|
| tbh I'm not sure what the current popular option is for
| wrapping with stack traces.
|
| Re join: it isn't a joiner-error, it has no need to do
| anything for that. Just stdlib-join-then-wrap.
| oefrha wrote:
| It's pretty easy to write your own Errorf() wrapper or
| some sort of WithStack() that stores
| runtime/debug.Stack() output. github.com/pkg/errors
| offers more flexibility in formatting though.
| Groxx wrote:
| Well, sure, but by that metric this library is _even
| easier_ to build yourself since it 's only gathering a
| single stack entry per wrap. And it has no backwards
| compatibility to worry about.
|
| "You can build X by hand too" has little to do with why
| people choose to create or use libraries.
| healsdata wrote:
| > "You can build X by hand too" has little to do with why
| people choose to create or use libraries.
|
| In my experience, "you can build X by hand" is the Go
| community's preferred approach.
| pstuart wrote:
| It would be great if the internals added %W as an option
| that would also include the relevant trace. Shouldn't be
| unreasonable or impossible.
| pixelpoet wrote:
| (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.
| Night_Thastus wrote:
| 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?
| klyrs wrote:
| Nope, no operator overloading. As I understand it, the
| philosophy is to not hide O(n) behavior behind notation that
| looks O(1).
| Night_Thastus wrote:
| Strange.
|
| How is that different from say, a function call? A function
| may look like a single O(1) operation from the
| input/output/name, but actually do something much more
| complex. That seems like the same thing to me, and very
| common. (and frankly I'm not sure that could even be
| avoided)
| klyrs wrote:
| I didn't mean to volunteer to defend this choice, but
| without investigating a function you can't really support
| an opinion about its runtime. A language can make such
| promises about its basic syntax however.
|
| Perhaps I'll rephrase how I understand the philosophy: if
| it's a function call, it should look like a function
| call. Operator overloading breaks that.
|
| That said, this isn't my hill to die on.
|
| Edit to clarify my final sentence there: I have zero
| interest in debating this any further. Pixelpoet, if
| you're going to be so fussy, go read Harvey and van der
| Hoeven and stop trying to win language fights, they're
| tedious.
| pixelpoet wrote:
| I appreciate your being such a good devil's advocate,
| however as ForkMeOnTinder points out, there is already
| the super complicated[0] overloaded O(N^1.58+) operator
| for arbitrary precision integer multiplication, easily
| argued to be vanishingly less useful than simple vector
| operators, particularly if they were well-expressed at
| the IR level and well-mapped to modern hardware /
| instructions.
|
| The ask isn't for general operator overloading (I'm also
| in favour of not having that), rather just not stopping
| native algebraic type support at scalars; the C function
| atan2(y, x) basically just wants to give you the complex
| argument, for example. Really it would just do so much to
| unify and simplify everything, besides being able to
| write vector stuff in a sane way; if every rando has to
| write their own vector and complex number classes, I'm
| much less likely to vouch for its correctness.
|
| [0] I've recently been looking into Karatsuba
| multiplication to reduce it from O(N^2) to O(N^1.58):
| https://en.wikipedia.org/wiki/Karatsuba_algorithm
| ForkMeOnTinder wrote:
| And what's funny about that stance is mathematical
| operators aren't actually O(1).
|
| https://en.wikipedia.org/wiki/Computational_complexity_of_m
| a...
|
| You don't want to know what the innocent-looking `*` in
| this function compiles to: fn square(num:
| u10000) u10000 { return num * num; }
| pixelpoet wrote:
| It's mildly offensive that u10000 is a builtin type but
| vec2f is not (also note that I am not asking for general
| operator overloading!). Which has dedicated CPU
| instructions across all modern architectures, what's the
| relative usage frequency, what's the cost/benefit of
| each, etc etc... :( And we all know why u10000 is in
| there: because you have to have arbitrary-width integers
| when writing a compiler, so they figured eh, we'll just
| expose that because we have it already. Absolutely
| transparent compiler-programming (cf. rendering-
| programming) bias, almost nobody else needs that.
|
| And yeah, I get that Add(Add(Add(a, b), Mul(c, 3)), d) is
| possible, but come on... imagine if you had to write your
| normal "a + b + c * 3 + d" with ints/floats like that!
| What's that, suddenly people care, but nobody cares if
| it's not their field...
|
| Whatever, I will continue to look longingly at Zig for
| all the bits of C/C++ (and apparently Go, to try bring it
| back to the original topic) it solves, but missing the
| trivial and absolutely critical single feature to enable
| an entire class of performance-critical programming.
| defen wrote:
| > And we all know why u10000 is in there: because you
| have to have arbitrary-width integers when writing a
| compiler
|
| You don't need them as a built-in type to write a
| compiler. They're there because LLVM was the original
| backend and you essentially get them for free (in the
| sense that the backend code generation is already handled
| for you, so why not include them).
| truckerbill wrote:
| 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)
| reactordev wrote:
| agreed, further with today's parallelism it _should_ be
| trivial but like you said, most languages stop at scalars and
| force the onus on you. I get it, higher order math is an
| implementation detail but to not provide the proper tools for
| those implementations is frustrating.
| pixelpoet wrote:
| The main thing that stands out about this comment to me
| (agreeing 100% about algebraic types) is the "at this point
| in time" bit, such boundless optimism :D
| ForkMeOnTinder wrote:
| 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.
| pixelpoet wrote:
| He's actually fluent in a lot of languages[0]. Just somehow
| apparently not much sympathy for numerical computing, or UI
| code (I'm fairly sure you want 2d vectors there too), or
| plotting, or ...
|
| [0] https://andrewkelley.me/post/not-a-js-developer.html
| dilyevsky wrote:
| Not supporting operator overloading is not a "strange
| decision" it's widely hated feature outside of very specific
| domains (like maths and graphics) and every shop i worked at
| which bothered with a c++ guideline banned it
| snovv_crash wrote:
| Banned for in-house use, sure. Require an extra review
| before including a library, sure. But don't tell me you
| refuse to use Eigen and force everyone to write their own
| matrix multiplication routines that don't have operator
| overloading...
| dilyevsky wrote:
| That is why I specifically mentioned math and graphics as
| exceptions. Honestly I still like explicit DSL model
| better for these than trying to build dsl on top of your
| existing language c++/lisp style
| zoogeny wrote:
| 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
| sevagh wrote:
| >I've heard people joke that AI is just matrix multiplication
|
| Not sure where the joke is, today's deep learning based AI
| models are literally matrix multiplications with learned
| weights.
| xh-dude wrote:
| Julia has good ideas, interesting trade-offs here as well.
| ISTM the deep problem is that there's so much room for
| optimization under composition of operations or with
| invariants not captured in types that the typical LinAlg
| library will never capture. But I agree most languages should
| be anticipating that users need something helpful here.
| lll-o-lll wrote:
| Doesn't this open github issue imply that vector operators are
| still being considered?
| https://github.com/ziglang/zig/issues/7295
|
| Or is it that the three years it's been around indicate it will
| never progress?
| pixelpoet wrote:
| This is far better than my attempts at initiating the
| discussion, thanks for linking!
|
| Also it seems like even the discussion of Geometric Algebra
| has been covered before 3 years ago: https://github.com/zigla
| ng/zig/issues/7295#issuecomment-7389...
|
| Unless it's actually possible after all this time (even in
| some random beta) to do vector code in infix notation, it
| doesn't feel like it's going to happen :(
| el_oni wrote:
| 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/
| Vanclief wrote:
| 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.
| zgk7iqea wrote:
| go is step by step reinventing exceptions
___________________________________________________________________
(page generated 2023-11-29 23:01 UTC)