Cpp2 should not use ==
to express constexpr
#959
Replies: 4 comments 7 replies
-
I totally agree. I also find the |
Beta Was this translation helpful? Give feedback.
-
Agreed, thank you for taking the time to express all these worries so succinctly
On 28 January 2024 23:00:20 Walter ***@***.***> wrote:
In short, reusing == as a way of defining that a function or variable is constexpr or consteval is a neat idea, but ultimately creates way more issues than it solves. We should not use == for this purpose, and should use keywords to color the types of these functions and variables. I've seen similar sentiments in other places too.<#714 (comment)>
I've seen this discussed a bit before, but I wanted to make a full argument against it and give room for discussion about it. I have skepticism about other areas I've seen using == for assignment, but I'm keeping my scope focused on this because I think it's most important here. Please let me know if I'm mistaken, unaware of recent developments, could look at it a different way, etc.
1. It's significantly divergent from the common use of ==
In every programming language I've ever used, == has meant one thing: An equality test. If you ask any programmer in the world what == means, they will give you that answer, no extra context needed. It's one of the most ubiquitous operators ever, and exists in almost every higher-level language.
That's a powerful thing. It means that basically no teaching has to be done whenever a programmer sees ==... except for cpp2. A programmer will look at cpp2 will be confused by why there are equality tests where it appears definitions should be occurring. In cpp2, in specific contexts, it is not an operator, it does not test equality, and it does not return a boolean. All expectations have been broken. There is now an entire class of cases where == does not mean what every programmer would expect it to mean.
2. It's role in the syntax is non-standard
When we write this code:
myfunc1: (x: int) -> int = {
...
}
Everything between the ":" and the "=" is the type of the thing being defined. Nothing before or after those two symbols alters the type declaration of this function. This is true for every kind of declaration or definition... except for a constexpr function:
myfunc2: (x: int) -> int == {
...
}
In this case, == modifies the type. The assignment operator becomes part of the type, and now myfunc1 has different type than myfunc2, and the two cannot be exchanged for one another. A new special case for type declarations has been added to the language.
3. It's unfriendly to documentation
If myfunc1 and myfunc2 have different types due to = vs. ==, how should we write the type? If I'm writing documentation for my code, or creating an intellisense tool for cpp2, how to I denote that this function is constexpr? Do I use cpp1 keywords that never show up in cpp2? Do I just write "=="? How do I write out this type information to communicate it to others?
myfunc2(x: int) -> int ==
x: Input value for the func
returns: Result of the calculation
4. It doesn't cover expressing both constexpr and consteval
I'll assume I don't have to explain why both are useful.
I've seen some chatter about possibly defining === as consteval<b589f5d#commitcomment-128465809>, but this is... frankly horrifying to me. It is again divergent from typical uses (see javascript), and again doesn't read like it's making a statement about types, code contracts, and enforced compile-time evaluation. At that point, how about we just turn all of our function/variable coloring into unrelated symbols we shove into the assignment operator! Let's make a consteval static member function defined as x: (i) ===% { ... }, and a constexpr virtual final member function into y: (i) ==$& { ... }. /s
5. It's not very extensible
If == remains the defacto constexpr tag for values and functions, the only place we can use it without causing further immense confusion or complication is during assignments. There is no possibility for defining a parameter to be constexpr, for defining a block consteval, or for making a consteval if statement. Cpp1 was able to reuse its keywords to add in all this new functionality that they maybe hadn't anticipated on first run, but without that sort of reusability, we're setting ourselves up to either not be able to express those things, or find weird new ways that don't connect concepts/keywords.
Conclusion
We should just use a keyword in the type declaration.
There's not really a better way of going about this. We are explicitly coloring our function or variable when we say that it's constexpr or consteval, and that's okay. We can bikeshed on what keywords we want to use and how they're defined, whether it's constexpr, consteval, const, consteval? const!, etc. etc.. Regardless, we should explicitly declare our intent in the type definition with keywords. It helps us communicate clearly what it is we're doing, it doesn't make special cases to reuse already well-defined operators, it's familiar, and it doesn't constrict us to just assignment contexts in the future if we want to expand the language.
—
Reply to this email directly, view it on GitHub<#959>, or unsubscribe<https://github.com/notifications/unsubscribe-auth/AALUZQKJ2A2QNJOEOQLUNWDYQ3KADAVCNFSM6AAAAABCOQL7NWVHI2DSMVQWIX3LMV43ERDJONRXK43TNFXW4OZWGE2DKMBXGI>.
You are receiving this because you are subscribed to this thread.Message ID: ***@***.***>
|
Beta Was this translation helpful? Give feedback.
-
I upvoted your post because I mostly agree with it, specially on the toolability and extensibility part, but I also feel like I should mention the things I like from the current alias syntax, which is not that bad yet nor is it that confusing once you use it for a bit (YMMV):
I also fail to see an alternative which doesn't involve spelling |
Beta Was this translation helpful? Give feedback.
-
I don't buy 1. argument. Let me show you counter example in your own post. All programmers know that Also, I don't feel 4. constexpr and consteval as something great at cpp1. I have feeling that one of them not needed. I tried to search, and get idea that constexpr MAY be comptime, and consteval MUST be comptime and CANNOT be runtime, so, I'd say bye to constexpr, you don't guarantee anything, almost like old good inline... On the other hand, consteval I just don't fully understand why it's needed, they say it will be good for reflection, but I have feeling that cpp2 will have better tools for reflection. |
Beta Was this translation helpful? Give feedback.
-
In short, reusing
==
as a way of defining that a function or variable isconstexpr
orconsteval
is a neat idea, but ultimately creates way more issues than it solves. We should not use==
for this purpose, and should use keywords to color the types of these functions and variables.I've seen this discussed a bit before, but I wanted to make a full argument against it and give room for discussion about it. I have skepticism about other areas I've seen using
==
for assignment, but I'm keeping my scope focused on this because I think it's most important here. Please let me know if I'm mistaken, unaware of recent developments, could look at it a different way, etc.1. It's significantly divergent from the common use of
==
In every programming language I've ever used,
==
has meant one thing: An equality test. If you ask any programmer in the world what==
means, they will give you that answer, no extra context needed. It's one of the most ubiquitous operators ever, and exists in almost every higher-level language.That's a powerful thing. It means that basically no teaching has to be done whenever a programmer sees
==
... except for cpp2. A programmer will look at cpp2 will be confused by why there are equality tests where it appears definitions should be occurring. In cpp2, in specific contexts, it is not an operator, it does not test equality, and it does not return a boolean. All expectations have been broken. There is now an entire class of cases where==
does not mean what every programmer would expect it to mean.2. Its role in the syntax is non-standard
When we write this code:
Everything between the "
:
" and the "=
" is the type of the thing being defined. Nothing before or after those two symbols alters the type declaration of this function. This is true for every kind of declaration or definition... except for a constexpr function:In this case,
==
modifies the type. The assignment operator becomes part of the type, and nowmyfunc1
has different type thanmyfunc2
, and the two cannot be exchanged for one another. A new special case for type declarations has been added to the language.3. It's unfriendly to documentation
If
myfunc1
andmyfunc2
have different types due to=
vs.==
, how should we write the type? If I'm writing documentation for my code, or creating an intellisense tool for cpp2, how to I denote that this function is constexpr? Do I use cpp1 keywords that never show up in cpp2? Do I just write "==
"? How do I write out this type information to communicate it to others?4. It doesn't cover expressing both
constexpr
andconsteval
I'll assume I don't have to explain why both are useful.
I've seen some chatter about possibly defining
===
asconsteval
, but this is... frankly horrifying to me. It is again divergent from typical uses (see javascript), and again doesn't read like it's making a statement about types, code contracts, and enforced compile-time evaluation. At that point, how about we just turn all of our function/variable coloring into unrelated symbols we shove into the assignment operator! Let's make a consteval static member function defined asx: (i) ===% { ... }
, and a constexpr virtual final member function intoy: (i) ==$& { ... }
. /s5. It's not very extensible
If
==
remains the defacto constexpr tag for values and functions, the only place we can use it without causing further immense confusion or complication is during assignments. There is no possibility for defining a parameter to be constexpr, for defining a block consteval, or for making a consteval if statement. Cpp1 was able to reuse its keywords to add in all this new functionality that they maybe hadn't anticipated on first run, but without that sort of reusability, we're setting ourselves up to either not be able to express those things, or find weird new ways that don't connect concepts/keywords.Conclusion
We should just use a keyword in the type declaration.
There's not really a better way of going about this. We are explicitly coloring our function or variable when we say that it's constexpr or consteval, and that's okay. We can bikeshed on what keywords we want to use and how they're defined, whether it's
constexpr
,consteval
,const
,consteval?
const!
, etc. etc.. Regardless, we should explicitly declare our intent in the type definition with keywords. It helps us communicate clearly what it is we're doing, it doesn't make special cases to reuse already well-defined operators, it's familiar, and it doesn't constrict us to just assignment contexts in the future if we want to expand the language.Beta Was this translation helpful? Give feedback.
All reactions