可以通过引用传递函数吗?
像这样:
function call($func){
$func();
}
function test(){
echo "hello world!";
}
call(test);
我知道你可以做'test'
,但我真的不想这样,因为我需要通过引用传递函数。
这是通过匿名函数执行此操作的唯一方法吗?
澄清:如果您从C++中回想一下,您可以通过指针传递函数:
void call(void (*func)(void)){
func();
}
或者在 Python 中:
def call(func):
func()
这就是我想要实现的目标。
对于它的价值,给这样的东西一个机会怎么样?(是的,我知道这是一个匿名函数,在帖子中提到过,但我对大量根本没有提到闭包/函数对象的回复感到不满,所以这主要是对遇到这篇文章的人的注释。
我不使用 PHP,但使用闭包似乎适用于 PHP 5.3(但不是 PHP 5.2(,如此处所示。我不确定有什么限制,如果有的话。(据我所知,关闭会吃掉你的孩子。你已经被警告了。
function doIt ($fn) {
echo "doIt'n";
return $fn();
}
function doMe () {
echo "doMe'n";
}
// I am using a closure here.
// There may be a more clever way to "get the function-object" representing a given
// named function, but I do not know what it is. Again, I *don't use PHP* :-)
echo doIt(function () { doMe(); });
快乐编码。
call_user_func()
的问题在于你传递的是所调用函数的返回值,而不是函数本身。
我以前也遇到过这个问题,这是我想出的解决方案。
function funcRef($func){
return create_function('', "return call_user_func_array('{$func}', func_get_args());");
}
function foo($a, $b, $c){
return sprintf("A:%s B:%s C:%s", $a, $b, $c);
}
$b = funcRef("foo");
echo $b("hello", "world", 123);
//=> A:hello B:world C:123
ideone.com 演示
不,函数不是 PHP 中的第一类值,它们不能通过名称文字传递(这是您所要求的(。即使是匿名函数或通过create_function
创建的函数也由对象或字符串引用传递。
可以将函数的名称作为字符串传递,将对象方法的名称作为数组传递(object, string)
或者将匿名函数作为对象传递。这些传递指针或引用都不是,它们只是传递函数的名称。所有这些方法都称为callback
伪类型:http://php.net/callback
function func1(){
echo 'echo1 ';
return 'return1';
}
function func2($func){
echo 'echo2 ' . $func();
}
func2('func1');
结果:
echo1 echo2 return1
在 PHP 5.4.4 中(尚未测试过较低版本或其他版本(,您可以完全按照您的建议进行操作。
以这个为例:
function test ($func) {
$func('moo');
}
function aFunctionToPass ($str) {
echo $str;
}
test('aFunctionToPass');
脚本将回显"moo",就像您直接调用"aFunctionToPass"一样。
Javascript第一类函数的类似模式:
function add(first, second, callback){
console.log(first+second);
if (callback) callback();
}
function logDone(){
console.log('done');
}
function logDoneAgain(){
console.log('done Again');
}
add(2,3, logDone);
add(3,5, logDoneAgain);
可以在PHP中通过以下方式完成(在C9 IDE上使用5.5.9-1ubuntu测试(:
// first class function
$add = function($first, $second, $callback) {
echo "'n'n". $first+$second . "'n'n";
if ($callback) $callback();
};
function logDone(){
echo "'n'n done 'n'n";
}
call_user_func_array($add, array(2, 3, logDone));
call_user_func_array($add, array(3, 6, function(){
echo "'n'n done executing an anonymous function!";
}));
结果:5 完成 9 完成执行匿名函数!
参考: https://github.com/zenithtekla/unitycloud/commit/873659c46c10c1fe5312f5cde55490490191e168
可以通过在声明函数时将函数分配给局部变量来创建引用:
$test = function() {
echo "hello world!";
};
function call($func){
$func();
}
call($test);
你可以说
$fun = 'test';
call($fun);
而不是call(test);
,使用 call_user_func('test');
。
从 PHP 8.1 开始,您可以使用 First 类可调用对象:
call(test(...));
您甚至可以使用方法:
call($obj->test(...));
就这么简单。
似乎有点不清楚为什么要通过引用传递函数?通常,仅当引用的数据需要(可能(由函数修改时,才会通过引用传递内容。
由于 PHP 使用数组或字符串来引用函数,因此您可以通过引用传递数组或字符串,这将允许修改函数引用。
例如,您可以执行以下操作
<?php
$mysort = function($a, b) { return ($a < $b) ? 1 : -1; };
adjust_sort_from_config($mysort); // modifies $mysort
do_something_with_data($mysort);
哪里
<?php
function load_my_configuration(&$fun)
{
$sort_memory = new ...;
...
$fun = [$sort_memory, "customSort"];
// or simply
$fun = function($a, b) { return (rand(1,10) < 4 ? 1 : -1; };
}
这是有效的,因为有三种方法可以通过变量引用 PHP 中的函数:
- $name – 字符串 $name 包含全局命名空间中应调用的函数的名称
- array($object, $name( – 指对象$object的字符串$name的方法。
- array($class, $name( – 指类 $class 的静态函数字符串$name。
如果我没记错的话,这些构造所指向的方法和静态函数必须是公共的。鉴于足够新的PHP版本,"第一类可调用语法"应该可以改善此限制,但它似乎只是Closure::fromCallable()
周围的一些语法糖。
匿名函数在后台的工作方式相同。您只是在任何地方都看不到这些函数的文字随机名称,但对匿名函数的引用也只是一个变量的值。