8

How should I document an anonymous function when it's passed as an argument? For example:

// Call my_function(), passing 2 arguments.
my_function( 'foo', function() {
    // Body of the anon function I'd like to document.
} );

Thanks in advance.

7ochem
  • 2,183
  • 1
  • 34
  • 42
henrywright
  • 10,070
  • 23
  • 89
  • 150
  • @MarkBaker that'd be the type but I'm wondering if a DocBlock is necessary, and if so where to put it etc. Is there a standard way to document this type of situation? – henrywright Dec 30 '15 at 19:18

2 Answers2

4

To document that a function accepts a Closure, I'd suggest callable:

/**
 * Do something.
 * @param callable $code
 */
function foo(callable $code) {
}

Regarding the commentary, PHPDoc uses DocBlocks, which the PHP engine Tokenizer only recognizes above formal definitions. Thus, PHPDoc will not see this:

/**
 * My closure.  PHPDoc will *not* parse this, because it's not a formal definition.
 * @param string $name
 */
$closure = function ($name) { return $name; };
bishop
  • 37,830
  • 11
  • 104
  • 139
  • Thanks, but isn't that documenting the param in the function's definition? My situation is slightly different. I need to document the argument in the function call when the argument happens to be a function itself. – henrywright Dec 30 '15 at 19:19
  • Yes, it is. Are you wanting to document the type in the caller? If so, I don't recall ever having seeing that before... Maybe I'm not getting what you want to document. :) – bishop Dec 30 '15 at 19:21
  • I've not seen it before either, I suppose that's why I'm asking. I feel anonymous functions are equal to named functions aside from their unbound nature. So my guess is they also need to be documented, but I have no idea how. – henrywright Dec 30 '15 at 19:23
  • Usually closures are self-evident and don't need much documentation beyond say a passing end-of-line comment. If you find your closure needs to explain why it works the way it does, consider making it a proper function. You'll have to do that anyway, because PHPDoc only supports DocBlocks, which only exist as `/** */` just above a definition. – bishop Dec 30 '15 at 19:27
  • I was thinking the same, although making a function non-anonymous purely because there's no easy way to document it doesn't feel right. You're right that the anon function code example I gave in my question is very simple and doesn't need explaining, but imagine if it took parameters, there would be a greater need to document it. – henrywright Dec 30 '15 at 19:32
  • In my experience, if a closure has needed documentation, then it's tended to be vital and therefore deserved formal naming. Maybe that's just my style. At any rate, see my edit, which addresses this. Bottom line: PHPDoc will not see your comment unless it's in a DocBlock, and DocBlocks are only seen on formal definitions. See also http://stackoverflow.com/q/2531085/2908724 and http://stackoverflow.com/q/16589902/2908724. – bishop Dec 30 '15 at 19:36
  • Thanks for the edit. I got into this situation because I didn't want to pollute the global space with a function name that could result in collisions (I know I can use namespaces for that but this became an interesting question so I thought I'd ask). Indeed, I guess house style will need to be the solution here because there seems to be no formal way to document this situation at this point. – henrywright Dec 30 '15 at 19:45
3

This has worked for me so far:

interface CustomCallback
{
    /**
     * @return string
     */
    public function __invoke();
}

/**
 * @param string $a
 * @param CustomCallback $b
 * @return void
 */
my_function($a, $b) {

}

This tells us that the second parameter of my_function expects something that implements the CustomCallback interface. By looking in the CustomCallback interface, we can see that it's callable because of the __invoke method. Then by looking at the __invoke method's documentation, we see what parameters it expects and the return type.