Live data from Hacker News

Context should go away for Go 2 (2017)

faiface.github.io

91–100 of 176 posts

Re: Context should go away for Go 2 (2017)

#91
post #66

Earlier quoted context omitted.

> against the principles behind statically-typed languages, which all hate implicit things But many statically typed languages allow throwing exceptions of any type. Contexts can be similar: "try catch" becomes "with value", "throw" becomes "get".

Yes, but then those languages usually implement only unchecked exception, as propagating error types up the call tree is seen as annoying . And then, because there are good reasons you may want to have typed error values (instead of just "any"), there is now pressure to use result types (aka. "expected", "maybe") instead - turning your return type Foo into Result . And all that it does is making you spell out the ent…

We could make explicit effect (context, error) declarations for public functions and inferred for private functions. Explicit enumeration of possible exceptions is required for stable APIs anyway.

Re: Context should go away for Go 2 (2017)

#92

This is about an explicit argument of type "Context". I'm not a Go user, and at first I thought it was about something else: an implicit context variable that allows you to pass stuff deep down the call stack, without intermediate functions knowing about it. React has "Context", SwiftUI has "@Environment", Emacs LISP has dynamic scope (so I heard). C# has AsyncLocal, Node.JS AsyncLocalStorage. This is one of those id…

> an implicit context variable that allows you to pass stuff deep down the call stack, without intermediate functions knowing about it. [...] but is actually very useful and can result in cleaner code with less globals or less superfluous function arguments. [...] and it applies to everything down the call stack (but not in other threads/async contexts).

In my experience, these "thread-local" implicit contexts are a pain, for several reasons. First of all, they make refactoring harder: things like moving part of the computation to a thread pool, making part of the computation lazy, calling something which ends up modifying the implicit context behind your back without you knowing, etc. All of that means you have to manually save and restore the implicit context (inheritance doesn't help when the thread doing the work is not under your control). And for that, you have to know which implicit contexts exist (and how to save and restore them), which leads to my second point: they make the code harder to understand and debug. You have to know and understand each and every implicit context which might affect code you're calling (or code called by code you're calling, and so on). As proponents of another programming language would say, explicit is better than implicit.

Re: Context should go away for Go 2 (2017)

#93
post #3

Earlier quoted context omitted.

Yes, I was about to comment that “there won’t be a Go 2”, but I guess that wasn’t settled when the article was written.

as someone who's not in the community: why not?

The major features that may have required a 2.0 were implemented in a backwards-compatible way, removing the utility of a Go 2.0.

Go 2.0 was basically a blank check for the future that said "We may need to break backwards compatibility in a big way". It turns out the Go team does not see the need to cash that check and there is no anticipated upcoming feature in the next several years that would require it.

The last one that I was sort of wondering about was the standard library, but the introduction of math/rand/v2 has made it clear the devs are comfortable ramping standard library packages without a Go 2. There are a number of standard libraries that I think could stand to take a v2; there aren't any that are so broken that it's worth a v2 to hard-remove them. (Except arguably syscall [1], which turns out it doesn't belong in the standard library because it can't maintain the standard library backwards compatibility and should have been in the extended standard library from the beginning, but that's been the way it is now for a long time and also doesn't rate a v2.)

(And again let me underline I'm not saying all the standard library is perfect. There is some brokenness here and there, for various definitions of "brokenness". I'm just saying it's not so broken that it's worth a v2 hard break at the language level and hard elimination of the libraries such that old code is forcibly broken and forced to update to continue on.)

[1]: https://pkg.go.dev/syscall

Re: Context should go away for Go 2 (2017)

#94

Earlier quoted context omitted.

Consider this: ctx, cancel := context.WithTimeout(context.Background(), 60*time.Second) reader := ioContextReader(ctx, r) ... ctx, cancel := context.WithTimeout(ctx, 1*time.Second) ctx = context.WithValue(ctx, "hello", "world") ... func(ctx context.Context) { reader.Read() // does not time out after one second, does not contain hello/world. ... }(ctx)

There are two solutions, depending on your real use case: 1) You're calling Read() directly and don't need to use functions that strictly accept io.Reader - then just implement ReadContext: func (rc ioContextReader) ReadContext(ctx context.Context, p []byte) (n int, err error) { done := make(chan struct{}) go func() { n, err = rc.Reader.Read(p) close(done) }() select { case Otherwise, just wrap the ioContextReader wi…

Changing the interface 1) is obviously not relevant.

Re-wrapping works only for the toy example. In the real world, the reader isn't some local variable, but there could be many, across different structs, behind private fields.

To cirle back, and not focus too much on the io.Reader example: the virality of ctx is real, and making wrapper structs is not a good solution. Updating stale references may not be possible, and would quickly become overwhelming. Not to forget the performance overhead.

Personally I think it's okay, go is fine as a "webservices" language. The go gospel is, You can have your cake and eat it too, but it's almost never true unless you twist the meaning of "cake" and "eat".

Re: Context should go away for Go 2 (2017)

#95
post #90

Earlier quoted context omitted.

> It’s best not to acquire a mutex and launch a goroutine to read 3 bytes of data at a time. io.Copy uses 32KB buffers. Other parts of standard library do too. If you're using Read() to read 3 bytes of data at a time, mutex is the least of your worries. Since you seem to be ignoring sarcasm of my previous comment - just saying "don't do that" without suggesting an alternative way in the particular code context you're…

It may well use 32KB buffers, or any size, but that doesn’t translate to “reading 32KB at a time”. If you’re aborting specifically an io.Copy, then there are better ways to do that: abort in the write path rather than the read path. It’s not my job to provide you with alternative code. That’s your job.

> It’s not my job to provide you with alternative code. That’s your job.

It is not your job to tell me "that is wrong", yet you do it because it's easy. Suggesting an alternative (not necessarily providing the code) is less easy, so you don't wanna do it. That's fine. I just want you to be aware that the former without the latter is pretty much useless.

Re: Context should go away for Go 2 (2017)

#96
post #90

Earlier quoted context omitted.

It may well use 32KB buffers, or any size, but that doesn’t translate to “reading 32KB at a time”. If you’re aborting specifically an io.Copy, then there are better ways to do that: abort in the write path rather than the read path. It’s not my job to provide you with alternative code. That’s your job.

> It’s not my job to provide you with alternative code. That’s your job. It is not your job to tell me "that is wrong", yet you do it because it's easy. Suggesting an alternative (not necessarily providing the code) is less easy, so you don't wanna do it. That's fine. I just want you to be aware that the former without the latter is pretty much useless.

It is also easy to tell you that you’re wrong if you were to post that you use your forehead to hammer nails into a post.

Posting detailed instructions on how to identify, purchase and utilise a hammer isn’t something I need to do, and doesn’t negate the correctness of the initial “don’t do that”.

Re: Context should go away for Go 2 (2017)

#97
post #86
post #43

Earlier quoted context omitted.

It seems you are both saying the same thing. Had Python not introduced a line in the sand and instead continued to support Python 2 amid future updates there would have been no reason for Python 3. The Python 2 line could have kept improving instead. Just as you say, Python could have introduced what is found in Python 3 without breaking Python 2 support. Which is the direction Go has settled on; hence why Go 2 is of…

No. The point of rust editions is that they do break support for older code, which is very different to what go has now settled on. IMO, it's the best of both worlds. Old code continues to work forever, but your language design isn't held back by older design mistakes.

The trouble with the Rust community is that it is terrible at communication. That may be why you extend a presupposition that everyone understands the meaningful difference between Rust editions and Go version directives, but I can't tell a difference beyond the frivolous like syntax used. Based on the documentation of each they seem like the exact same concept, with the exact same goals in mind. As a result, unfortunately, your point is not yet made. Perhaps you can break the cycle and describe for every day people how Rust editions are fundamentally different?

Re: Context should go away for Go 2 (2017)

#98
post #26
post #20

Earlier quoted context omitted.

To not repeat other's (Python) mistakes ;-)

The the introduction of Python 3 wasn't a mistake. The mistake was discontinuing Python 2. Just look at how rust does it. Rust 1.0 code still works in the latest version of rustc, you just need to set the project to the Rust 2015 edition. You can even mix-and-match editions, as each crate can have a different edition. Newer versions of rustc will always support all previous editions, and breaking changes are only eve…

I'd say Rust editions are more like going from Python 2.x to Python 2.y, than the 2->3 migration. The Rust standard library is still the same (and the string type is still "valid UTF-8") no matter the edition (this is why you can mix-and-match editions), the edition differences are mostly on the syntax.

> Just imagine how much smoother the python 3 transition would have been if you could transition projects incrementally, module by module as needed.

That would require manually converting strings to the correct type at each module boundary (you can't do it automatically, because on the Python 2.x side, you don't know whether or not a string has already been decoded/encoded into a specific character encoding; that is, you don't know whether a Python 2.x string should be represented by a "bytes" or a "str" on the Python 3.x side). That's made even harder by Python's dynamic typing (you can't statically look at the code and point all the places which might need manual review).

Re: Context should go away for Go 2 (2017)

#99
post #80

Earlier quoted context omitted.

An alternative is to add all dependencies explicitly into function argument list or object fields, instead of using them implicitly from the context, without documentation and static typing. Including logger.

> instead of using them implicitly from the context, without documentation and static typing This is exactly what context is trying to avoid, and makes a tradeoff to that end. There's often intermediate business logic that shouldn't need to know anything about logging or metrics collection or the authn session. So we stuff things into an opaque object, whether it's a map, a dict, a magic DI container, "thread local s…

I disagree that it's a good approach. I think that parameters must be passed down always, as parameters. It allows compiler to detect unused parameters and it removes all implicitness.

It is verbose indeed and may be there should be programming language support to reduce that verbosity. Some languages support implicit parameters which proved to be problematic but may be there should be more iterations on that manner.

I consider context for passing down values to do more harm than good.

Re: Context should go away for Go 2 (2017)

#100
post #92

This is about an explicit argument of type "Context". I'm not a Go user, and at first I thought it was about something else: an implicit context variable that allows you to pass stuff deep down the call stack, without intermediate functions knowing about it. React has "Context", SwiftUI has "@Environment", Emacs LISP has dynamic scope (so I heard). C# has AsyncLocal, Node.JS AsyncLocalStorage. This is one of those id…

> an implicit context variable that allows you to pass stuff deep down the call stack, without intermediate functions knowing about it. [...] but is actually very useful and can result in cleaner code with less globals or less superfluous function arguments. [...] and it applies to everything down the call stack (but not in other threads/async contexts). In my experience, these "thread-local" implicit contexts are a…

They're basically dynamic scoping and it's both a very useful and powerful and very dangerous feature ... scheme's dynamic-wind model makes it more obvious when the particular form of magic is in use but isn't otherwise a lot different.

I would like to think that somebody better at type systems than me could provide a way to encode it into one that doesn't require typing out the dynamic names and types on every single function but can instead infer them based on what other functions are being called therein, but even assuming you had that I'm not sure how much of the (very real) issues you describe it would ameliorate.

I think for golang the answer is probably "no, that sort of powerful but dangerous feature is not what we're going for here" ... and yet when used sufficiently sparingly in other languages, I've found it incredibly helpful.

Trade-offs all the way down as ever.

Post reply on HN