UFCS with multiple related arguments #811
Replies: 6 comments 9 replies
-
I know it conflicts with comma operator in Cpp1, but it can work without any problem in Cpp2. |
Beta Was this translation helpful? Give feedback.
-
var4: = (0, 0, 0).point(true);
var5: = ("Alex", 30, country::usa).person();
At this point, why is this better than
var4: = point(0, 0, 0, true);
var5: = person("Alex", 30, country::usa);
I don't dislike your proposal per-se, I just want to understand why you think we can increase readability by arbitrarily splitting up arguments between before and after the function /typename
Also I understand that ufcs allows for certain templates to become more generic, does this proposal help this at all?
On 8 November 2023 06:52:10 Sadeq ***@***.***> wrote:
UFCS is really expressive when we want to constrcut an object from one argument:
person: type = {
// ...
operator=: (out this, name: std::string) = { /* ... */ }
// ...
}
var1: = "Alex".person();
// : person = "Alex";
Also it's nice to manipulate objects with constructors:
var2: = "Hello World!".std::string(5);
And it looks similar to UDL suffixes that supports multiple units:
var3: = 10.box().apple();
But when we want to construct an object from multiple arguments, it significantly harms readability:
var4: = 0.point(0, 0, true);
var5: = "Alex".person(30, country::usa);
Would it be possible to extend UFCS to support multiple arguments?
var4: = (0, 0, 0).point(true);
var5: = ("Alex", 30, country::usa).person();
It would helpfully allow us to separate related arguments to the left side of operator..
I opened two issues (#455<#455>, #463<#463>) to request this feature before, but mistakenly my suggestions contained syntax changes.
The syntax doesn't really matter, only a way to put related arguments aside is enough. Thanks.
—
Reply to this email directly, view it on GitHub<#811>, or unsubscribe<https://github.com/notifications/unsubscribe-auth/AALUZQP2VNVJQZFRCDJVXTLYDMTZNAVCNFSM6AAAAAA7CLSMF6VHI2DSMVQWIX3LMV43ERDJONRXK43TNFXW4OZVHAZDMMZTGY>.
You are receiving this because you are subscribed to this thread.Message ID: ***@***.***>
|
Beta Was this translation helpful? Give feedback.
-
Oh I'm already well in favour of UFCS, and I agree that your multiple arguments allows for nicer discovery of types pertaining to the variables, but what programmer intent is portrayed when viewing
(a, b).f(c);
Vs
a.f(b, c);
Autocomplete is already the work of a tool, so extending it to work with "(a, b, c)." doesn't necessarily require a language feature, as it could easily auto complete to "type(a, b, c)"
Basically my point is, do we need to visually complicate the language further, when the feature you suggest is for a tool rather than the language?
On 8 November 2023 10:21:10 Sadeq ***@***.***> wrote:
I don't dislike your proposal per-se, I just want to understand why you think we can increase readability by arbitrarily splitting up arguments between before and after the function /typename
According to P3021r0 paper from @hsutter<https://github.com/hsutter>, UFCS has the following benefits:
3.1.1. It’s friendlier to editors and tools
3.1.2. It’s friendlier to programmers: Discoverability
3.1.3. It more directly corresponds to what programs do: State transition
3.1.4. The existing-practice workarounds already simulate extending the member call syntax, not the nonmember syntax
If I want to construct a 3D point, and | is the cursor in the following example:
var1: = (0, 0, 0).|
The editor will show me the appropriate list of functions and types (3.1.1). The editor will find types and functions which can be called with those parameters, and it will show me a list of them. In this example, it may show me a list with point, matrix, etc.
Also as Herb wrote in that paper (3.1.2):
This illustrates why the member call syntax is generally friendlier to programmers. I believe the “start with the
object” point of view is a much more usable programming model because it directly enables answering the con-
stant question of how to discover “what can I do next?”. What you can do next (functions) depends on what you
have now to do it with (your objects and variables).
In this example, our object has 3 parts (0, 0, 0) instead of 1 part "Alex".
And the most important case in my example is state transition (3.1.3), I as a programmer prefer to write the object and then I do something to that.
And for the last case (3.1.4):
(first(), second()).third();
third(first(), second());
Infact, my suggestion is motiviated from Herb's P3021r0 paper that makes me think why we still need UFCS with multiple related arguments.
Also I understand that ufcs allows for certain templates to become more generic, does this proposal help this at all?
I mean, the only thing that matters in my suggestion is readability and toolability, and it works in generic programming too (because of UFCS):
fnc1: (a: i32, b: i32, c: bool) = { /* ... */ }
(0, 0).fnc1(true);
So (0, 0).fnc1(true) calls non-member functions too. The separated arguments would make it clear that what was the indention of the programmer in generic programming. So yes, it helps in generic programming too. Thanks.
—
Reply to this email directly, view it on GitHub<#811 (reply in thread)>, or unsubscribe<https://github.com/notifications/unsubscribe-auth/AALUZQIBJFQSMJPKQRJ47Y3YDNMJHAVCNFSM6AAAAAA7CLSMF6VHI2DSMVQWIX3LMV43SRDJONRXK43TNFXW4Q3PNVWWK3TUHM3TKMBYGYYTO>.
You are receiving this because you commented.Message ID: ***@***.***>
|
Beta Was this translation helpful? Give feedback.
-
I think this might encourage writing inside-out code again. auto sushi_for_two(std::vector<int> sushi) { // clang-format off
return sushi
|> zip_with(_neq_, $, $ | drop(1))
|> zip($, iota(1))
|> filter($, _fst)
|> values($)
|> concat(single(0), $, single(sushi.size()))
|> zip_with(_sub_, $ | drop(1), $)
|> zip_with(_min_, $, $ | drop(1))
|> std::ranges::max($) * 2;
} // clang-format on Line
to
|
Beta Was this translation helpful? Give feedback.
-
Briefly, I suggest to make ... (obj, a1, a2, ...).call(b1, b2, ...) ... a syntax sugar to ... obj.call(a1, a2, ..., b1, b2, ...) Therefore if TYPE(/* out this */, obj, a1, a2, ..., b1, b2, ...)
FUNCTION(obj, a1, a2, ..., b1, b2, ...) But if obj.FUNCTION(a1, a2, ..., b1, b2, ...)
FUNCTION(obj, a1, a2, ..., b1, b2, ...) So the behavior of it depends on if As you see, So if we use UFCS, we can argue that On the other hand, if for readability reasons I change As a result, |
Beta Was this translation helpful? Give feedback.
-
Here's why I think this is not worth it. UFCS unified two notations that ALREADY EXISTED but here you are making a new one. This does not help in writing code in any way, because there's no code out there that has this new syntax in it. Also, the advantages that Herb mentions in his paper do not apply here. This is not friendlier to editor, tools or programmer. Most of that friendliness came because dot syntac already existed but this one doesn't. |
Beta Was this translation helpful? Give feedback.
-
UFCS is really expressive when we want to constrcut an object from one argument:
Also it's nice to convert or manipulate objects with constructors:
And it looks like UDL suffixes and supports multiple units too:
var3: = 10.box().apple();
But when we construct an object from multiple related arguments, it significantly harms readability:
Would it be possible to extend UFCS to support multiple arguments on the left side?
It increases readability and helpfully allows us to separate related arguments to the left side of
operator.
.I opened two issues (#455, #463) to request this feature before, but mistakenly my suggestions contained syntax changes.
The syntax doesn't really matter, only a way to put related arguments aside is enough. Thanks.
Beta Was this translation helpful? Give feedback.
All reactions