You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
On Jun 11, 2018, at 5:04 AM, Thomas Köppe ***@***.***> wrote:
Can we take a wider look at how we say "call " and how we spell that?
And, if we're going to do that, let's also please reconsider our use of "called" in the sense of "named" or "termed": "called" is such an important term of art that it seems preferable to restrict (as much as possible) its use to the technical sense of "invoked".
For example, we could easily s/called/termed/ in [intro.refs]:
2 The library described in Clause 7 of ISO/IEC 9899:2011 is hereinafter called the C standard library.
3 The operating system interface described in ISO/IEC 9945:2003 is hereinafter called POSIX.
4 The ECMAScript Language Specification described in Standard Ecma-262 is hereinafter called ECMA-262.
As another example, we could s/called/known as/ or s/called/termed/ in footnote 4, which starts "This provision is sometimes called the “as-if” rule, ...".
At a minimum, I urge that we avoid introducing further uses of "call", "called", "calling", etc., unless used in the technical sense of "invoke". We can then do drive-by fixes as opportunity presents.
One issue is naming functions as function() instead of just function, where the trailing parentheses are supposed to merely indicate "that thing was a function" and the function actually takes parameters. That's simply wrong, and we have existing editorial guidance on removing those parentheses. But that's not this case.
For a function that takes no parameters, such as terminate, terminate() could mean two things. One is "the overload of the function terminate that has no parameters". I would strongly prefer that we do not use trailing parentheses on a function name unless it is overloaded. (If a smart pointer has both reset() and reset(pointer) overloads, it's fine to say "reset() does this thing, reset(pointer) does something else". But not for terminate.) That appears to cover most of the uses in [except], which are referring to the function itself, not to a call to the function.
The other thing that terminate() could mean is "the expression terminate()". That usage seems fine to me, and is consistent with how we'd describe a call to a library function that takes arguments. But I don't think (m)any of our uses of terminate() actually mean that.
The phrase "calls blah" is ambiguous, particularly when "blah" ends with parentheses. It could mean either "calls the function named by blah [with no arguments]", or "evaluates the expression blah, which is a function call expression". "Calls terminate" is the former, and "Calls terminate()" is the latter. Both forms are disappointing:
When we say "std::terminate is called", we have incompletely specified the behavior. Called with what arguments? We get away with this because there is (currently) no choice, but that would change if an overload were added.
When we say "calls std::terminate()", do we mean "evaluates std::terminate()" or do we mean "evaluates std::terminate(), interprets its result as a callable, and then calls that?
Decision:
Do not use trailing parentheses to mean simply "this name is a function". You may use trailing parentheses when referring to an overloaded function to specify which overload you mean, but if this comes up we should discuss a better way of naming it, such as "the blah(int) overload".
When we say "Calls blah", blah should be an expression that results in a function call. Eg, "calls operator new(size)" or "calls current_exception() and stores the returned value".
As an alternative, you may use "Calls blah with <some arguments>", and in that case blah should be a function.
The form "Calls to the function blah do X, Y, Z" is also OK, and blah should denote a function not an expression. (Per the first bullet, there should be no parentheses unless the function is overloaded.)
Which I think means that most of the places that say std::terminate without parens are wrong and need parens (eg, in [basic.start.term]), and most of the places that say std::terminate() with parens are wrong and need the parens removed (eg, in [except]).
I also think Walter's suggestion is good. Try not to introduce more uses of "called" when we mean something other than an invocation of a function. In contexts where we can't just use "is", "known as" can be used.
All else being equal, we should endeavor to define terms separately from stating requirements on those terms, allowing use of "is" instead of "known as" or "called". Eg, in [lex.ccon], we have:
A character literal that begins with u8, such as u8’w’, is a character literal of type char, known as a UTF-8 character literal. The value of a UTF-8 character literal is equal to [...]
But we should instead separate the definition from the requirements on the implementation, removing the "known as" in the process:
A UTF-8 character literal is a character literal that begins with u8, such as u8'w'. A UTF-8 character literal is of type char and its value is equal to [...]
I'd like to point out that "called" (as in function call) is slightly ambiguous whether only calls via function call expressions [expr.call] are in scope, or any situation where a function is invoked (e.g. conversion function, constructor, destructor of temporary at end of full-expression etc.) I thought CWG was eager to use "invoked" in such general circumstances, but a second look at existing text might be worthwhile.
@zygoloid, I believe we should really remove more of the "is called", in particular with std::terminate, since it almost never appears in an expression that the user wrote.
I'd suggest for the std::terminate case in particular, "... the function std::terminate is invoked (except.terminate]". This phrasing avoids the parens question and the "is there really an expression that is evaluated" question (for example, what if std::terminate had a default argument: where would temporaries be destroyed?)
Activity
tkoeppe commentedon Jun 11, 2018
Can we take a wider look at how we say "call <function-name>" and how we spell that?
W-E-Brown commentedon Jun 11, 2018
zygoloid commentedon Jun 11, 2018
There are multiple issues here:
One issue is naming functions as
function()
instead of justfunction
, where the trailing parentheses are supposed to merely indicate "that thing was a function" and the function actually takes parameters. That's simply wrong, and we have existing editorial guidance on removing those parentheses. But that's not this case.For a function that takes no parameters, such as
terminate
,terminate()
could mean two things. One is "the overload of the function terminate that has no parameters". I would strongly prefer that we do not use trailing parentheses on a function name unless it is overloaded. (If a smart pointer has bothreset()
andreset(pointer)
overloads, it's fine to say "reset()
does this thing,reset(pointer)
does something else". But not forterminate
.) That appears to cover most of the uses in [except], which are referring to the function itself, not to a call to the function.The other thing that
terminate()
could mean is "the expressionterminate()
". That usage seems fine to me, and is consistent with how we'd describe a call to a library function that takes arguments. But I don't think (m)any of our uses ofterminate()
actually mean that.The phrase "calls blah" is ambiguous, particularly when "blah" ends with parentheses. It could mean either "calls the function named by blah [with no arguments]", or "evaluates the expression blah, which is a function call expression". "Calls
terminate
" is the former, and "Callsterminate()
" is the latter. Both forms are disappointing:std::terminate
is called", we have incompletely specified the behavior. Called with what arguments? We get away with this because there is (currently) no choice, but that would change if an overload were added.std::terminate()
", do we mean "evaluatesstd::terminate()
" or do we mean "evaluatesstd::terminate()
, interprets its result as a callable, and then calls that?Decision:
Do not use trailing parentheses to mean simply "this name is a function". You may use trailing parentheses when referring to an overloaded function to specify which overload you mean, but if this comes up we should discuss a better way of naming it, such as "the
blah(int)
overload".When we say "Calls
blah
",blah
should be an expression that results in a function call. Eg, "callsoperator new(size)
" or "callscurrent_exception()
and stores the returned value".As an alternative, you may use "Calls
blah
with <some arguments>", and in that caseblah
should be a function.The form "Calls to the function
blah
do X, Y, Z" is also OK, andblah
should denote a function not an expression. (Per the first bullet, there should be no parentheses unless the function is overloaded.)Which I think means that most of the places that say
std::terminate
without parens are wrong and need parens (eg, in [basic.start.term]), and most of the places that saystd::terminate()
with parens are wrong and need the parens removed (eg, in [except]).zygoloid commentedon Jun 11, 2018
I also think Walter's suggestion is good. Try not to introduce more uses of "called" when we mean something other than an invocation of a function. In contexts where we can't just use "is", "known as" can be used.
All else being equal, we should endeavor to define terms separately from stating requirements on those terms, allowing use of "is" instead of "known as" or "called". Eg, in [lex.ccon], we have:
But we should instead separate the definition from the requirements on the implementation, removing the "known as" in the process:
jensmaurer commentedon Jun 14, 2018
I'd like to point out that "called" (as in function call) is slightly ambiguous whether only calls via function call expressions [expr.call] are in scope, or any situation where a function is invoked (e.g. conversion function, constructor, destructor of temporary at end of full-expression etc.) I thought CWG was eager to use "invoked" in such general circumstances, but a second look at existing text might be worthwhile.
jensmaurer commentedon Jun 15, 2018
@zygoloid, I believe we should really remove more of the "is called", in particular with std::terminate, since it almost never appears in an expression that the user wrote.
I'd suggest for the std::terminate case in particular, "... the function std::terminate is invoked (except.terminate]". This phrasing avoids the parens question and the "is there really an expression that is evaluated" question (for example, what if std::terminate had a default argument: where would temporaries be destroyed?)