Last active
May 26, 2020 18:02
-
-
Save sgolemon/5a541fa86be682692c0276ac8209d18d to your computer and use it in GitHub Desktop.
Typed callables (random musings)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
We can already do this: | |
function foo(Callable $bar) { | |
$bar("Hellow World"); | |
} | |
But that requires foo() to make assumptions about the callback its received. | |
If it's invoked with a callback that doesn't take precisely one string argument, then things will break. | |
function ItakeNoArgs() {} | |
foo('ItakeNoArgs'); | |
foo('IdontEvenExist'); | |
foo(function($a, $b) { /* I take more than one args */ }); | |
foo(function(array $x) { /* I don't allow strings */ }); | |
What if we could type our callbacks? | |
HackLang has this: https://docs.hhvm.com/hack/functions/introduction#function-types | |
function foo((function(string): void) $bar) { | |
$bar("Hello World"); | |
} | |
Even if we use `fn` as with short lambdas, those signatures get pretty heavy, pretty quickly. | |
HackLang addresses that problem with aliases: https://docs.hhvm.com/hack/types/type-aliases | |
type BarCallback = function(string): void; | |
function foo(BarCallback $bar) {...} | |
A possible alternative syntax might be prototype declarations: | |
function BarCallback(string): void; | |
function foo(BarCallback $bar) {..} | |
Ultimately, these all have the problem of runtime enforcement where the callable | |
has to be resolved to reflectable signatures. | |
Object instances implemeting the __invoke() magic method are probably the simplest to identify. | |
Class/object methods have the issue of visibility. Even if the method isn't visible to the | |
function receiving the callable, it may be valid to pass it through to a subordinate method | |
which does have visibility. | |
Global function (string) callables are the most complicated as they lack autoloading, | |
and namespace resolution is a question without an easy ansewr. |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment