Skip to content

Conversation

@voldenet
Copy link
Contributor

This pull requests adds documentation for Promise.andthen and Promise.orelse methods, since they're really useful.

@voldenet
Copy link
Contributor Author

I'm not sure if these methods should be documented in the current form - they could get changed, so they get result/cause instead of the promise, which is not needed for anything.

@librasteve
Copy link
Contributor

maybe wise to also add two tests to ROAST - then the behaviour is official?

@FCO
Copy link

FCO commented May 29, 2025

Here is a suggestion on what it could do (not a suggestion on how to do it): https://glot.io/snippets/h7sotvz66u

@raiph
Copy link
Contributor

raiph commented May 29, 2025

Promise.andthen and Promise.orelse methods, since they're really useful.

.oO ( Did you forget a .new? )

(In other words, you must mean Promise.new rather than Promise, and I've decided to be explicit about that wrinkle in this comment in case anyone reading it is fairly new to Raku.)

I'm not sure if these methods should be documented in the current form - they could get changed

(Afaik) we are only supposed to document roasted behavior. Has that changed? (I'm asking about the general principle, regardless of whether any given current Rakudo behavior is or isn't roasted.)

I will assume that their current behavior is not roasted based on @librasteve's comment. (If that assumption isn't warranted then please adjust your understanding of the rest of this comment.)

they get result/cause instead of the promise, which is not needed for anything.

That sounded surprising, so I reflected for a moment.

One thing that immediately jumped to mind is that, in theory, and presumably potentially occasionally in practice in a future Rakudo run of a program, if not already, a new Promise instance might already have been kept or broken by the time the andthen/orelse method runs.

(I don't mean the code passed to the andthen/orelse method. I mean the andthen/orelse method itself.)

Presumably the foregoing does not matter -- it still all works as intended, right?

(I'm just asking y'all to check my home work/thunk after the mind jump I began this paragraph with. TIA.)


Another thing that jumped to mind is that the proposed change would presumably make andthen/orelse blocking (synchronous) methods unlike the current non-blocking / asynchronous behavior.

Presuming I'm right then that would surely be a fundamental change, right? Furthermore, I presume it would also be a breaking change for a reasonable definition of "breaking", right?


If we presume that the current behavior is not roasted (see above), and, furthermore, that that reflects the current behavior not being "spec'd" (in the last decade or so sense of "spec'd"), then that does have some weight on the side of making what I am presuming is a fundamental and/or breaking change.

However, I would still expect, or at least hope, that any such change would be discussed further before taking any action like adding roast tests for this or that behavior.

It would make sense to me for initial discussion to occur here. If we get consensus here, and perhaps on IRC or whatever, that, in retrospect, the current behavior makes sense, then we can decide whether to roast it as is, and document it as is, or instead just open a problem-solving issue.

A similar notion applies if we get consensus that the current behavior does not make sense, and that making it blocking makes sense. (I will say right now that making these methods block doesn't yet make sense to me as I write this sentence. Especially if that breaks code out there -- but even if it doesn't. But I'm getting older and am ever more aware that I could easily be making some mistake, basic or subtle! 😊)

If instead the current behavior is roasted, well, a similar notion to the above still applies. I'd expect discussion and development of consensus.


A final set of thoughts jumped to mind after the above and is covered in the rest of this comment.

(All of this jumping and reflecting on the jump described above, plus what follows, took about one second, literally. It's then taken me in the order of an hour to linearize it into words. I love and hate my brain/mind in equal measure.)

This final set of thoughts was about what andthen is doing, and what the words "and then" suggest.

(Actually, the initial thought was my first thought as I read the title of this issue before reading any of its content. The title -- Add "andthen" ... to Promise.rakudoc -- juxtaposes "andthen" and "Promise", which instantly sets things up for confusion.


The andthen infix operator has relatively obvious sequential / synchronous semantics. The LHS is evaluated, and then ("and then"), based on the result of the LHS, the RHS may be evaluated.

The exact same explanation of the overall semantics would work fine for orelse: the LHS is evaluated, and then ("and then"), based on the result of the LHS, the RHS may be evaluated.

Note how it's "and then" regardless of whether the operator is andthen or orelse. That's because the "and then" is just how code executes in most Raku code, and indeed most code in any programming language. One thing happens and then another and then another, sequentially.


To a degree the andthen Promise method is like the foregoing.

The LHS is evaluated, and then ("and then") the method is invoked. The "and then" I just wrote has nothing to do with the exact nature of the particular method. The method could be, for example, .orelse or .say or .my-method.

My point here is that .andthen means something like "queue some code that will await the Promise instance that's my invocant -- but do not await me, the method you just called". This is entirely different semantics from the andthen infix operator.


Thank you for your patience with my verbosity!

P.S. And maybe imagine what it's like to deal with me if I'm speaking. Consider the following:

Someone says a single sentence, like Add "andthen" and "orelse" to Promise.rakudoc.

In response all of the above -- plus a vast array of other thoughts I have not written about, something like a thousand times as much -- nearly simultaneously explodes in my brain/mind in less than a second.

This is all very off topic of course, but it's the kind of thing that has torpedoed my personal relationships with pretty much all friends, family, and even my wives.

Thank goodness for a community that can cope with my verbosity and off topic writing. I hope! Much love to any and all patient enough to read this far. 💚

@FCO
Copy link

FCO commented May 29, 2025

Another thing that jumped to mind is that the proposed change would presumably make andthen/orelse blocking (synchronous) methods unlike the current non-blocking / asynchronous behavior.

The block passed to andthen is already only called after the promise is kept, so it's always immediate. Right?

@voldenet
Copy link
Contributor Author

we are only supposed to document roasted behavior

That makes sense, these docs will have to wait until this is specified.

The rest of the comment is about the issue rakudo/rakudo#5892

.oO ( Did you forget a .new? )

I was trying to not write long blocks of code in the title, but I promise that the description has proper code.

Another thing that jumped to mind is that the proposed change would presumably make andthen/orelse blocking (synchronous) methods unlike the current non-blocking / asynchronous behavior.

The continuation is always executed after the Promise is resolved, so the behavior of those two methods would not significantly change. The biggest change is that the original Promise would not be accessible anymore, however already documented then method covers advanced use cases. My initial need was to have .then and .catch known from promises in javascript to allow building chain of callables in a simplified way, so upon finding undocumented (but working) methods, I thought it'd be good idea to describe them.

(Actually, the initial thought was my first thought as I read the title of this issue before reading any of its content. The title -- Add "andthen" ... to Promise.rakudoc -- juxtaposes "andthen" and "Promise", which instantly sets things up for confusion.

I have used the already existing methods, so I didn't think much about how they're named, but I agree - these names could be more unique.

@raiph
Copy link
Contributor

raiph commented May 29, 2025

@FCO

The block passed to andthen is already only called after the promise is kept, so it's always immediate. Right?

I was presuming that, currently, it's always immediately, if by "it" you mean return from .andthen. But @voldenet wrote:

I'm not sure if these methods should be documented in the current form - they could get changed, so they get result/cause

I was interpreting "they" as referring to these methods (not the block they're passed) and "get result/cause" requiring awaiting the promise before .andthen returns. So it'll no longer immediately return, right? (If not, I'm confused. Well, I'm confused anyway, but hopefully you see my point!)

@FCO
Copy link

FCO commented May 29, 2025

But the .result and .cause do not need to be called when the method runs, but, if it's implemented using .then, it could do something like:

method andthen(&block) {
    $.then: -> Promise $p {
        block $p.result if $p.status ~~ Kept; # it's only called inside the then's block. So, only after kept or broken (kept on this case, because of the if)
        # treat catch case...
        ...;
}

@raiph

This comment was marked as resolved.

@voldenet
Copy link
Contributor Author

@raiph
To clarify - I didn't mean that andthen should block. The &code parameter inside it should get different parameters.
See the original issue about it: rakudo/rakudo#5892

@FCO
Copy link

FCO commented May 30, 2025

What I think was meant by:

I'm not sure if these methods should be documented in the current form - they could get changed, so they get result/cause instead of the promise, which is not needed for anything.

Is that the block passed to andthen ($promise.andthen: { this block }) would receive the .result instead of the promise object.

On .then, it's important to the block to receive the promise object, because it needs to be able to test its state.

On the other hand, if the block passed to andthen is running, the status is already known, it's Kept, otherwise it wouldn't run the block. So we don't need the whole promise object be received by the block, only the result is enough.

@raiph

This comment was marked as resolved.

@coke
Copy link
Collaborator

coke commented Oct 4, 2025

Can someone please summarize the current state of this PR?

@coke coke self-requested a review October 9, 2025 17:40
@arkiuat
Copy link
Contributor

arkiuat commented Oct 20, 2025

Can someone please summarize the current state of this PR?

My first impression on reading it over is that the behavior is underspecified and that changes in the documentation are on hold until tests are added to roast, but I don't see any linked or open issues or PRs on roast related to this.

It seems that adding such tests is also on hold, pending the outcome of the discussion in issue rakudo/rakudo#5892

@coke coke marked this pull request as draft October 21, 2025 22:47
@coke
Copy link
Collaborator

coke commented Oct 21, 2025

Converting to draft, looks like we have decisions to be made elsewhere.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants