# function call chaining

- Thread: https://externals.io/message/46789
- Original archive: https://news-web.php.net/php.internals/46789
- Started by Stanislav Malyshev on 2010-01-19T00:27:51+00:00
- Messages: 67
- Page 1 of 3: messages 1 to 25 (25 per page, add `?page=N` to the URL)
- Next page: https://externals.io/message/46789.md?page=2
- 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

---

## #46789 — Stanislav Malyshev — 2010-01-19T00:27:51+00:00

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

Hi!

I wrote a small patch that enables this kind of syntax in PHP:

foo()();

What it means is that if foo() returns callable value (which probably 
should be function name or closure) then it would be called. Parameters 
and more than two sets of () work too.
Of course, this is mostly useful for doing closures, and that was 
primary drive for implementing it - to make working with closures and 
especially function returning closures easier.
What does not work currently is $foo->bar()() - since it is surprisingly 
hard to tell parser it's not {$foo->bar}()() - which of course is not 
what I want to do.

The patch is here: http://random-bits-of.info/funcfunc.diff

What do you think? If somebody has better idea btw - maybe make 
something like {foo()}() - and make that work for any expression inside 
{} - that might work too. So, what do you think?
-- 
Stanislav Malyshev, Zend Software Architect
stas@zend.com   http://www.zend.com/
(408)253-8829   MSN: stas@zend.com

---

## #46791 — Richard Lynch — 2010-01-19T04:12:42+00:00

URL: https://externals.io/message/46789#46791 · In reply to: #46789

> I wrote a small patch that enables this kind of syntax in PHP:
>
> foo()();
>
> What it means is that if foo() returns callable value (which probably
> should be function name or closure) then it would be called.
> Parameters
> and more than two sets of () work too.
> Of course, this is mostly useful for doing closures, and that was
> primary drive for implementing it - to make working with closures and
> especially function returning closures easier.
> What does not work currently is $foo->bar()() - since it is
> surprisingly
> hard to tell parser it's not {$foo->bar}()() - which of course is not
> what I want to do.
>
> The patch is here: http://random-bits-of.info/funcfunc.diff
>
> What do you think? If somebody has better idea btw - maybe make
> something like {foo()}() - and make that work for any expression
> inside
> {} - that might work too. So, what do you think?

If I understand what this does...

I think it would be far easier to just keep using:
$foo_closure = foo();
$foo();

then to try to deal with foo()();

foo()(); just seems a bit too arcane to me...

-- 
Some people ask for gifts here.
I just want you to buy an Indie CD for yourself:
http://cdbaby.com/search/from/lynch

---

## #46792 — Alexey Zakhlestin — 2010-01-19T07:14:34+00:00

URL: https://externals.io/message/46789#46792 · In reply to: #46789

> Hi!
> 
> I wrote a small patch that enables this kind of syntax in PHP:
> 
> foo()();
> 
> What it means is that if foo() returns callable value (which probably should be function name or closure) then it would be called. Parameters and more than two sets of () work too.
> Of course, this is mostly useful for doing closures, and that was primary drive for implementing it - to make working with closures and especially function returning closures easier.
> What does not work currently is $foo->bar()() - since it is surprisingly hard to tell parser it's not {$foo->bar}()() - which of course is not what I want to do.

I like it!

regarding $foo->bar()()…
is it possible to use precedence rules here? something like:

    ($foo->bar())();


> What do you think? If somebody has better idea btw - maybe make something like {foo()}() - and make that work for any expression inside {} - that might work too. So, what do you think?

why curly braces?
Parentheses would feel more natural here.

Would be nice if something like this worked too:

    (new Class())->method();

---

## #46793 — Eddie Drapkin — 2010-01-19T07:29:06+00:00

URL: https://externals.io/message/46789#46793 · In reply to: #46792

>
> Would be nice if something like this worked too:
>
>    (new Class())->method();
>
>

I was just looking at some Java code and thinking, "man I wish PHP did this."

---

## #46794 — Jani Taskinen — 2010-01-19T10:30:42+00:00

URL: https://externals.io/message/46789#46794 · In reply to: #46793

> 
> > […]
> I was just looking at some Java code and thinking, "man I wish PHP did this"

Funny, I was just thinking the opposite "man I wish PHP never allows 
this" :)

Can of worms I say, can of worms..

--Jani

---

## #46795 — Antony Dovgal — 2010-01-19T10:43:52+00:00

URL: https://externals.io/message/46789#46795 · In reply to: #46794

> Funny, I was just thinking the opposite "man I wish PHP never allows 
> this" :)
> 
> Can of worms I say, can of worms..

Exactly my thought.
Please, let's not open it.

-- 
Wbr,
Antony Dovgal
---
http://pinba.org - realtime statistics for PHP

---

## #46796 — Christian Schneider — 2010-01-19T10:47:27+00:00

URL: https://externals.io/message/46789#46796 · In reply to: #46792

Alexey Zakhlestin wrote:
> Would be nice if something like this worked too:
>     (new Class())->method();

If you *really* want to do this you can use a factory method:
Class::create()->method();

- Chris

---

## #46797 — Pierre Joye — 2010-01-19T10:53:52+00:00

URL: https://externals.io/message/46789#46797 · In reply to: #46789

hi Stan,


> Hi!
>
> I wrote a small patch that enables this kind of syntax in PHP:
>
> foo()();
>
> What it means is that if foo() returns callable value (which probably should
> be function name or closure) then it would be called. Parameters and more
> than two sets of () work too.
> Of course, this is mostly useful for doing closures, and that was primary
> drive for implementing it - to make working with closures and especially
> function returning closures easier.
> What does not work currently is $foo->bar()() - since it is surprisingly
> hard to tell parser it's not {$foo->bar}()() - which of course is not what I
> want to do.
>
> The patch is here: http://random-bits-of.info/funcfunc.diff
>
> What do you think? If somebody has better idea btw - maybe make something
> like {foo()}() - and make that work for any expression inside {} - that
> might work too. So, what do you think?

I'm not a fan of this kind of syntaxic sugars, especially for
procedural implementation only. What are the benefits?

Cheers,
-- 
Pierre

@pierrejoye | http://blog.thepimp.net | http://www.libgd.org

---

## #46798 — Alexey Zakhlestin — 2010-01-19T10:55:32+00:00

URL: https://externals.io/message/46789#46798 · In reply to: #46796

> Alexey Zakhlestin wrote:
> > […]
> 
> If you *really* want to do this you can use a factory method:
> Class::create()->method();

I know. That's what I do if I need it.
Or just create temporary variable

But, still, I want consistent syntax, which doesn't put limitations on me
this construct is an example of things, which many people take for granted and are shocked, when they discover, that they can't use it.
I saw a lot of questions on forums regarding it

---

## #46799 — Alain Williams — 2010-01-19T11:19:36+00:00

URL: https://externals.io/message/46789#46799 · In reply to: #46798

> 
> 
> 
> > […]
> 
> I know. That's what I do if I need it.
> Or just create temporary variable
> 
> But, still, I want consistent syntax, which doesn't put limitations on me
> this construct is an example of things, which many people take for granted and are shocked, when they discover, that they can't use it.
> I saw a lot of questions on forums regarding it

I am in favour of such things and get annoyed when it doesn't work.
I get annoyed because things like this don't work:
	$a = '0123456789'[$i];

But I come from a C background and am a competent programmer.

I have seen the argument that things like this will confuse novice programmers,
maybe: but would they ever try to type something like that ?

-- 
Alain Williams
Linux/GNU Consultant - Mail systems, Web sites, Networking, Programmer, IT Lecturer.
+44 (0) 787 668 0256  http://www.phcomp.co.uk/
Parliament Hill Computers Ltd. Registration Information: http://www.phcomp.co.uk/contact.php
Past chairman of UKUUG: http://www.ukuug.org/
#include <std_disclaimer.h

---

## #46800 — Michael Wallner — 2010-01-19T11:31:13+00:00

URL: https://externals.io/message/46789#46800 · In reply to: #46789

> Hi!
> 
> I wrote a small patch that enables this kind of syntax in PHP:
> 
> foo()();

I'd rather see two other things that are missing, support for
dynamic object and array de-referencing like
(new class)->method() and get_array()["index"].

I honestly don't see func()()()() make anything better in the
world of a PHP programmer.

Regards,
Mike

---

## #46801 — Pierre Joye — 2010-01-19T11:41:05+00:00

URL: https://externals.io/message/46789#46801 · In reply to: #46800

> 
> > […]
>
> I'd rather see two other things that are missing, support for
> dynamic object and array de-referencing like
> (new class)->method() and get_array()["index"].
>
> I honestly don't see func()()()() make anything better in the
> world of a PHP programmer.

Exactly.

Cheers,
-- 
Pierre

@pierrejoye | http://blog.thepimp.net | http://www.libgd.org

---

## #46802 — Arvids Godjuks — 2010-01-19T11:44:47+00:00

URL: https://externals.io/message/46789#46802 · In reply to: #46801

2010/1/19 Pierre Joye <pierre.php@gmail.com>:
> 
> > […]
>
> Exactly.
>
> Cheers,
> --
> Pierre
>

Totally agree.

---

## #46803 — johannes@php.net — 2010-01-19T12:01:26+00:00

URL: https://externals.io/message/46789#46803 · In reply to: #46800

Hi,


> 
> > […]

I think that becomes hard to read quite easily.

> I'd rather see two other things that are missing, support for
> dynamic object and array de-referencing like
> (new class)->method() and get_array()["index"].

For the latter - there's a patch by some user in the bug tracker, which
I can't find right now.

Having $foo[0]->bar(); and $foo()[0];  it might also make sense to allow
more of these, like the proposed foo()() but other than such consistency
I don't really like it ....

johannes

---

## #46804 — Clint Priest — 2010-01-19T13:25:32+00:00

URL: https://externals.io/message/46789#46804 · In reply to: #46800

> I'd rather see two other things that are missing, support for
> dynamic object and array de-referencing like
> (new class)->method() and get_array()["index"].
>
> I honestly don't see func()()()() make anything better in the
> world of a PHP programmer.

The array de-referencing and dynamic objects are much more common use 
cases in PHP than call de-referencing, has anyone even needed (or 
wanted) to do a func()() before?  I haven't.

That being said, it probably should work unless there's a good reason 
not to allow it to work.

-Clint

---

## #46805 — Stanislav Malyshev — 2010-01-19T16:00:44+00:00

URL: https://externals.io/message/46789#46805 · In reply to: #46797

Hi!

> I'm not a fan of this kind of syntaxic sugars, especially for
> procedural implementation only. What are the benefits?

Some as all other syntax sugars - better-looking code.
-- 
Stanislav Malyshev, Zend Software Architect
stas@zend.com   http://www.zend.com/
(408)253-8829   MSN: stas@zend.com

---

## #46806 — Pierre Joye — 2010-01-19T16:02:37+00:00

URL: https://externals.io/message/46789#46806 · In reply to: #46805

> Hi!
>
> > […]
>
> Some as all other syntax sugars - better-looking code.

Ah ok, then let say -1 from here for the function()() thing, as I
don't see it as an improvement.

However I would really like the other things described in this thread
about methods.


Cheers,
-- 
Pierre

@pierrejoye | http://blog.thepimp.net | http://www.libgd.org

---

## #46807 — Stanislav Malyshev — 2010-01-19T16:05:36+00:00

URL: https://externals.io/message/46789#46807 · In reply to: #46800

Hi!

> I'd rather see two other things that are missing, support for
> dynamic object and array de-referencing like
> (new class)->method() and get_array()["index"].

The second was next on my list, while the first seems to me kind of 
exotic - why create object only to call one method and immediately drop 
it? Why this method is not static then?

> I honestly don't see func()()()() make anything better in the
> world of a PHP programmer.

You probably don't use closures, right?
-- 
Stanislav Malyshev, Zend Software Architect
stas@zend.com   http://www.zend.com/
(408)253-8829   MSN: stas@zend.com

---

## #46808 — Eddie Drapkin — 2010-01-19T16:20:02+00:00

URL: https://externals.io/message/46789#46808 · In reply to: #46807

> The second was next on my list, while the first seems to me kind of exotic -
> why create object only to call one method and immediately drop it? Why this
> method is not static then?


Why would this imply "dropping" the object?

This:
   $foo = (new bar())->someSetter();
Looks a lot better than this
   $foo = new bar();
   $foo->someSetter();

It's more obvious when you have to store your objects somewhere:
   $foo->bar[$somevar] = (new bar())->someSetter();

Any object that returns $this a lot makes for a valid use case and
right now, we're forced to use a factory method hack, which doesn't
always work, especially in the cases where you have a dynamically
named class (and you can depend on inheritence to guarantee your
method, but not the existence of a static factory method).

What arguments are there against this?  Why shouldn't it be allowed?

---

## #46809 — Rasmus Lerdorf — 2010-01-19T17:02:09+00:00

URL: https://externals.io/message/46789#46809 · In reply to: #46808

Eddie Drapkin wrote:
> 
> > […]
> 
> 
> Why would this imply "dropping" the object?
> 
> This:
>    $foo = (new bar())->someSetter();
> Looks a lot better than this
>    $foo = new bar();
>    $foo->someSetter();

The second version is much clearer.  You know exactly what $foo is.  In
the shortened version you have no idea what $foo is without reading the
code for the someSetter() method.  On first glance I would assume that
$foo would be the success/failure return of the setter and that the
object is dropped.

-Rasmus

---

## #46810 — Chris Stockton — 2010-01-19T17:03:21+00:00

URL: https://externals.io/message/46789#46810 · In reply to: #46789

Hello,


> I wrote a small patch that enables this kind of syntax in PHP:
>
> foo()();
> ...

I think language enhancements with no BC breaks that offer a wider
toolset to programmers is a good thing. I would also like to see the
other ideas in this thread implemented such as array access & object
creation.

The only thing I do not like about this is I do not beleive it fits
the PHP error model. Lets just say Bar::foo($arg) returns a function
callback or FALSE/NULL on a error condition. So you end up with a
function call to something that is not callable, the PHP way under
this case is to have a fatal error. I would rather not see more ways
to cause fatal errors in PHP (call to undefined method has gotten a
bit more popular since object chaining has risen in popularity as
well). Of course I know exceptions are likely out of the question for
these kinds of cases as well. These thoughts do not apply to array
access or object creation.

Regards,

-Chris

---

## #46811 — Lukas Kahwe Smith — 2010-01-19T17:07:03+00:00

URL: https://externals.io/message/46789#46811 · In reply to: #46810

> Hello,
> 
> 
> > […]
> 
> I think language enhancements with no BC breaks that offer a wider
> toolset to programmers is a good thing. I would also like to see the
> other ideas in this thread implemented such as array access & object
> creation.


enhancements in the sense that they enable things that were not possible before, sure. syntax sugar that hurts readability, not really.
if you are worried about key strokes switch to an IDE. if you are worried about performance use a byte code cache.

regards,
Lukas Kahwe Smith
mls@pooteeweet.org

---

## #46812 — Eddie Drapkin — 2010-01-19T17:18:03+00:00

URL: https://externals.io/message/46789#46812 · In reply to: #46809

> Eddie Drapkin wrote:
> > […]
>
> The second version is much clearer.  You know exactly what $foo is.  In
> the shortened version you have no idea what $foo is without reading the
> code for the someSetter() method.  On first glance I would assume that
> $foo would be the success/failure return of the setter and that the
> object is dropped.
>
> -Rasmus
>

I don't think that's necessarily a fair statement to make.  If you
were working within a set of guidelines, or even within just a style,
that "dictated" that setters return $this consistently across several
class (or even all of them), it wouldn't be any less clear than the
second.   Assuming that you had no idea what the class did, or what
any of its methods returned, you could make the argument that the
former is less readable, but then again, if you're making wild guesses
at what methods return without reading code/documentation, you've got
bigger issues than the readability of a constructor + method call.

Even accepting the argument against readability, I don't think it's
strong enough to say that the feature is unacceptable.  If used
properly, it can very well aid in the concision and readability of
code (especially if you're a fan of the "fluent" interface); I don't
agree with the thinking that presenting a case where a feature can be
used improperly is grounds for its dismissal.  Were that the case,
nearly every feature in the language would be able to be dismissed,
no?

And to illustrate what I mean by fluent interface, there's a lot of
cases in code that I've written where I have something that looks
like:

Class::someFactory()->blah()->blah()->foo()->bar()->baz()->hello()->world();
//well, this is a little extreme

Which I think looks much better, and is more self documenting, as:

(new Class())->blah()->blah()->foo()->bar()->baz()->hello()->world();

---

## #46813 — Rasmus Lerdorf — 2010-01-19T17:24:10+00:00

URL: https://externals.io/message/46789#46813 · In reply to: #46812

Eddie Drapkin wrote:
> 
> > […]
> 
> I don't think that's necessarily a fair statement to make.  If you
> were working within a set of guidelines, or even within just a style,
> that "dictated" that setters return $this consistently across several
> class (or even all of them), it wouldn't be any less clear than the
> second.   Assuming that you had no idea what the class did, or what
> any of its methods returned, you could make the argument that the
> former is less readable, but then again, if you're making wild guesses
> at what methods return without reading code/documentation, you've got
> bigger issues than the readability of a constructor + method call.

Wild guesses?  The point is that it doesn't matter what the setter
returns in the longer version because we know for a fact that the return
is dropped whereas it matters a lot in the shorter version and that is
where most people will guess wrong.  And guess what, most people don't
read documentation.  Trust me on this one.

-Rasmus

---

## #46814 — Jared Williams — 2010-01-19T17:26:42+00:00

URL: https://externals.io/message/46789#46814 · In reply to: #46789

> -----Original Message-----
> From: Stanislav Malyshev [mailto:stas@zend.com] 
> Sent: 19 January 2010 00:28
> To: 'PHP Internals'
> Subject: [PHP-DEV] function call chaining
> 
> Hi!
> 
> I wrote a small patch that enables this kind of syntax in PHP:
> 
> foo()();
> 
> What it means is that if foo() returns callable value (which 
> probably should be function name or closure) then it would be 
> called. Parameters and more than two sets of () work too.
> Of course, this is mostly useful for doing closures, and that 
> was primary drive for implementing it - to make working with 
> closures and especially function returning closures easier.
> What does not work currently is $foo->bar()() - since it is 
> surprisingly hard to tell parser it's not {$foo->bar}()() - 
> which of course is not what I want to do.
> 
> The patch is here: http://random-bits-of.info/funcfunc.diff
> 
> What do you think? If somebody has better idea btw - maybe 
> make something like {foo()}() - and make that work for any 
> expression inside {} - that might work too. So, what do you think?
> --
> Stanislav Malyshev, Zend Software Architect
> stas@zend.com   http://www.zend.com/
> (408)253-8829   MSN: stas@zend.com
> 
> --
>  To 
> unsubscribe, visit: http://www.php.net/unsub.php
> 

I've run into problems with 

$foo[1]();

If the closure attempts to change the value of $foo[1] then PHP
complains.
So was forced to assign to a temporary variable before hand.

$f = $foo[1];
$f();

I guessing foo()() could also suffer from the problem?

Jared

---

Next page: https://externals.io/message/46789.md?page=2
