C++ Club - 167. Kona, C++26, Contracts, Reflection, Cpp2
Episode Date: November 23, 2023With Gianluca Delfino and other colleagues.Notes: https://cppclub.uk/meetings/2023/167/Video: https://youtu.be/_KYUUc6LJR8...
Transcript
Discussion (0)
Welcome to the club. This is meeting 167 and today is the 16th of November 2023.
The main topic is C++ committee meeting in Kona, which took place last week.
And there are quite a few news. This was the second meeting dedicated to sqlfast 26 and
that release is going to be a big one, looks like. There's still quite a few meetings that will
work on the features before the feature freeze, so I'm kind of hopeful
for more big features in C++ 26, but the stuff that's already been approved
is good. Let's see, this is the meeting report by Inbal Levy and her reports are pretty thorough.
The meeting was hybrid, 20% of attendees were the plan for C++ 26
ranges, P2760.
We discussed it previously, and it's quite an extensive to-do
list.
So that's fine.
The free function linear algebra interface has been approved for C++ 26.
So that's a biggie. It's P1673. And people are saying that it should be in the
standard and there are always libraries but many others say that
it's good to have this kind of functionality in the standard. Now this one we've seen before and
I'm glad that it got approved. It's pack indexing. And this paper
basically makes it possible
to refer to
the template
pack members
values by index,
which should simplify
the template
metaprogramming
chores.
I think I need any help I can get with template metaprogramming chores I think I need any help I can get
with template metaprogramming
I'm very glad that
somebody is trying to make it simpler
yeah
someone like always
like it always happens
some people said that it's not necessary
and we have all these
workarounds but I think this is very good.
My brain is very small, I need this place.
Yeah. Debugging support was approved. This is p2546 and it adds several functions like, is debugger present, a breakpoint.
Those are the functions that can be useful during debugging.
So yeah, that's a good addition.
Seems like a nice to have.
Probably wasn't too controversial.
Because all compilers had compiler-specific
functionality like that.
And it'd be good to standardize it.
So that's going to be in. Support for runtime format strings. This is a part of the std format
facility that stems from the excellent fmt library, so that's always good. Now, language progress. The review uses emojis to signify
the outcome of a discussion on a particular paper. Like, consensus to stop work is thumbs down,
thumbs up is advance the paper to core or other groups targeting C++26. The recycling emoji is consensus
to continue work in UG. The crossed circle is the issue is not a defect and yeah so that's convenient.
There's a whole section of papers destined to make C++ hurt less. That's always good.
Typeof and Typeof Unqualified. I hadn't looked into it. This is by Jeanne-Huidh Meneed.
Right, I think I saw that that wasn't approved because I think the reason was we already have it.
Like that meme, we already have typo at home.
And this is something that C didn't have, and now it has it.
And C++ had it for a long time, so I don't know. The other I wanted to look at.
Was it the erroneous behavior one?
Yes, yes.
P2795, erroneous behavior for uninitialized reads.
They did say explicitly that it's a different way
of addressing the issue from the paper
about zero initialization.
So they are looking at those papers sort of together.
And the comment says, erroneous behavior is a promising way to make EUB hurt less.
That said, there are significant wording issues in core.
This paper introduces the concept of erroneous behavior and uses it in one location."
So I think they want to continue working on this and that's good basically. So they will
have to address the issues of conflict between those two papers,
but I think we might even get it.
I think it's kind of having a meteoric rise.
I've seen it when you presented it last time and I have never heard of it before,
and some people like it. I didn't like it at the beginning, now I am kind of for it.
Even the committee is starting to like it. Look at this paper, p2973,
erroneous behavior for missing return from assignment that we discussed the
last time. The comment says, this is the second application of EB.
There was a discussion on making missing returns ill-formed instead, but the committee was
interested in using EB for this instead. So yeah, they must be seeing the advantages.
I mean, this small idea planted a seed in people's idea and people's brain and I think
it's maybe gonna flower.
Yeah, it's like, oh, we didn't even know that there was this way of solving UB. Trivial infinite loops are not undefined behavior.
P28.09 proceeded to core and the way they solved it was a bit unexpected, but I guess
that makes sense if you didn't want to make an infinite loop a special case. So now I think they added two bullet points to the wording,
the language wording.
Under this section, the implementation
may assume that any thread will eventually
do one of the following.
So the first added bullet point is call a function marked
no return.
And the second one, call std this thread colon colon yield.
So that would mean that this never returns, I guess.
And it just loops infinitely.
There was another function, std colon colon this underscore
thread colon colon yield underscore forever.
Good name, unabiguous.
So the proposed change would be instead of writing while true or the for with two semicolons,
which is currently undefined behavior, you would write std thread yield forever. Yeah, that's fine. Right. Ah, this one. Implication for C++.
Remember that? P2971. Walter Brown. Walter Brown's document. Paper, received thumbs down. It says,
there was a mild opposition and many neutrals, but also significant interest from a small but
vocal set of people. It is expected that this paper will come back with stronger
justification to increase consensus. And from the reddit thread I saw this quote
okay vocal minority return with your next proposal but just don't steal the
arrow operator for your niche purpose rather than something more valuable and
common like a terse lambda many have asked for and many more have asked for that than have ever asked
for implication.
But then what do you use for implication?
That is implication in a mathematical sense.
That's another problem.
First, we need to agree that we want implications.
And personally, at the beginning, this is another one that I didn't like at the beginning
and reading the paper, Walter Brown being the scholar that he is makes a lot of sense
and it could be useful in several contexts.
So yeah, I mean, I don't care about the syntax, but maybe one day I will get it, hopefully.
I have a feeling that had he chosen a different operator, it would have been better
received in the committee.
But what operator could he have chosen?
That's another curiosity.
What kind of arrow do you take? Well, it kind of has to be some sort of an
arrow. But yeah, I don't know. We'll see how it goes. Maybe he'll think of something. Right. Right, next.
There are lots of papers that remove sharp edges, which is like, yeah, well, we won't
go into each of those. Now for the features, again, features that make C++ nicer.
P1046 automatically generates more operators.
The author wrote a new draft paper, automatically generate operator arrow,
which narrows the scope of change and has strong support.
The paper is by David Stone
and it says the proposal follows the lead of operator Spaceship by generating rewrite rules
if a particular operator does not exist rewrites all kinds of other operators
that could be useful.
But apparently that was too much for the committee.
And the new paper will only deal with the operator.
How do you call it?
What do you call this? Oper do you call this operator? Arrow?
Arrow operator, I guess. It's not like interaction or something, no? No, I don't know. No, I don't think so.
This one's interesting. P1045. constexpr function parameters. They said that they will need an updated paper for this and
it's by David Stone again. So initially I thought what would that give us, like
declare constexpr parameter, but this is also for making template metaprogramming easier and bringing it
closer to normal programming. And this quote is very interesting. The section is called
No Shadow Worlds and it says, quote, Maltes Karupke wrote an article on language design and shadow worlds.
Shadow worlds are parts of language which are segregated from the rest of the language.
When you're stuck in the shadow language,
you find yourself wanting to use the full power of the real language.
C++ contains at least four general-purpose languages,
three of them shadow languages.
Regular C++, constexpr functions, templates, and macros. And so this before and after section,
just if we look at this, just this one paper, just introducing constex context function parameters results in so much simplification.
Like if you have a tuple instead of std get with index, you could just use subscript operator.
Instead of writing std true type, you could write true. Instead of std interval constant int 24, you could just write 24 and so on.
So, yeah, that was kind of a surprise for me.
And, yeah, it'd be interesting if it got adopted.
It does look very nice, this right column, to be honest. I wonder if there is some hidden implication
that are going to make something else explode.
I mean, it looks too good to be true.
Yes, exactly.
I'm sure the committee will find some obstacle
and maybe overcome it.
Right, so there was a whole section on the undefined behavior which has a subtitle remove it or at least
document it. This paper p2843 pre-processing is never undefined. Survey is all UB in the preprocessor and suggest solution for each.
Apparently there's strong support for this work, so that's always good. There was another
attempt at enumerating core undefined behavior and hopefully reviewing it. It's p1705.
And yeah, they say it's a start to allow us to revisit what is UB.
And the other paper p2234, consider a UB and if NDR audit. Maybe some of UB will become defined.
And some of it may need the compiler to complain because there is no diagnostic required,
that it's also something that they're discussing on many things.
So the plan for the next meeting which will take place in Tokyo for UUG is to continue
improving C++, focus on reflection and prepare for focusing on contracts. We might get the delete should have a reason paper p2573, which
means that any error message that says that particular function was deleted
would now have an explanation for that. But is this something that should have a reason?
Does it mean that it must have a reason that would certainly break present code?
No, that's probably gonna be optional, I would hope, because otherwise there'll be
lots of breaks. I mean they wouldn't do it otherwise. Now this one's interesting. P2826, replacement functions.
I think we looked at it before. It kind of stems from the absence of unified function call
syntax. It's by Gaj Parajman and it introduces a way to redirect a function call to a different function without a forwarding layer.
So we would just say if you have a function f, for example, and you would want another function g to forward to f,
you would say auto g equals ampersand f.
So that's a very interesting core feature and I'd be curious how it progresses.
Could be confusing, could be a little confusing.
Yeah, yeah.
The library had quite a few features approved And you will not believe this! Introduction of StutHive to the standard library had been approved after 24 revisions of the paper. I think that's
a record.
Is this the same person insisting about this? They didn't give up all these years. That's Matthew Bentley. He held fast and held strong and demonstrated incredible patience.
He kept reviewing paper and adding features as requested by the committee.
And it looks like it paid off.
I mean, it's a very interesting container. I'm sure the name will
cause a little bit of confusion but I mean probably would find use for it. Now interestingly
there was a paper P3001 StudHive and containers like it are not a good fit for the standard library.
And that paper got rejected.
That was by Jonathan Muller, Zach Lane, Bryce Lelbock and David Sankul.
Those are very high profile people.
Indeed.
And so, yeah.
It is listed in the section not supported or needs revision.
But I think if Steadhive has been approved, that ship has sailed.
Right.
Implication again.
Ah, implication library part tentatively approved.
So that was a library part, apparently.
Yeah, we'll wait for the next revision to review it.
There were small fixes and deprecations of various kinds. Matt Bentley wrote two documents in support for this Hive proposal.
One was called Outreach for Evidence of Container Style Use in the Industry and the second one
was Use of Stood List in Open Source Codebases.
I mean it does make a good point in those papers that people do write this kind
of container, maybe slightly different variations, but a lot of industries, they have some sort
of container like that, where you have these blocks that looks basically like a deck on
steroid. It could be useful i mean and uh you know
even if i may not use it um i'm not gonna complain that it's around no i'm happy that
we have something else an additional container yeah i like it i mean we have valeray and you
know nobody uses it you can if you don't like, you can just forget about it like Valarei.
Yep. Now this paper was
submitted and I think the committee wants to... I think I saw some votes and
there was strong consensus to continue working on it.
Sounds good. A lot of scientists use C++, might as well give them the tools.
There are quite a few third-party libraries that do it. It would make sense to have something like
that in the standard. Networking met for one session to review the latest revision of senders-receivers interface
for networking.
Basically, notably, ah, that's interesting, quote, notably, the group had a consensus
in favor of supporting only the senders and receivers model for asynchronous operations
and dropping the executors model from the networking TS.
Rest in peace, networking TS.
Rest in peace.
So that means that ASIO in networking TS is gone.
I think so.
I mean, I don't see, I think, at this point.
I mean, I'm not, you know, I used ASIO a lot.
I never really liked it that much,
but it was the only game in town.
It was fine.
You know, I would have been happy to have that in the standard.
We needed something in the standard.
As long as I get something that is serviceable, I'm happy.
I'm a bit upset that it is taking a lot of back and forth to to get whatever in yeah chris kolhoff um the author of asio demonstrated
angelic levels of patients dealing with various issues and rebasing networking
TS on new developments but I think he stopped doing that quite recently.
Understandably. And yeah without him as a champion doesn't make sense to keep
networking TS based on ASIO.
Right.
Now Reflection is back. Yay!
I'm so happy.
I was about to start a petition on change.org.
At last, it's moving forward.
There's a document called Reflection for C++26
by Wyatt Childers, Peter Dimov, Barry Revzin, Andrew Sutton,
Faisal Vali, and David van der Voorde.
I think Andrew Sutton was one of the initial champions for
Reflection and it's good to see his name back on paper about it.
It says, quote, this is a proposal for a reduced initial set of features to support
static reflection in C++. It might be a reduced set of features, support static reflection in C++?
It might be a reduced set of features, but I am happy. Yeah, me too. Basically, they decided to go with the value-based reflection instead of the
type-based reflection. There were two competing proposals, and they went with value-based.
A reflection operator will be caret.
There will be a number of const eval meta functions to work with reflections.
And constructs called splices to produce grammatical elements from reflections.
So it's like code generation in compile time, which is excellent.
The syntax is weird.
It's enclosed within square brackets, colon.
They say this proposal is not intended to be the end game as far as the friction and
compile time metaprogramming are concerned.
Instead, we expect it will be a useful core around which more powerful features will be
added incrementally over time.
Yeah, so, hooray!
I'm really happy about it.
Now pattern matching on the other hand is still dead and that's a pity. I think there is a table somewhere below maybe in this or in another post where it
goes what is the optimistic overview and what is the pessimistic overview?
That was not in the optimistic overview. The pattern matching was 2029.
Yeah, that's this table, the status of major C++ feature development. It says pattern matching,
no developments. Current target C++ 29, optimistic, same.
Which maybe does have some dependencies on something else that needs to get in.
There were several proposals that looked like stepping stones.
Yeah, some proposals that we discussed previously,
but yeah, the actual pattern matching is not
progressing.
Right, so contracts also got some developments. SG21 approved the paper with a new contract
syntax and the new contract syntax is the natural one. The double square
brackets are gone, contract checks are now spelled like this pre-parentheses, post-parentheses and contracts assert seriously.
That I understand they couldn't use assert obviously. In Herb Sutter's talk in CppCon 23, he presented a slide about Timo Dummler running a code search
to determine which of the potential assert names were not used in the existing code.
And obviously things like check, expect, verify, ensure, and so on were widely used, so they couldn't use those.
I just know quite a few weird ones, let's say.
Programmers like abbreviations, even if they don't make sense or sound bad.
So yeah, AssertExpra, CCAssert, GoAssert someone proposed, which would be like super confusing.
It would be.
ContractAssert, yeah. ContractAssert without underscore. Cpp assert as opposed to just
assert. Dynamic assert, that's also confusing. Std assert with underscore, no. Anyway, it
looks like they didn't have a really good option and
they could have made contract
pre-contract post but
I guess that would be
would have been two of the goals anyway
also
that's a match yes we got something
you know
I'm not going to sweat
over this as long as we get
contracts in 26, it's fine.
It's not like the rest of C++ naming is brilliant.
Just look at coroutines.
But yeah, that's an interesting development.
And if you remember the paper we looked at, which I thought was like a wildcard unrelated
paper that summarized everything, I now think that that development and provided sort of a
running total of everything contract related. At least that's my read.
Right. Did I read it correctly that Reddit is happy?
Reddit is very happy about reflection.
Someone posted, fuzzy feeling when I see progress being made on reflection.
Peter Dimov says, I know, right?
Nice.
Yeah, that's nice.
That's going to enable lots of interesting possibilities.
Someone says, keep at it, fellas. The world is waiting in anticipation.
There's this grumpy dude which says, as if the language wasn't complicated enough,
and they got downvoted.
Well, this guy is grumpy, it's worse than us. Someone replies, don't worry, people have been working on this for centuries, it's going
to be perfect.
Right.
There were three papers from the October mailing that I wanted to look at briefly. The
first one was by Steve Downey. It's p2988, revision 0, and Peter Summerlad,
also co-author. It's stdoptional of tref, which is... they really went there, they must be really brave.
Because that was the only thing that never got any consensus,
because of the assignment thing, if you remember,
part of the committee wanted assignment to be reciting of the optional,
and part was of the opinion that assigning to an optional of tref
would transparently modify the value that was referenced.
Quote, we propose to fix a hole intentionally left instead optional. An optional overall reference such that the post condition of
onAssignment is independent of the engaged state, always producing a rebound reference,
and assigning a u to a t is disallowed by static assert if a u cannot be bound to a tref. So the example is of a function findcat with a name which returns a pointer that can be
null. And this traditional way is if cat is not null, then you do something with the dereferenced cat. And after this,
you would say stdoptional cat ref cat equals find cat, which would give you either an empty
optional or a reference to a cat that was found, and that would enable you to call a member function of the stdoptional
and then. So you would just say cat.andthen do it, which would automatically deal with the
empty optional. So this proposal also adds and then? No, I think that's already in. It's already in?
Yeah, I think that's even in C++23.
We didn't get those for std expected,
but we did get those for std optional
as far as I can remember in C++23.
If you forgive me for saying this,
I would have expected in std expected. I would not have
expected in optional. I think they were just late for the train. Now the next one is, we've seen
that before, it's called unified function call syntax. It's by Herb Sutter. He also
demonstrates his bravery here because UFCS, Unified Function Call Syntax, had been discussed
lots of times. And I think it was abandoned because they decided that it was a dead end and there wouldn't ever be agreement on this.
And now...
There's a lot of people that...
Yes, I don't know if you want to say that.
Some people are actually for it, but...
It's very difficult to...
It would have been very difficult to implement as it was proposed.
But Hubsata here proposes something close, but not the entire thing.
Much like Reflection, it's a workable solution that would improve life of C++ developers,
but not entirely in the way that was discussed
previously. In the abstract, he says that the lack of single call syntax that can call both member
and non-member functions causes real problems in C++. He precedes this with the phrase, we have new information since the previous discussion.
And then he says, it makes writing generic code harder and makes libraries harder to use and
compose. It makes tools such as IDE autocomplete less useful for C++ code because they work well for the member function syntax but not for the
non-member function syntax. And then he lists new points. It continues to lead to workarounds,
including in the standard library, such as overloading operator pipe for ranges.
That means he didn't like the operator pipe override syntax.
I think he's just saying that it would have been unnecessary if we had uscs.
How would it look like if you have to pipe ranges into other ranges?
I think it would be just dots, lots of dots, dot calls. The quote continues,
or providing non-member versions of a limited set of common functions that cannot be made members
on built-in types such as arrays like std begin. Another new point, it continues to lead to
repeated language evolution proposals for narrow features, such
as extension methods and the other papers currently proposing operator pipe greater
than, which sort of looks like an arrow if you squint enough.
Yeah.
What was that for?
Was this a massive... That was exactly for the surrogate universal function call.
The composition of functions.
It was by Colby Pike and Barry Revzin, and it was called a pipeline rewrite operator,
which would provide you with pipeline-like function calls.
Right.
Which was implemented by using pipe operator for ranges.
So that's another workaround that does the same thing,
only with a different operator.
And the third new point, he says,
these workarounds and language evolution proposals would not be needed
if x.f call could call f of x.
By being inherently left-to-right workarounds and proposals,
the new experience information provides further evidence of which current call syntax is important to make UFCS capable.
And here is a zinger.
An experimental implementation of this proposal is available in
the CppFront compiler. Of course. So yeah, we'll discuss that later, but this I think is undeniably a good thing that he can show his work and prove that this actually helps.
Basically, this says that member-style function call would find non-member functions,
but not vice versa. The previous UFCS proposal did it in both directions i think so if you called
a free function and a member function was available with the same sort of functionality
and signature it would find it and call the member function This will not be in this proposal because it's probably too disruptive.
And I think that was one of the reasons, at least,
that the initial proposal didn't go well.
But this one, I think if it succeeds,
this would be really good.
I mean, it would make it, I think, more difficult to actually sometimes understand
what is going on if somebody introduces some extra function that would then be automatically called.
Yeah, it would add another implicit behavior to C++. Indeed. It would be more difficult for us
humans to understand exactly what's going on. But I do recognize that for generic programming,
that would be a blessing. So that said, I understand both sides of the argument. I'm
not sure what personally I would argue for here. I know very smart
people arguing for it, so there must be good reasons. I've read skating papers against
it, which also makes sense. It's a tough one. I think Bjarne was the one who proposed the initial UFCs. And I think he did say at some
point that basically there's no way it's going to pass. So it'd be interesting what he says about
this one. And the next paper I looked at was C++ should be C++ by David Sankel, p3023. And that's an interesting one.
It's like a bit of a rant, I'd say. Quote, over the past few years, the C++ community
has dealt with scandals, calls for a so-called successor, and threats of anti-C++
safety regulations. All this is on top of the ordinary committee stress of competing designs
and harsh prioritization. In a time like this, it's easy to dwell on our troubles or take fiercely
defensive positions. This paper reframes the unconstructive narratives and argues that the committee's real opportunity is to improve people's lives
will show how this outlook leads to guidance on committee participation, direction and responsibilities
This paper is harsh, but I liked the overall message
I invite you to read it in full, it's pretty short This paper is harsh, but I liked the overall message.
I invite you to read it in full.
It's pretty short.
And there were quite interesting paragraphs,
like the social aspect.
People use C++ to define their personal identity and purpose.
Resulting emotional baggage makes recent discussion difficult.
I think that's very true.
If you feel territorial about whatever you do, your code or your proposals,
then it's really hard to move from that position, even if it doesn't make sense. And this applies in all sorts of fanboyism and whenever you have feelings reign over logic
then obviously reason won't apply and won't sway any one's mind. Another bullet point, he says,
tribalism creates skepticism of outgroups.
Good ideas are rejected on the basis of where they came from.
And the takeaway is, quote,
being part of C++ is not a vehicle for life fulfillment.
That's a bit harsh.
I think for many people it's a valid
life goal
to improve C++
but maybe
it's worth thinking of
dialing this down a little bit
yeah yeah you can get
fulfillment out of this
but yeah I mean this is
I like this paper point of view is trying to get back to a more
recent discussion. And yeah, I think, you know, the community could benefit from listening
to these kinds of arguments a little bit more. Yeah. So yeah, he raises lots of very good points, and I invite you to read this
document. Now really quickly, there was a video of Pianos Trostrup delivering Save C++ in CppCon
2023. It's an updated talk that we discussed previously, So I think it's the latest version now.
And also, there was a document that I think was discussed in Kona by Piane called Concrete Suggestions for Initial Profiles, profiles where he outlines what his focus on type safety would result as a way of defining
new safety profiles and which ones he thinks should be the initial ones.
Now this video of Herb Sata on Cpp2 in CppCon 2023,
I have words about it. I mean not a fan, to be honest.
And of course, who am I to criticize? I just, I don't do anything, I just criticize.
But still, there's a follow-up post on Herb's blog. And he says, safety for C++,
50 times more safety for C++,
10 times more simplicity for C++.
Round numbers and slogans are a red flag for me.
They usually don't mean anything.
In the beginning of the talk,
he asked the audience,
how many of you would be interested
in seeing C++ get significantly simpler
and type memory safer?
It's a bit of a low trick.
I wouldn't imagine anyone be against that.
So I'm not a fan of this style of presentation.
Because then it sounds like you're not against his idea.
You're against making things simpler and safer.
Exactly. Especially given that Herb's solution is not actually C++.
He invoked the Beatles song again. All you need is class.
Then he repeats again. This is 100% C++.
And then proceeds to show non-C++ code.
Often invoking Bjarne's name.
Was it for validation?
Yeah, it does.
As Bjarne says.
As Bjarne did with his C front.
So I did with C C front, so I did with CppFront. He also says that Swift is a typescript for Objective-C, which is you would have to squint really hard to come to that conclusion. Again, he says that it's
just a personal experiment and it's fine, but then he tells the audience that the TypeScript way or CPP2 is the only
way forward for C++ because people say that gradual evolution is not enough and we can't
break compatibility like Python 3 did. So this solution, my solution, is the only one that's possible.
Yeah, I'm so pessimistic and cynical.
I shouldn't be, probably.
For all I know, CPP2 could be our future.
Or it could be a way to trailblaze new C++ features like UFCS,
for which I'm really grateful to Herb.
But to me, this whole talk feels like an ad.
And that's... I don't like this style.
Agreed.
Reddit says, quote,
Strohstrup's keynote, specifically the last point in the slide
where it mentions that successor languages are welcome,
but they are not C++,
is relevant here.
No matter how much you try and sugarcoat it
as TypeScript for C++.
So, yeah,
I'm kind of glad it progresses and I'm curious to see the progress, but to frame
it as the only way forward for C++ is a bit disingenuous, I think.
Almost out of time and I'll leave you with this interesting thing that I found.
Omar Shahin posted, I think it was back when Twitter was a thing,
quote, I came across this great document at Microsoft on how to answer the question,
how are you doing? I like a structured way to share this. And the document says,
it uses emoji to indicate your mental status. The sun emoji, normal capacity, focus,
and or well-being. Partly cloudy, slightly reduced capacity, focus, and or well-being.
Cloudy, significantly reduced capacity, focus, and well-being.
Storm, severely reduced capacity, focus, and well-being.
And a Friday emoji, temporarily offline to replenish my capacity, focus, and well-being.
So, as we all need to care about our mental state and our jobs can be very stressful and taxing,
I thought that was a good way to indicate,
even to yourself,
to take stock of how you're feeling today.
So, yeah, I thought that was very good.
Of course, the proper British way to reply to this question is, I'm all right, thanks.
Or yes yourself without even listening to what the other person said.
Yep.
Cool.
So that's it for today.
Thank you very much for coming and I'll talk to you soon.
Bye bye.
Thank you.