Re: [PHP-DEV] [RFC]

This is only part of a thread. view whole thread
  108488
February 11, 2020 16:48 Danack@basereality.com (Dan Ackroyd)
Nicolas Grekas wrote:
> I wish this would return a Closure instead, making $foo::function the > equivalent of Closure::fromCallable($foo).
I didn't include the following in that RFC, because I thought it would be too controversial, but I think it's worth considering a new syntax for this. Given the code: function foo(); class Zoq { public function Fot() {} public static function Pik() {} } $obj = new Zoq(); Then these: $(foo); $($obj, Fot); $(Zoq, Fot); Would be equivalent to: Closure::fromCallable('foo'); Closure::fromCallable([$obj, 'Fot']); Closure::fromCallable('Zoq::Fot'); or Closure::fromCallable(['Zoq', 'Fot']); Or similar. The justification for having a dedicated syntax is that I think readability is quite important in code, and it's reasonably common for me to have quite long lists of 'callables'. [Bar::class, foo1::function], [Bar::class, foo2::function], [Bar::class, foo3::function], [Bar::class, foo4::function] vs $(Bar, foo1), $(Bar, foo2), $(Bar, foo3), $(Bar, foo4) The latter is far easier to read for me. Nikita Popov wrote:
> This would circumvent all the issues outlined in > https://wiki.php.net/rfc/consistent_callables.
Probably there would still be some issues with some of the weird stuff happening internally in SPL related code where the deep horrors rest...but we can leave them alone...and they might not wake. cheers Dan Ack
  108490
February 11, 2020 17:21 manuelcanga@gmail.com (Manuel Canga)
On Tue, 11 Feb 2020 at 17:49, Dan Ackroyd <Danack@basereality.com> wrote:
> > Nicolas Grekas wrote: > > I wish this would return a Closure instead, making $foo::function the > > equivalent of Closure::fromCallable($foo). > > I didn't include the following in that RFC, because I thought it would > be too controversial, but I think it's worth considering a new syntax > for this. > > Given the code: > > function foo(); > class Zoq { > public function Fot() {} > public static function Pik() {} > } > $obj = new Zoq(); > > > Then these: > > $(foo); > $($obj, Fot); > $(Zoq, Fot); > > Would be equivalent to: > > Closure::fromCallable('foo'); > Closure::fromCallable([$obj, 'Fot']); > Closure::fromCallable('Zoq::Fot'); or Closure::fromCallable(['Zoq', 'Fot']); > > Or similar. > > The justification for having a dedicated syntax is that I think > readability is quite important in code, and it's reasonably common for > me to have quite long lists of 'callables'. > > [Bar::class, foo1::function], > [Bar::class, foo2::function], > [Bar::class, foo3::function], > [Bar::class, foo4::function] > > vs > > $(Bar, foo1), > $(Bar, foo2), > $(Bar, foo3), > $(Bar, foo4) > > The latter is far easier to read for me. > > Nikita Popov wrote: > > This would circumvent all the issues outlined in > > https://wiki.php.net/rfc/consistent_callables. > > Probably there would still be some issues with some of the weird stuff > happening internally in SPL related code where the deep horrors > rest...but we can leave them alone...and they might not wake. > > cheers > Dan > Ack
Hi, Dan, I like it, although syntax reminds me to JQuery syntax. Thanks
  108492
February 11, 2020 17:41 manuelcanga@gmail.com (Manuel Canga)
On Tue, 11 Feb 2020 at 17:49, Dan Ackroyd <Danack@basereality.com> wrote:
> > Nicolas Grekas wrote: > > I wish this would return a Closure instead, making $foo::function the > > equivalent of Closure::fromCallable($foo). > > I didn't include the following in that RFC, because I thought it would > be too controversial, but I think it's worth considering a new syntax > for this. > > Given the code: > > function foo(); > class Zoq { > public function Fot() {} > public static function Pik() {} > } > $obj = new Zoq(); > > > Then these: > > $(foo); > $($obj, Fot); > $(Zoq, Fot); > > Would be equivalent to: > > Closure::fromCallable('foo'); > Closure::fromCallable([$obj, 'Fot']); > Closure::fromCallable('Zoq::Fot'); or Closure::fromCallable(['Zoq', 'Fot']); > > Or similar. > > The justification for having a dedicated syntax is that I think > readability is quite important in code, and it's reasonably common for > me to have quite long lists of 'callables'. > > [Bar::class, foo1::function], > [Bar::class, foo2::function], > [Bar::class, foo3::function], > [Bar::class, foo4::function] > > vs > > $(Bar, foo1), > $(Bar, foo2), > $(Bar, foo3), > $(Bar, foo4) > > The latter is far easier to read for me. > > Nikita Popov wrote: > > This would circumvent all the issues outlined in > > https://wiki.php.net/rfc/consistent_callables. > > Probably there would still be some issues with some of the weird stuff > happening internally in SPL related code where the deep horrors > rest...but we can leave them alone...and they might not wake. > > cheers > Dan > Ack
Other option: Closure::fromCallable('foo'); Closure::fromCallable([$obj, 'Fot']); Closure::fromCallable('Zoq::Fot'); or Closure::fromCallable(['Zoq', 'Fot']); to <$foo, Fot> E.g: array_map(, $array); array_map(, $array); Do you like ?
  108495
February 11, 2020 19:01 michal.brzuchalski@gmail.com (=?UTF-8?Q?Micha=C5=82_Brzuchalski?=)
wt., 11 lut 2020, 18:42 użytkownik Manuel Canga <manuelcanga@gmail.com>
napisał:

> On Tue, 11 Feb 2020 at 17:49, Dan Ackroyd <Danack@basereality.com> wrote: > > > > Nicolas Grekas wrote: > > > I wish this would return a Closure instead, making $foo::function the > > > equivalent of Closure::fromCallable($foo). > > > > I didn't include the following in that RFC, because I thought it would > > be too controversial, but I think it's worth considering a new syntax > > for this. > > > > Given the code: > > > > function foo(); > > class Zoq { > > public function Fot() {} > > public static function Pik() {} > > } > > $obj = new Zoq(); > > > > > > Then these: > > > > $(foo); > > $($obj, Fot); > > $(Zoq, Fot); > > > > Would be equivalent to: > > > > Closure::fromCallable('foo'); > > Closure::fromCallable([$obj, 'Fot']); > > Closure::fromCallable('Zoq::Fot'); or Closure::fromCallable(['Zoq', > 'Fot']); > > > > Or similar. > > > > The justification for having a dedicated syntax is that I think > > readability is quite important in code, and it's reasonably common for > > me to have quite long lists of 'callables'. > > > > [Bar::class, foo1::function], > > [Bar::class, foo2::function], > > [Bar::class, foo3::function], > > [Bar::class, foo4::function] > > > > vs > > > > $(Bar, foo1), > > $(Bar, foo2), > > $(Bar, foo3), > > $(Bar, foo4) > > > > The latter is far easier to read for me. > > > > Nikita Popov wrote: > > > This would circumvent all the issues outlined in > > > https://wiki.php.net/rfc/consistent_callables. > > > > Probably there would still be some issues with some of the weird stuff > > happening internally in SPL related code where the deep horrors > > rest...but we can leave them alone...and they might not wake. > > > > cheers > > Dan > > Ack > > Other option: > > Closure::fromCallable('foo'); > Closure::fromCallable([$obj, 'Fot']); > Closure::fromCallable('Zoq::Fot'); or Closure::fromCallable(['Zoq', > 'Fot']); > > to > > > <$foo, Fot> > > > > E.g: > > array_map(, $array); > array_map(, $array); > > Do you like ? >
That reminds me an old draft RFC https://wiki.php.net/rfc/short-closures where I thought curly braces can be used to create closure from syntax nearly the same as invoking but without parentheses. That way we can provide clear intent - I mean if whatever is around: curly braces or $ with parentheses IMHO it should be consistent with call like format. For example: $(strlen) or {strlen} for Closure::fromCallable('foo') $($foo->Fot) or {$foo->Fot} for Closure::fromCallable([$obj, 'Fot']) $(Zoq::Fot) or {Zoq::Fot} for Closure::fromCallable('Zoq::Fot') Etc. The same inside like a call but wrapped in something and with no parentheses part. Cheers, -- Michał Brzuchalski
>
  108500
February 11, 2020 20:14 d.h.j.takken@freedom.nl (Dik Takken)
On 11-02-2020 20:01, Michał Brzuchalski wrote:
> wt., 11 lut 2020, 18:42 użytkownik Manuel Canga <manuelcanga@gmail.com> > napisał: > > That reminds me an old draft RFC https://wiki.php.net/rfc/short-closures > where I thought curly braces can be used to create closure from syntax > nearly the same as invoking but without parentheses.
My message mentioning just about the same idea crossed yours. Thanks for pointing at this RFC, I think it just caught our attention again. :) I quickly scanned the list to see if your RFC was discussed and all I could find was threads about a different RFC with almost identical name (https://wiki.php.net/rfc/short_closures). Has it not been discussed before? Regards, Dik Takken
  108501
February 11, 2020 21:06 michal.brzuchalski@gmail.com (=?UTF-8?Q?Micha=C5=82_Brzuchalski?=)
wt., 11 lut 2020, 21:14 użytkownik Dik Takken takken@freedom.nl>
napisał:

> On 11-02-2020 20:01, Michał Brzuchalski wrote: > > wt., 11 lut 2020, 18:42 użytkownik Manuel Canga <manuelcanga@gmail..com> > > napisał: > > > > That reminds me an old draft RFC https://wiki.php.net/rfc/short-closures > > where I thought curly braces can be used to create closure from syntax > > nearly the same as invoking but without parentheses. > > My message mentioning just about the same idea crossed yours. Thanks for > pointing at this RFC, I think it just caught our attention again. :) > > I quickly scanned the list to see if your RFC was discussed and all I > could find was threads about a different RFC with almost identical name > (https://wiki.php.net/rfc/short_closures). Has it not been discussed > before? >
No, it hasn't been discussed. It stopped at being a draft. BR, -- Michał Brzuchalski
>
  108496
February 11, 2020 19:08 d.h.j.takken@freedom.nl (Dik Takken)
On 11-02-2020 17:48, Dan Ackroyd wrote:
> I didn't include the following in that RFC, because I thought it would > be too controversial, but I think it's worth considering a new syntax > for this. > > Given the code: > > function foo(); > class Zoq { > public function Fot() {} > public static function Pik() {} > } > $obj = new Zoq(); > > > Then these: > > $(foo); > $($obj, Fot); > $(Zoq, Fot); > > Would be equivalent to: > > Closure::fromCallable('foo'); > Closure::fromCallable([$obj, 'Fot']); > Closure::fromCallable('Zoq::Fot'); or Closure::fromCallable(['Zoq', 'Fot']); > > Or similar.
Given the fact that $() would only accept functions and methods as argument, this idea could be taken one step further by writing: $(foo); $($obj->Fot); $(Zoq::Fot); Referring to a method like this is normally not possible because it is ambiguous. However, wrapped inside $(), which only accepts functions and methods, the ambiguity disappears. The $() syntax is nice and short. And something completely new. As new syntax can only be 'spent' once, more familiar alternatives should be explored as well. Thinking about the existing list() and array() syntax, another possibility could be: closure(foo); closure($obj->Fot); closure(Zoq::Fot); It is slightly longer but more familiar syntax. On 11-02-2020 19:46, Larry Garfield wrote:
> > I would love a nicer way to reference function names; it's really ugly to do functional code in PHP otherwise, or even just dynamic function
logic within a namespace. If I never have to write $fn = __NAMESPACE__ .. '\a_func' again, it will be too soon. :-) Perhaps Larry can convince us all to go for something like $() by posting a fabulous functional programming example? Regards, Dik Takken
  108497
February 11, 2020 19:20 Danack@basereality.com (Dan Ackroyd)
On Tue, 11 Feb 2020 at 19:08, Dik Takken takken@freedom.nl> wrote:

> $($obj->Fot); > However, wrapped inside $(), which only accepts > functions and methods
I don't think I meant that. I think it still should accept variables as well, so it would still be ambiguous as to whether it referred to the value of the property Fot of object $obj, or the method Fot on the $obj class. Also, just in general using something that has the same syntax as current PHP code, but a different meaning, sounds like a bad idea.
> another possibility could be: closure(foo);
That has the downside of exposing the implementation detail, that it's implemented through closures, which would be a regrettable choice if we ever decided to change the implementation details in the future. And it also has the downside of looking like a function call, but having different rules for what can be put inside it: function foo(); closure(foo); // fine. special_closure(foo); // syntax error, undefined constant foo. Although avoiding new syntax is good in general, if what can go inside it is different, then I think it requires a new syntax. cheers Dan Ack
  108499
February 11, 2020 20:11 d.h.j.takken@freedom.nl (Dik Takken)
On 11-02-2020 20:20, Dan Ackroyd wrote:
> On Tue, 11 Feb 2020 at 19:08, Dik Takken takken@freedom.nl> wrote: > >> $($obj->Fot); >> However, wrapped inside $(), which only accepts >> functions and methods > > I don't think I meant that. I think it still should accept variables > as well, so it would still be ambiguous as to whether it referred to > the value of the property Fot of object $obj, or the method Fot on the > $obj class.
In that case, the ambiguity issue remains. I was thinking about it as a construct for wrapping functions and methods into closures. Could you provide an example of how accepting variables would be useful?
>> another possibility could be: closure(foo); > > That has the downside of exposing the implementation detail, that it's > implemented through closures, which would be a regrettable choice if > we ever decided to change the implementation details in the future.
I don't think I understand. Creating a closure is something you do because of the specific semantics they have. The fact that it yields a closure is not a detail, it is the reason why I would use it...
> And it also has the downside of looking like a function call, but > having different rules for what can be put inside it: > > function foo(); > closure(foo); // fine. > special_closure(foo); // syntax error, undefined constant foo.
That is a downside indeed. Regards, Dik Takken
  108498
February 11, 2020 19:22 michal.brzuchalski@gmail.com (=?UTF-8?Q?Micha=C5=82_Brzuchalski?=)
wt., 11 lut 2020, 20:08 użytkownik Dik Takken takken@freedom.nl>
napisał:

> On 11-02-2020 17:48, Dan Ackroyd wrote: > > I didn't include the following in that RFC, because I thought it would > > be too controversial, but I think it's worth considering a new syntax > > for this. > > > > Given the code: > > > > function foo(); > > class Zoq { > > public function Fot() {} > > public static function Pik() {} > > } > > $obj = new Zoq(); > > > > > > Then these: > > > > $(foo); > > $($obj, Fot); > > $(Zoq, Fot); > > > > Would be equivalent to: > > > > Closure::fromCallable('foo'); > > Closure::fromCallable([$obj, 'Fot']); > > Closure::fromCallable('Zoq::Fot'); or Closure::fromCallable(['Zoq', > 'Fot']); > > > > Or similar. > > Given the fact that $() would only accept functions and methods as > argument, this idea could be taken one step further by writing: > > $(foo); > $($obj->Fot); > $(Zoq::Fot); > > Referring to a method like this is normally not possible because it is > ambiguous. However, wrapped inside $(), which only accepts functions and > methods, the ambiguity disappears. > > The $() syntax is nice and short. And something completely new. As new > syntax can only be 'spent' once, more familiar alternatives should be > explored as well. Thinking about the existing list() and array() syntax, > another possibility could be: > > closure(foo); > closure($obj->Fot); > closure(Zoq::Fot); >
It looks like a function but it's not a function cause what you have inside parentheses looks like a const, property and class const. IMO a statement like that for consistency it should be with no parentheses like: $foo = closure foo; $foo = closure $obj->Fot; $foo = closure Zoq::Fot; Cheers, -- Michał Brzuchalski
>
  108542
February 13, 2020 16:55 larry@garfieldtech.com ("Larry Garfield")
On Tue, Feb 11, 2020, at 1:08 PM, Dik Takken wrote:

> On 11-02-2020 19:46, Larry Garfield wrote: > > > > I would love a nicer way to reference function names; it's really ugly > to do functional code in PHP otherwise, or even just dynamic function > logic within a namespace. If I never have to write $fn = __NAMESPACE__ > . '\a_func' again, it will be too soon. :-) > > Perhaps Larry can convince us all to go for something like $() by > posting a fabulous functional programming example?
I walked right into that one, didn't I... Well, Dik asked me to post a "fabulous functional programming example". I dont' have one, so I'll go with one from the book I'm working on instead. :-) This is what I have now, assuming all global functions: $result = Stats::of($string) ->analyze('normalizeNewlines') ->analyze('readingLevel') ->analyze('countStats') ->analyze(fn($s) => wordDistribution($s, 3)) ; I think we are all in agreement that is sub-optimal. If using functions in the `Stats\Analyzer` namespace, you end up with this: $result = Stats::of($string) ->analyze('\Stats\Analyzer\normalizeNewlines') ->analyze('\Stats\Analyzer\readingLevel') ->analyze('\Stats\Analyzer\countStats') ->analyze(fn($s) => \Stats\Analyzer\wordDistribution($s, 3)) ; Or if you're in that namespace (as I often am) you can do: $ns = __NAMESPACE__; $result = Stats::of($string) ->analyze($ns . '\normalizeNewlines') ->analyze($ns . '\readingLevel') ->analyze($ns . '\countStats') ->analyze(fn($s) => \Stats\Analyzer\wordDistribution($s, 3)) ; This is doubleplusungood. I'll expand the example to use some methods, too, for variety's sake: $result = Stats::of($string) ->analyze('normalizeNewlines') ->analyze('readingLevel') ->analyze('countStats') ->analyze([$synonymSuggester, 'analyze']) ->analyze([WordCouter::class, 'analyze']) ->analyze(fn($s) => wordDistribution($s, 3)) ; As I understand it, the goal in this thread is to: 1) Make code like the above more statically analyziable by not using strings. (That covers a number of areas.) 2) Make code like the above easier to write by using symbols rather than strings. In each case, the analyze() method wants a callable with a specific signature. Enforced callable signatures are *absolutely something we desperately need*, but are not the scope at the moment. In this example, then, that a function name is a string is incidental; what we care about is that it's callable. I don't have a good example off hand for it actually wanting a string, although strings are callables. So, given this import block: use Stats\Analyzer\normalizeNewlines; use Stats\Analyzer\readingLevel; use Stats\Analyzer\countStats; use Stats\Analyzer\normalizeNewlines; use Stats\Analyzer\wordDistribution; use Stats\Analyzer\Stats; use Stats\Analyzer\WordCounter; here's the above example cast into a number of the different proposals floating about this thread: ::function $result = Stats::of($string) ->analyze(normalizeNewlines::function) ->analyze(readingLevel::function) ->analyze(countStats::function) ->analyze([$synonymSuggester, 'analyze']) ->analyze([WordCouter::class, 'analyze']) ->analyze(fn($s) => wordDistribution($s, 3)) ; Analysis: I stand by my earlier statement that ::function is just too damned long for this funtionality. Not when already reserved shorter options exist. ::fn $result = Stats::of($string) ->analyze(normalizeNewlines::fn) ->analyze(readingLevel::fn) ->analyze(countStats::fn) ->analyze([$synonymSuggester, 'analyze']) ->analyze([WordCouter::class, 'analyze']) ->analyze(fn($s) => wordDistribution($s, 3)) ; Analysis: Same thing, less typing. ::name $result = Stats::of($string) ->analyze(normalizeNewlines::name) ->analyze(readingLevel::name) ->analyze(countStats::name) ->analyze([$synonymSuggester, 'analyze']) ->analyze([WordCouter::name, 'analyze']) ->analyze(fn($s) => wordDistribution($s, 3)) ; Analysis: This one gives us unification between classes and functions. I think that would be good, although it's not a hard requirement for the functionality. Any of the above could be expanded, potentially, to include methods, like so: ::name, for methods, too $result = Stats::of($string) ->analyze(normalizeNewlines::name) ->analyze(readingLevel::name) ->analyze(countStats::name) ->analyze([$synonymSuggester, analyze::name]) ->analyze([WordCouter::name, analyze::name]) ->analyze(fn($s) => wordDistribution($s, 3)) ; However, that requires the parser being able to tell the difference between analyze::name inside a callable array and not. That's... potentially complicated, since you can also just have an array that contains both objects and strings, or objects and callables, especially as objects can also be callables with __invoke(). $() or variations thereof $result = Stats::of($string) ->analyze($(normalizeNewlines)) ->analyze($(readingLevel)) ->analyze($(countStats)) ->analyze($($synonymSuggester, 'analyze')) ->analyze($(WordCouter::class, 'analyze')) ->analyze(fn($s) => wordDistribution($s, 3)) ; Analysis: I'm not sure I like this one, visually. "($(..))" feels like a lot of sigils soup. It also doesn't offer a way to deal with the method names in the object versions, unless we just assume that bare strings are allowed there, like so: $result = Stats::of($string) ->analyze($(normalizeNewlines)) ->analyze($(readingLevel)) ->analyze($(countStats)) ->analyze($($synonymSuggester, analyze)) ->analyze($(WordCouter::class, analyze)) ->analyze(fn($s) => wordDistribution($s, 3)) ; I will say that, given the behavior of ::class now, ::fn or ::name "feel like" they should return a string, whereas $() "feels like" it should return a callable, or something richer than a string. That's naturally subjective but is consistent with ::foo being a constant value and $() being, um, jQuery. Also suggested was this: closure() $result = Stats::of($string) ->analyze(closure(normalizeNewlines)) ->analyze(closure(readingLevel)) ->analyze(closure(countStats)) ->analyze(closure($synonymSuggester->analyze)) ->analyze(closure(WordCouter::analyze)) ->analyze(fn($s) => wordDistribution($s, 3)) ; Which aside from being verbose really does look an awful lot like a function call, and is how I'd interpret it. That said, a syntax that would recognize `$foo->bar` as a callable, not an invocation, and `Foo::bar` as a callable, would be really nice. Of course... I feel compelled to ask why we can't just use bare function names. Treating a bare string as a string has been deprecated for several versions. If we remove that in PHP 8 and instead let it mean constant, then function, then class name, the following would become legal: $result = Stats::of($string) ->analyze(normalizeNewlines) ->analyze(readingLevel) ->analyze(countStats) ->analyze([$synonymSuggester, analyze]) ->analyze([WordCouter, analyze]) ->analyze(fn($s) => wordDistribution($s, DISTRIBUTION_LIMIT)) ; Which would be much more in line with how many other languages handle symbol names. (There is likely some engine reason why it's way harder than I make it sound; I'd love to hear what that is so I know not to suggest it again, unless it really is that simple in which case...) In all, I don't think there's a clear obvious winner here. All of the options have some kind of trade-off. My own preferences lean toward: 1) Keep it short; we don't need more long words. 2) No more parentheses; in context, there will be ample parentheses already anywhere a function is being referenced as a callable, so let's not drift more toward LISP. (This is why I don't think "well wrap it in fromCallable()" is a good answer.) 3) Handling method callables at the same time is *not* required, but would be really good for a complete solution. --Larry Garfield
  108554
February 13, 2020 23:13 d.h.j.takken@freedom.nl (Dik Takken)
On 13-02-2020 17:55, Larry Garfield wrote:
> I walked right into that one, didn't I...
You did. :)
> Well, Dik asked me to post a "fabulous functional programming example". I dont' have one, so I'll go with one from the book I'm working on instead. :-)
Thanks, much appreciated.
> $() or variations thereof > > $result = Stats::of($string) > ->analyze($(normalizeNewlines)) > ->analyze($(readingLevel)) > ->analyze($(countStats)) > ->analyze($($synonymSuggester, 'analyze')) > ->analyze($(WordCouter::class, 'analyze')) > ->analyze(fn($s) => wordDistribution($s, 3)) > ; > > Analysis: I'm not sure I like this one, visually. "($(..))" feels like a lot of sigils soup. It also doesn't offer a way to deal with the method names in the object versions, unless we just assume that bare strings are allowed there, like so: > > $result = Stats::of($string) > ->analyze($(normalizeNewlines)) > ->analyze($(readingLevel)) > ->analyze($(countStats)) > ->analyze($($synonymSuggester, analyze)) > ->analyze($(WordCouter::class, analyze)) > ->analyze(fn($s) => wordDistribution($s, 3)) > ;
If the $() construct would only accept methods then it provides an environment without the usual ambiguity and we can write: $result = Stats::of($string) ->analyze($(normalizeNewlines)) ->analyze($(readingLevel)) ->analyze($(countStats)) ->analyze($($synonymSuggester->analyze)) ->analyze($(WordCouter::analyze)) ->analyze(fn($s) => wordDistribution($s, 3)); The RFC of Michał (https://wiki.php.net/rfc/short-closures) would yield: $result = Stats::of($string) ->analyze({normalizeNewlines}) ->analyze({readingLevel}) ->analyze({countStats}) ->analyze({$synonymSuggester->analyze}) ->analyze({WordCouter::analyze}) ->analyze(fn($s) => wordDistribution($s, 3)); To me this looks less soup-ish compared to using $().
> I will say that, given the behavior of ::class now, ::fn or ::name "feel like" they should return a string, whereas $() "feels like" it should return a callable, or something richer than a string. That's naturally subjective but is consistent with ::foo being a constant value and $() being, um, jQuery.
Although a closure would also be a constant I share your 'feel like' issue. It might just need getting used to.
> Of course... I feel compelled to ask why we can't just use bare function names. Treating a bare string as a string has been deprecated for several versions. If we remove that in PHP 8 and instead let it mean constant, then function, then class name, the following would become legal: > > $result = Stats::of($string) > ->analyze(normalizeNewlines) > ->analyze(readingLevel) > ->analyze(countStats) > ->analyze([$synonymSuggester, analyze]) > ->analyze([WordCouter, analyze]) > ->analyze(fn($s) => wordDistribution($s, DISTRIBUTION_LIMIT)) > ; > > Which would be much more in line with how many other languages handle symbol names. (There is likely some engine reason why it's way harder than I make it sound; I'd love to hear what that is so I know not to suggest it again, unless it really is that simple in which case...)
I guess using bare function names in that context could be supported. I would prefer getting rid of these awkward array constructs altogether though and just write $synonymSuggester->analyze in stead. This requires a context that only accepts methods, which is what $() or {} could provide. As a side note, I would love to have a name for these closure producing constructs we are talking about. Maybe: 'enclosure'? Regards, Dik Takken