[SUGGESTION] Typed Expressions; generalized constructors, UDLs, unnamed variables and functions #631
Replies: 55 comments
-
Also this suggestion won't add any new syntax to the language, it uses the existing syntax |
Beta Was this translation helpful? Give feedback.
-
In a nutshell:
|
Beta Was this translation helpful? Give feedback.
-
I like the other suggestion better I think. Would this be context-free?
…On Sun, 21 May 2023, 17:50 Sadeq, ***@***.***> wrote:
In a nutshell:
- ID : TYPE would be a declaration if it's at the start of a
statement.
- We use ID : TYPE to specify the type of a declaration.
- EXPR : TYPE would be a typed expression if it's not at the start of
a statement.
- We use EXPR : TYPE to specify the type of an expression.
- : TYPE = SOMETHING would be an unnamed variable.
—
Reply to this email directly, view it on GitHub
<#463 (comment)>,
or unsubscribe
<https://github.com/notifications/unsubscribe-auth/A2KJHTTIO3C2EI2JIBJYF7LXHICATANCNFSM6AAAAAAYJLD2PA>
.
You are receiving this because you are subscribed to this thread.Message
ID: ***@***.***>
|
Beta Was this translation helpful? Give feedback.
-
Thanks. Yes, It would be context-free, because the behaviour of // It's a declaration.
something: Type;
// It's a typed expression.
call(something: Type);
// It's a parameter declaration.
call: (something: Type) = {} |
Beta Was this translation helpful? Give feedback.
-
Briefly: // `A` is a declaration.
A: Type = 0;
// `B` is a declaration.
// `X` is a typed expression.
B: Type = X: Type; |
Beta Was this translation helpful? Give feedback.
-
A typed expression can subsume a UDL better than UFCS. Let's consider the type
As you can glean from the comments, Just switch from having a
For an alias template (e.g., to replace the UDLs |
Beta Was this translation helpful? Give feedback.
-
From our experience at https://github.com/mpusz/units, which has quantity references (e.g.,
As seen from "Unit-specific Aliases", a typed expression isn't thus affected. See also UDLs vs Quantity References for many major pain points against UDLs.
|
Beta Was this translation helpful? Give feedback.
-
I expanded on the quote above. Allow me to expand the summary's table:
As you you can see, a typed expression is the best in almost all aspects. |
Beta Was this translation helpful? Give feedback.
-
@mpusz You may be interested in looking at this. In particular, the 3 comments above. |
Beta Was this translation helpful? Give feedback.
-
@JohelEGP Thanks for explaining about indirect construction of UDL and UFCS, I wasn't aware of it.
I changed the example to have typed expressions: // simple numeric operations
static_assert(10:km / 2 == 5:km);
// unit conversions
static_assert(1:h == 3'600:s);
static_assert(1:km + 1:m == 1'001:m);
_s: = 1:s;
kmph:type == decltype(1:km / _s);
// dimension conversions
static_assert(1:km / 1:s == 1'000:m / _s);
static_assert(2:kmph * 2:h == 4:km);
static_assert(2:km / 2:kmph == 1:h);
static_assert(2:m * 3:m == 6:m2);
static_assert(10:km / 5:km == 2);
static_assert(1'000 / 1:s == 1:kHz); For this to work, I think that unit types may have an extra template parameter to indicate the prefix. For example |
Beta Was this translation helpful? Give feedback.
-
Don't worry. The library has taken care of all that. |
Beta Was this translation helpful? Give feedback.
-
From commit 0982b8e:
That works well for named declarations. Commit 1090a31 also enabled
|
Beta Was this translation helpful? Give feedback.
-
Good point. So it would be like to pronounce:
In general:
|
Beta Was this translation helpful? Give feedback.
-
Assignment to Typed Expression: // `A` is a declaration.
A: Type = 0;
// `B` is a declaration.
// `A` is a typed expression.
B: Type = A: Type;
// It's equal to:
// = Type::operator=(out this, B).operator=(something)
C: Type = B: Type = something;
// (2 + 2): Type = something;
// x++*.f(): Type = something;
// It's equal to:
// = Type::operator=(out this, something)
D: Type = : Type = something; It's can be safe to disallow assignment in case 3, because it's rvalue: // ERROR `B: Type` is rvalue.
C: Type = B: Type = something; I'm going to categorize them. They all have a similar syntax but semantically they are different in this way:
Unnamed Variables are a special Typed Expression.So we can think about it that Unnamed Variables are a special Typed Expression. This is a generalized syntax for both of them: (something: Type = value) Unnamed Variables don't have the After that, they would be categorized in this way:
This categorization will reduce concept count. |
Beta Was this translation helpful? Give feedback.
-
I'm trying to find a general rule to reduce concept count. Also Unnamed Functions could be somehow a special Typed Expression if Cpp2 would support issue suggestion #391 titled "Statement-expressions, (something: (args) -> Type = { /*statements*/ }) Unnamed Functions don't need the After that, they would be categorized in this way:
I have to clarify about the syntax (described above) of typed expressions:
So this example won't be allowed: // WRONG! This typed expression applied to a statement block.
{ /*statements*/ }:(args) -> Type |
Beta Was this translation helpful? Give feedback.
-
I examined
So type composition within declarations would be like this: A: type = { /*declarations*/ }
B: type = { /*declarations*/ }
function: <T> (a: A*T, b: B*T) -> A*B = { /*statements*/ }
X: type = { /*declarations*/ }
variable: <T> X*T = /*value*/; That's because Briefly, it means that:
|
Beta Was this translation helpful? Give feedback.
-
That's interesting. Also C23 has
I like how Cpp2 already has |
Beta Was this translation helpful? Give feedback.
-
I agree that's not intuitive from human-language point too. In cpp2 |
Beta Was this translation helpful? Give feedback.
-
|
Beta Was this translation helpful? Give feedback.
-
Yet Another Alternative SolutionWhat if first we try to fix Abc: type = { /*declarations*/ }
x1: = 1.Abc; // this suggestion
x2: = 1.Abc(); // in current Cpp2
y1: = (1, 2).Abc; // this suggestion
y2: = (1).Abc(2); // in current Cpp2
z1: = (1, 2, 3).Abc; // this suggestion
z2: = (1).Abc(2, 3); // in current Cpp2 So
Using 10.(N*m) == 10 * 1.kg * 1.m2 / 1.s2
// <> can be used instead of ()
10.<N*m> == 10 * 1.kg * 1.m2 / 1.s2 But this alternative solution has a problem (opinion-based). The problem is that if |
Beta Was this translation helpful? Give feedback.
-
Now, if we use // Type composition within declarations:
A: type = { /*statements*/ }
B: type = { /*statements*/ }
function: <T> (a: A*T, b: B*T) -> A*B = { /*statements*/ }
point: type = {
operator=: (out this, a: A, b: B) = { /*statements*/ }
}
main: () = {
a: = ().A; // It calls the default constructor.
b: = 12.B; // It calls the constructor `operator=(out this, 12)`.
c: = 12.int.B; // Also they can be chained.
// Type composition within typed expressions:
x: = 10.(N*m) == 10 * 1.kg * 1.m2 / 1.s2;
y: = 10.(N*m) == 10.(kg*m2/s2);
z: = (a, b).point;
} |
Beta Was this translation helpful? Give feedback.
-
I don't think that's context-free:
Even with parentheses, |
Beta Was this translation helpful? Give feedback.
-
Yes, it's not context-free, because it's based on UFCS The motivation of this alternative suggestion is that if UFCS |
Beta Was this translation helpful? Give feedback.
-
They are not so comparable. |
Beta Was this translation helpful? Give feedback.
-
That's right but I've to clarify I don't want to say that |
Beta Was this translation helpful? Give feedback.
-
From this comment:
So simply |
Beta Was this translation helpful? Give feedback.
-
The type of |
Beta Was this translation helpful? Give feedback.
-
Surely the same suffix would result in the same type anyway?
On 15 June 2023 13:34:39 Johel Ernesto Guerrero Peña ***@***.***> wrote:
The type of 1s + 1.0s is their common type, which is the type of 1.0s.
—
Reply to this email directly, view it on GitHub<#463 (comment)>, or unsubscribe<https://github.com/notifications/unsubscribe-auth/AALUZQJWGJE4E3JRTBB5PYTXLL6NVANCNFSM6AAAAAAYJLD2PA>.
You are receiving this because you are subscribed to this thread.Message ID: ***@***.***>
|
Beta Was this translation helpful? Give feedback.
-
What if Cpp2 uses the following syntax for named arguments? x: = call(name: = "someone", age: int = 20); It may conflict with this suggestion ( |
Beta Was this translation helpful? Give feedback.
-
Thanks. After discussion in #663, @hsutter confirmed |
Beta Was this translation helpful? Give feedback.
-
This is an alternative solution to this issue. If you don't like
...TYPE
notation for object construction because of its UDL syntax, this is an alternative solution. In this suggestion, objection construction would use familiar notationEXPR:TYPE
(aka Typed Expression) which is similar to how Cpp2 programmers use it within declarations.Consider
EXPR:TYPE
as syntactic sugar to(: TYPE = EXPR)
. For example:Literally if
x:int
is at the start of a statement or function parameter, it would be a declaration, otherwise it would be a Typed Expression.EXPR:TYPE
is similar to...TYPE
suggestion, except with the following advantages:...TYPE
would complicate the grammar especially for working within function chaining.a++:Abc
). It depends on operator precedence, and it's left to right.And this notation has the following disadvantages:
:
. BTW it's opinion based.I have to explain
:
withinSOMETHING:TYPE
is for object construction (as an expression) or declaration (as a statement), but::
withinSOMETHING::TYPE
is scope resulotion operator for qualified names. They can be combined like10++ : my::Type
. Also after the object is constructored, we can use operator dot oroperator()
oroperator[]
or ... to access members from it, e.g.10:Type.call()
or10:Type[0]
.Will your feature suggestion eliminate X% of security vulnerabilities of a given kind in current C++ code?
No.
Will your feature suggestion automate or eliminate X% of current C++ guidance literature?
Yes.
EXPR:TYPE
, parentheses are not necessary whenEXPR
has operators with higher precedence.():TYPE
, it calls the default constructor(args...):TYPE
FUNCTION()
, it calls a function without argumentsFUNCTION(args...)
obj.FUNCTION()
obj.FUNCTION(args...)
using
statement before they can be applied to literals._
, thus they will be distinguished from UDLs which are declared in the Cpp1 standard library.TYPE(args)
it doesn't work with UFCS intentionally. UFCS should not work on constructors as described in this comment. Compare:Describe alternatives you've considered.
These are alternative solutions:
Thanks.
Beta Was this translation helpful? Give feedback.
All reactions