# Call closure stored as object property directly without use of temporary variable

- Thread: https://externals.io/message/64199
- Original archive: https://news-web.php.net/php.internals/64199
- Started by Adam Jon Richardson on 2012-12-08T21:48:50+00:00
- Messages: 7
- Reply by email to internals@lists.php.net
- More for agents: search with https://externals.io/search.md?q={query} · JSON API at https://externals.io/api · documentation at https://externals.io/llms.txt

---

## #64199 — Adam Jon Richardson — 2012-12-08T21:48:50+00:00

URL: https://externals.io/message/64199#64199

First, thanks everyone for the hard work on the PHP 5.5 alpha. I just ran
the tests and submitted some results, but from the little bit I've used it
so far, things are looking really nice.

Second, and to the main point of this email, I would like to be able to
call closures that are stored as object properties directly without having
to make use of a temporary variable.

For example:

<?php
$o = new stdClass();
$o->func = function(){
    return 'Yes!';
};
$o->func();
?>

The above code elicits the error:
Call to undefined method stdClass:test() in...

I realize I could create a class that implements __call() to intercept and
redirect the call to the closure, but this adds much overhead for a simple
approach and also precludes the use of stdClass (I like the option of being
able to cast to an array, and then back with very little overhead.)

It seems as though the parser could be updated to accommodate this
intention, but I understand this could pose a backwards compatibility issue
(current users could have closures stored as object properties and be
expecting the magic method __call() to be invoked instead of the closure
itself.)

Has anyone else wanted this functionality? Has anyone else thought of ideas
of addressing this (or come to the conclusion it really isn't safely
addressable without causing disproportionate amounts of grief?)

Thank you,

Adam

---

## #64200 — Stas Malyshev — 2012-12-08T22:05:21+00:00

URL: https://externals.io/message/64199#64200 · In reply to: #64199

Hi!

> Has anyone else wanted this functionality? Has anyone else thought of ideas
> of addressing this (or come to the conclusion it really isn't safely
> addressable without causing disproportionate amounts of grief?)

Yes, there were people that wanted this functionality, but since having
the same thing ($foo->bar()) mean two different things (call method
named "foo" vs. "fetch property named foo and then call it if it's
callable") is not a good idea this wasn't done.
In some languages, the options above are the same - i.e. methods and
properties are actually the same thing - but in PHP is is not so, and
can be made so without some BC-breaking changes.
-- 
Stanislav Malyshev, Software Architect
SugarCRM: http://www.sugarcrm.com/
(408)454-6900 ext. 227

---

## #64201 — Steve Clay — 2012-12-08T22:36:04+00:00

URL: https://externals.io/message/64199#64201 · In reply to: #64199

Adam,


> call closures that are stored as object properties directly without having
> to make use of a temporary variable.
...
> $o = new stdClass();
> $o->func = function(){
>      return 'Yes!';
> };
> $o->func();

The following expression avoids PHP's dilemma of distinguishing prop/method, but fails 
because you can't execute an expression:

($o->func)();

Similarly if $a is a Closure, $a() works but ($a)() fails.

If these could be made to work, would it break BC? And *should* they be made to work?

Steve Clay
-- 
http://www.mrclay.org/

---

## #64202 — Adam Jon Richardson — 2012-12-08T22:37:12+00:00

URL: https://externals.io/message/64199#64202 · In reply to: #64200

On Sat, Dec 8, 2012 at 5:05 PM, Stas Malyshev <smalyshev@sugarcrm.com>wrote:

> Hi!
>
> > […]
> ideas
> > […]
>
> Yes, there were people that wanted this functionality, but since having
> the same thing ($foo->bar()) mean two different things (call method
> named "foo" vs. "fetch property named foo and then call it if it's
> callable") is not a good idea this wasn't done.
> In some languages, the options above are the same - i.e. methods and
> properties are actually the same thing - but in PHP is is not so, and
> can be made so without some BC-breaking changes.
>

As it stands now, calling a method can mean two different things: calling
the method directly, or handling the method invocation within __call().
Checking for a method first, a closure instance next, and then falling
through to __call() seems like it would have been a reasonable approach.

That said, as you mention BC-breaking is now an issue.

Thanks,

Adam

---

## #64203 — Adam Jon Richardson — 2012-12-08T23:12:23+00:00

URL: https://externals.io/message/64199#64203 · In reply to: #64201

> 
>
> > […]
> ...
>
>  $o = new stdClass();
> > […]
>
> The following expression avoids PHP's dilemma of distinguishing
> prop/method, but fails because you can't execute an expression:
>
> ($o->func)();
>

I actually tried that very technique before remembering the limitation :)

Interesting idea.

Adam

---

## #64204 — Marco Pivetta — 2012-12-08T23:27:10+00:00

URL: https://externals.io/message/64199#64204 · In reply to: #64203

I'm currently working around this problem by assuming that a Closure
implements `__invoke`:

`$this->someProp->__invoke();`

Not really nice, but this works in both 5.3 and 5.4.

If the suggestion above could cover also `callable` and not just `Closure`
then it would be quite interesting to have that.



Marco Pivetta

http://twitter.com/Ocramius

http://ocramius.github.com/

---

## #64206 — Stas Malyshev — 2012-12-09T08:30:27+00:00

URL: https://externals.io/message/64199#64206 · In reply to: #64202

Hi!

> As it stands now, calling a method can mean two different things:
> calling the method directly, or handling the method invocation within
> __call(). Checking for a method first, a closure instance next, and then
> falling through to __call() seems like it would have been a reasonable
> approach.

This is the same thing. However, what you mean by "closure instance" is
actually a property access, which is not the same thing as method call.
Think about what happens if you have both __call and __get (or object
implementing both handlers).

-- 
Stanislav Malyshev, Software Architect
SugarCRM: http://www.sugarcrm.com/
(408)454-6900 ext. 227
