On Thu, Apr 20, 2023, at 7:30 PM, Dan Ackroyd wrote:
> On Thu, 20 Apr 2023 at 18:25, Larry Garfield <la...@garfieldtech.com> wrote:
>>
>> Hi folks.  This is a pre-discussion, in a sense, before a formal RFC.
>
>
> Hi Larry,
>
> The "Allow casting closures into single-method interface
> implementations" one seems a complete non-starter, as that seems
> really hard to work with. You'd have to do lots of "wiring up" to do
> any significant amount of programming.

That's my concern as well, and part of what led me to suggest the structural 
typing approach.  

> "Allow Closures to Declare Interfaces they Implement"
>
> That sounds bad as it doesn't allow arbitrary functions to be used as 
> callables.

Yes.  Which is why I think it would make the most sense when combined with one 
of the other two options, so it's a sort of performance optimization for the 
general case.

>> We feel that the interface-based approach is strong
>
> All three of them are using interfaces...?

I'm referring to the general idea of this thread, which is "an interface with 
__invoke is how you define a callable type."  Everything else here is a 
variation on that basic premise.

> But if you mean the "Structural Typing for Closures" one, then I'd
> probably agree. But as currently proposed it seems like a hack, that
> would be predictably regrettable in a couple of years.

In what way?

>> and a good way forward for getting typed callables
>> without a bunch of dependent features needed first.
>
> Maybe list what you think the dependent features are, so that there
> isn't confusion about them, but I suspect that we're going to not
> agree on how languages should be designed and evolve.

Mainly the type alias question.  Every time I see callable types discussed, it 
immediately sidetracks into "how do we make that less fugly to write, because 
callable types are naturally very verbose?"  That leads directly to 
typedefs/type aliases, which take one of two forms:

type TwoInts = callable(int $x, int $y): int
type LinkedResponse = ResponseInterface&LinkCollectionInterface

which raises autoloading questions and means a dependency on a type defined in 
another package, in many cases.  Or:

use callable(int $x, int $y): int as TwoInts
use ResponseInterface&LinkCollectionInterface as LinkedResponse

Which would be file-local, much like class "use" statements are.  That avoids 
the autoload and dependency problem, at the cost of having to retype that 
frickin' thing in every file where it's relevant.  In many cases, that could be 
dozens or hundreds of files repeating that line.

And that's where the discussion usually dies off.

As noted, this is still a form of structural typing, which means the function 
call process necessarily gets more complex (for callables).

Using existing interfaces for callable definitions side steps the 
implementation challenges of type aliases/typedefs, since once you have an 
object tagged with an interface (via any of the mechanisms described), its 
behavior is already very well-defined and predictable.

> Although I really want to see typed callables, and other forms of type
> aliasing, as they would be huge improvements in being able to write
> code that is easy to reason about and maintain, I don't want to seem
> them as soon as possible, having taken short-cuts against good
> language design.
>
> "No is temporary, yes is forever".

I'm happy to see forward motion on any front.  If the result of this thread is 
that someone gets incentivized to finally figure out callable types for 
realsies without an interface, I'd sleep happy with that result.  But this 
gives us something concrete to chew on, which we have so far lacked.

--Larry Garfield

-- 
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: https://www.php.net/unsub.php

Reply via email to