Hey, thanks for raising this important use case.  Do you have any specific examples in mind you could point to?

I think the answer should follow easily from what defines a new scope.  New scopes get their own mini-stack frame created, and in that frame the context pointer can be saved like any other virtual register or 'g' property.  Of course, you know that an if block has its own scope inside it, and variables declared inside the if blocks are not in scope outside of that block.

You can create a new scope without an if statement, like this:

   func ScopeTest() {
        var varname = "outer"

        {
            var varname = "inner"
            fmt.Printf("varname = %s\n", varname)
        }
        fmt.Printf("varname = %s\n", varname)
   }

This prints:

   varname = inner
   varname = outer

It should follow that context variables declared in a block like that would have their state unwound when exiting the block.

Of course, any change in the way that statements are written brings with it change, resistance to change, and so on, so if you feel like this is jumping through awkward hoops, of course I can understand that position.  I feel it myself when I consider language changes a lot of the time.  The way I like to look past that is to make sure is that real-world examples don't end up /contrived/. It should be clear what is going on when written in the way it needs to be written to function as before, and that includes concerns around backwards compatibility.

So back to the initial question: can you give an example of somewhere that a unit test uses context in a way that you predict this proposal will make problematic?  I'd love to explore it to make sure, to make sure the proposal has lots of good examples.

Thanks,
Sam

On 2/21/24 2:34 AM, 'TheDiveO' via golang-nuts wrote:
Forgive me if I missed that, but what if I have multiple context vars, because I need to pass different (derived) contexts into different functions/receivers? Take unit tests as real-world examples.

On Wednesday, February 21, 2024 at 1:37:05 AM UTC+1 Sam Vilain wrote:

    Alright, well thanks for your input.

    I do think these questions can be answered; exploring the use
    cases in a proposal format should hopefully show that the impact
    of closures would not normally be an issue. Possibly the worst
    case is if you had a library to some external service, and at some
    low layer you're using a closure, well you might need to refactor
    that if you wanted to add cross–service tracing support.  But to
    be honest, it's probably better that the state you're depending on
    is captured in a struct instead of being scattered about loosely
    in a scope as with a closure.  And the common practice in Go is to
    return types that satisfy interfaces, not function references that
    you blind call.

    I think I will submit a proposal, but please don't take that to
    imply that I think you're "wrong, or mistaken". Your concerns are
    legitimate and the proposal should answer them cleanly.  In the
    proposal format, hopefully the "litigation", or more exploration
    of possible uses and abuses of the system, along with performance
    concerns, can be addressed.  I don't want to be dismissive of
    them, I just want to understand them.

    I had a brief look on the Golang issues in Github and could not
    find any prior proposals along this line using "context" and
    "dynamic scope" as search terms, so I'll submit this as a "new"
    proposal for now.

    Thanks again, and truly—thanks for responding, >100% better than
    people who just rolled eyes and marked thread as read.

    Cheers,
    Sam

    On 2/20/24 3:35 PM, Axel Wagner wrote:
    If I may quote myself:

    > And no matter which choice you make for the language - it means
    that if the programmers wanted the other, they'd have to jump
    through annoying hoops and get confusing and hard to debug problems.

    Having a mechanism to get one or the other semantic doesn't
    change the fact that it's easy to choose wrongly by accident, as
    long as the effect is implicit. In fact, the mechanism you
    propose (AIUI) seems extra confusing: Having a function value
    sometimes create a new dynamic scope and sometimes not, is weird
    and seems like a recipe for frustration.

    But really, convincing me isn't really the point, which is why
    I'm not super invested in litigating this (otherwise I might try
    to come up with realistic examples, for instance. Or explain
    further why I'm still not sure that this can be implemented
    efficiently). I'm just re-stating what, in the past, where the
    reasons why things like this have been rejected. In order to
    predict what I would consider a likely outcome of a proposal like
    this.

    If you think I am wrong or misunderstanding you, you can always
    file a proposal to get a more official response.

    On Tue, Feb 20, 2024 at 8:18 PM Sam Vilain <s...@vilain.net> wrote:

        On 2/17/24 1:32 AM, Axel Wagner wrote:
        On Sat, Feb 17, 2024 at 2:09 AM Sam Vilain <s...@vilain.net>
        wrote:

            I would argue that the matter can be simply decided by
            choosing the /calling/ stack, not the destination stack.

        I agree that this is *one choice*. But the point is, that
        *sometimes* you'd want one and *sometimes* the other. And no
        matter which choice you make for the language - it means
        that if the programmers wanted the other, they'd have to
        jump through annoying hoops and get confusing and hard to
        debug problems. So if you want to justify either choice, you
        have to make an argument that it is so overwhelmingly more
        common what people would want, that the cost of running into
        these problems is small enough to be justified by the benefit.

        I think that's a hard case to make.

        Alex, I agree that there are cases where you might prefer one
        versus the other.  However, you cut out the part of my reply
        where I pointed out it was possible to choose semantics by
        either returning a closure (context is the source stack) or a
        bound method (context is the destination stack).  Both of
        these values can be used interchangeably, as they have the
        same type, func ..., and so the caller does not need to care
        whether the function they are calling uses the calling
        context or the original context.  Were you not convinced by
        the argument?

        Sam

-- Sam

--
You received this message because you are subscribed to the Google Groups "golang-nuts" group. To unsubscribe from this group and stop receiving emails from it, send an email to golang-nuts+unsubscr...@googlegroups.com. To view this discussion on the web visit https://groups.google.com/d/msgid/golang-nuts/98dc6699-2b2e-48a8-bc4c-fc70406940e5n%40googlegroups.com <https://groups.google.com/d/msgid/golang-nuts/98dc6699-2b2e-48a8-bc4c-fc70406940e5n%40googlegroups.com?utm_medium=email&utm_source=footer>.

--
Sam

--
You received this message because you are subscribed to the Google Groups 
"golang-nuts" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to golang-nuts+unsubscr...@googlegroups.com.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/golang-nuts/5d888f02-9b01-4b5c-aedf-f75629ce0d02%40vilain.net.

Reply via email to