- android - RelativeLayout 背景可绘制重叠内容
- android - 如何链接 cpufeatures lib 以获取 native android 库?
- java - OnItemClickListener 不起作用,但 OnLongItemClickListener 在自定义 ListView 中起作用
- java - Android 文件转字符串
PHP manual for anonymous functions (即闭包)指出:
Anonymous functions are currently implemented using the Closure class. This is an implementation detail and should not be relied upon.
(重点是我自己)
是否可以测试一个变量,以便只有当变量是闭包时测试才返回真,不引用闭包类?
换句话说,当 $bar
不是匿名函数时,我如何重写以下内容以引发错误:
function foo(Closure $bar) { $bar();}
EDIT: Based on the answers received, here is an example test.
Notes:
ReflectionFunction::isClosure()
method seems to be be almost useless: by the time you've done the checks required to make sure that ReflectionFunction can actually be instantiated (can't take a Class except for a Closure), you've eliminated all other options.Code:
/**
* Return true if and only if the passed argument is a Closure.
*/
function testClosure($a) {
// Must be Callback, Labmda, Functor or Closure:
if(!is_callable($a)) return false;
// Elminate Callbacks & Lambdas
if(!is_object($a)) return false;
// Eliminate Functors
//$r = new ReflectionFunction($a); <-- fails if $a is a Functor
//if($r->isClosure()) return true;
return false;
}
测试用例:
//////////// TEST CASE /////////////
class CallBackClass {
function callBackFunc() {
}
}
class Functor {
function __invoke() {
}
}
$functor = new Functor();
$lambda = create_function('', '');
$callback = array('CallBackClass', 'callBackFunc');
$array = array();
$object = new stdClass();
$closure = function() { ; };
echo "Is it a closure? \n";
echo "Closure: " . (testClosure($closure) ? "yes" : "no") . "\n";
echo "Null: " . (testClosure(null) ? "yes" : "no") . "\n";
echo "Array: " . (testClosure($array) ? "yes" : "no") . "\n";
echo "Callback: " . (testClosure($callback) ? "yes" : "no") . "\n";
echo "Labmda: " .(testClosure($lambda) ? "yes" : "no") . "\n";
echo "Invoked Class: " . (testClosure($functor) ? "yes" : "no") . "\n";
echo "StdObj: " . (testClosure($object) ? "yes" : "no") . "\n";
-
最佳答案
你也可以使用
ReflectionFunctionAbstract::isClosure
— 检查是否关闭
例子:
$poorMansLambda = create_function('', 'return TRUE;');
$rf = new ReflectionFunction($poorMansLambda);
var_dump( $rf->isClosure() ); // FALSE
$lambda = function() { return TRUE; };
$rf = new ReflectionFunction($lambda);
var_dump( $rf->isClosure() ); // TRUE
$closure = function() use ($lambda) { return $lambda(); };
$rf = new ReflectionFunction($closure);
var_dump( $rf->isClosure() ); // TRUE
请注意,对于 PHP 5.3 Lambda 和闭包,上面的代码只会返回 TRUE
。如果你只是想知道一个参数是否可以用作回调,is_callable
会表现得更好。
编辑如果您还想包含仿函数,您可以( as of PHP 5.3.3 )
$rf = new ReflectionObject($functorOrClosureOrLambda);
var_dump( $rf->hasMethod('__invoke') ); // TRUE
或
method_exists($functorOrClosureOrLambda, '__invoke');
后者是更快的选择。
一个 Closure
实例基本上只是一个类,它有一个 __invoke
函数,您可以动态地将其提供给方法体。但由于这是对实现细节的测试,我认为它与测试 Closure
类名一样不可靠。
编辑 由于您提到您无法通过反射 API 可靠地进行测试,因为它在将 Functor 传递给 ReflectionFunctionAbstract::isClosure
时引发错误,请尝试以下解决方案满足您的需求:
function isClosure($arg)
{
if(is_callable($arg, FALSE, $name)) {
is_callable(function() {}, TRUE, $implementation);
return ($name === $implementation);
}
}
这将检查传递的参数是否可调用。 $name
参数存储可调用名称。对于闭包,目前是 Closure::__invoke
。由于这对于任何闭包/Lambda 都是相同的,我们可以将传递的参数的名称与任意其他闭包/Lambda 进行比较。如果它们相等,则参数必须是 Closure/Lambda。在运行时确定可调用名称有一个额外的好处,即您不必将关于实现细节的假设硬编码到源代码中。传递仿函数将返回 FALSE
,因为它不会具有相同的可调用名称。由于这不依赖于反射 API,因此它也可能更快一些。
上面的内容可以更优雅地写成
function isClosure($arg) {
$test = function(){};
return $arg instanceof $test;
}
关于php - 在不引用 Closure 内部类的情况下测试 PHP Closure,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4127959/
我是 Java 新手,这是我的代码, if( a.name == b.name && a.displayname == b.displayname && a.linknam
在下面的场景中,我有一个 bool 值。根据结果,我调用完全相同的函数,唯一的区别是参数的数量。 var myBoolean = ... if (myBoolean) { retrieve
我是一名研究 C++ 的 C 开发人员: 我是否正确理解如果我抛出异常然后堆栈将展开直到找到第一个异常处理程序?是否可以在不展开的情况下在任何 throw 上打开调试器(即不离开声明它的范围或任何更高
在修复庞大代码库中的错误时,我观察到一个奇怪的情况,其中引用的动态类型从原始 Derived 类型更改为 Base 类型!我提供了最少的代码来解释问题: struct Base { // some
我正在尝试用 C# 扩展给定的代码,但由于缺乏编程经验,我有点陷入困境。 使用 Visual Studio 社区,我尝试通过控制台读出 CPU 核心温度。该代码使用开关/外壳来查找传感器的特定名称(即
这可能是一个哲学问题。 假设您正在向页面发出 AJAX 请求(这是使用 Prototype): new Ajax.Request('target.asp', { method:"post", pa
我有以下 HTML 代码,我无法在所有浏览器中正常工作: 我试图在移动到
我对 Swift 很陌生。我如何从 addPin 函数中检索注释并能够在我的 addLocation 操作 (buttonPressed) 中使用它。我正在尝试使用压力触摸在 map 上添加图钉,在两
我设置了一个详细 View ,我是否有几个 Nib 文件根据在 Root View Controller 的表中选择的项目来加载。 我发现,对于 Nibs 的类,永远不会调用 viewDidUnloa
我需要动态访问 json 文件并使用以下代码。在本例中,“bpicsel”和“temp”是变量。最终结果类似于“data[0].extit1” var title="data["+bpicsel+"]
我需要使用第三方 WCF 服务。我已经在我的证书存储中配置了所需的证书,但是在调用 WCF 服务时出现以下异常。 向 https://XXXX.com/AHSharedServices/Custome
在几个 SO 答案(1、2)中,建议如果存在冲突则不应触发 INSERT 触发器,ON CONFLICT DO NOTHING 在触发语句中。也许我理解错了,但在我的实验中似乎并非如此。 这是我的 S
如果进行修改,则会给出org.hibernate.NonUniqueObjectException。在我的 BidderBO 类(class)中 @Override @Transactional(pr
我使用 indexOf() 方法来精细地查找数组中的对象。 直到此刻我查了一些资料,发现代码应该无法正常工作。 我在reducer中尝试了上面的代码,它成功了 let tmp = state.find
假设我有以下表格: CREATE TABLE Game ( GameID INT UNSIGNED NOT NULL, GameType TINYINT UNSIGNED NOT NU
代码: Alamofire.request(URL(string: imageUrl)!).downloadProgress(closure: { (progress) in
我是一名优秀的程序员,十分优秀!