Request for Comments: Alternative syntax for creating fully resolved callbacks
- Version: 1.0
- Date: 2012-09-18
- Author: Stephen Clay steve@mrclay.org
- Status: Withdrawn
- First Published at: https://wiki.php.net/rfc/alternative_callback_syntax
Introduction
This RFC proposes the syntax func_name::function
for generating a callback value at runtime with correctly resolved class and function names.
Why?
The string and array formats for callbacks present difficulties for users and IDEs:
- Most IDEs do not recognize callbacks, and so cannot offer autocompletion, rename refactoring, and other benefits of code comprehension.
- Authors can misspell identifiers inside strings.
- Within namespaced code, authors can forget to prepend the namespace, since function calls within the namespace do not require it.
- Where use statements change the identifier for a class, authors can forget to specify the fully resolved name.
Proposal
PHP would provide a syntax, similar to a function call, which evaluates to a string or array callback value. This would be composed of the usual function call syntax, but replacing the parameter list and surrounding parenthesis with ::function
. For example, to create the callback “Foo::bar”
, one would use the expression Foo::bar::function
.
Under the proposal, the following expressions (within a namespace NS
and a class Foo
) would evaluate as true:
func::function === 'NS\\func'; \func::function === 'func'; CN::meth::function === 'NS\\CN::meth'; \CN::meth::function === 'CN::meth'; self::meth::function === 'NS\\Foo::meth'; $obj->meth::function === [$obj, 'meth']; parent::{'meth'}::function === ['NS\\Foo', 'parent::meth'];
Example Code
namespace NS1; use NS2\Bee as B; class A { static function init() { $inst = new self; var_export($inst->bar::function); $inst->bar(); } function bar() { var_export(B::baz::function); } } function c() {} var_export(var_export ::function); var_export(A::init ::function); A::init(); var_export(c ::function);
At runtime, these values would be passed to var_export
:
'var_export'; 'NS1\\A::init'; [$inst, 'bar']; 'NS2\\Bee::baz'; 'NS1\\c';
Considerations
As function
is a reserved word, it should not be misinterpreted as a constant or method in previous versions (this idea borrowed from Ralph Schindler’s class_name_scalars RFC). If the implementation reused the T_FUNCTION token, the syntax would be case-insensitive.
Any other use of ::function
should throw a parse error. Although it may be reasonable to suggest supporting syntaxes like ($callable)::function
(evaluating to the value of $callable
), I believe this would not provide much benefit and would complicate the spec.
As it is permitted between a function name and its argument list, for consistency and flexibility, whitespace should be permitted before the ::function
tokens. It's not clear whether whitespace would improve or worsen readability of the expression in practice; this will likely depend on how syntax highlighters display the ::function
tokens.
Summary
::function
would give authors a straightforward and reliable way to specify correctly-formed callbacks without being tripped up by namespaces and use
statements. Callback expressions would also be more clearly recognized as such by the reader, and by IDEs and static analysis tools.
Changelog
- 2012-09-18 Created by Steve Clay