Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Extension methods #1122
Extension methods #1122
Changes from all commits
c64a86f
115a66b
b95834f
fc45ee8
5e20b69
ee06fed
9aa400a
4dc6ebc
File filter
Filter by extension
Conversations
Jump to
There are no files selected for viewing
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think
i32
is going to be a class type though....Maybe "There are no restrictions on the types that can be used with
me
parameters."?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm unconvinced by the ergonomic argument.
This is noted by the example at https://en.wikipedia.org/wiki/Extension_method#Current_C#_solutions, where they compare
string y = Utility.Reverse(x);
with the more desirablestring y = x.Reverse();
. It seems like this proposal would providestring y = x.(Utility.Reverse)();
, but the key advantage noted in the article is eliding theUtility
container class (and also, unless qualified function calls turn out to be common, I think the extra parens will be awkward in practice).Put differently, I feel like the main advantage of extension methods in other languages would be that they're seamless. However, the whole argument against that here is that you want to avoid new name lookup rules. In which case, I don't think extension methods are a reasonable comparison (and you might also want to consider the alternative: provide extension methods similar to how they exist elsewhere).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
An ergonomic disadvantage is also that, assuming I'm understanding correctly that this only moves the location of
Utility.Reverse
in the call, I think there'll be limited adoption. i.e., it's not so unambiguous an advantage that developers will flock to it (I don't understand why I would use this, but I assume other developers would think the opposite), and there'll just be multiple ways of offering member-method-like functions for classes.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You can get pretty close to the C# syntax, but it requires an explicit opt-in:
And yeah, I also don't expect developers to flock to this. But we need some rule in this space, and the only question seems to be how much of a barrier and what amount of language complication we want to put in front of people -- even the most restrictive of the alternatives below still permits writing extension methods, with more cumbersome syntax. The simple, orthogonal thing to do is to not restrict which functions can have a
me
.There is one way in which this isn't just moving the location of
Utility.Reverse
in the call: onlyme
has the specialaddr me
behavior that implicitly takes the address of the value before the.
.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
One ergonomic advantage of method call syntax is that, if the codebase uses a natural language like English that has SVO word order, the method can sometimes be named so that the call syntax matches that order, which can make the code clearer. For example, I find
x.Contains(y)
substantially clearer thanContains(x, y)
, because it matches the order of the English phrase "x contains y". That not only reduces my mental effort in parsing the code, it makes me more confident in the meaning of the code:x.Contains(y)
is very unlikely to mean "y contains x", whereasContains(x, y)
plausibly could.Extension methods make that option available even when the "subject" and "verb" are defined by different libraries. However, that may be undermined by the need to qualify the method name in most cases:
x.(Utility.Contains)(y)
doesn't read very naturally, although it's probably still less ambiguous about the roles ofx
andy
. And of course this advantage doesn't apply at all if the codebase's natural language doesn't use SVO order.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
To be clear, I'm not objecting to extension methods (as a concept), I'm objecting that the syntactic overhead undermines the ergonomic benefit of this particular approach. Some of the question may be from the intuition: is compound member access going to be something that's really common in Carbon, or something that developers rarely see? My assumption is the latter, but maybe others differ.
If compound member access is common, then it reduces the cognitive costs of the feature by making it something people are accustomed to; if rare, then developers will be learning the feature when they see it (and perhaps forgetting it quickly due to disuse), and leading to slower understanding of code and likely more bugs.
Contains(x, y)
may not read as great, but it's going to be familiar to C++ developers as a function call, even versusx.(Contains)(y)
.In other words -- maybe similar things would exist regardless, as noted in the alternatives, and determined developers would surely find them. But pushing developers towards a smaller set of common approaches has readability benefits too; I'd argue it's lower cognitive load for developers.