【发布时间】:2009-10-27 15:19:08
【问题描述】:
此代码产生的结果为 56。
function x ($y) {
function y ($z) {
return ($z*2);
}
return($y+3);
}
$y = 4;
$y = x($y)*y($y);
echo $y;
知道里面发生了什么吗?我很困惑。
【问题讨论】:
-
听上去像是一道作业题,不过还是个好题哈哈。
此代码产生的结果为 56。
function x ($y) {
function y ($z) {
return ($z*2);
}
return($y+3);
}
$y = 4;
$y = x($y)*y($y);
echo $y;
知道里面发生了什么吗?我很困惑。
【问题讨论】:
X 返回(值 +3),而 Y 返回(值*2)
给定值 4,这意味着 (4+3) * (4*2) = 7 * 8 = 56。
虽然函数的范围不受限制(这意味着您可以安全地“嵌套”函数定义),但这个特定示例很容易出错:
1) 不能在调用x() 之前调用y(),因为函数y() 直到x() 执行一次后才会真正定义。
2) 两次调用x()会导致PHP重新声明函数y(),导致致命错误:
致命错误:无法重新声明 y()
解决方案是拆分代码,使两个函数声明为彼此独立:
function x ($y)
{
return($y+3);
}
function y ($z)
{
return ($z*2);
}
这也更具可读性。
【讨论】:
(4+3)*(4*2) == 56
请注意,PHP 并不真正支持“嵌套函数”,因为它仅在父函数的范围内定义。所有函数都是全局定义的。请参阅docs。
【讨论】:
y() 在 x() 中时的部分
不确定该代码的作者想要实现什么。在另一个函数内部定义一个函数并不意味着内部函数只在外部函数内部可见。第一次调用 x() 后,y() 函数也将在全局范围内。
【讨论】:
这对于没有静态属性、引用等的递归很有用:
function getRecursiveItems($id){
$allItems = array();
function getItems($parent_id){
return DB::findAll()->where('`parent_id` = $parent_id');
}
foreach(getItems($id) as $item){
$allItems = array_merge($allItems, getItems($item->id) );
}
return $allItems;
}
【讨论】:
$id的所有grandchildren
foreach 中的第一个getItems 替换为getItemms,将第二个getItems 替换为getReqursiveItems,您将获得递归函数。
可以从另一个函数内部定义一个函数。 在外部函数执行之前,内部函数不存在。
echo function_exists("y") ? 'y is defined\n' : 'y is not defined \n';
$x=x(2);
echo function_exists("y") ? 'y is defined\n' : 'y is not defined \n';
输出
y 没有定义
y 已定义
简单的事情你不能在执行 x 之前调用函数 y
【讨论】:
您的查询是 7 * 8
x(4) = 4+3 = 7 和 y(4) = 4*2 = 8
当函数 x 被调用 创建 函数 y 时,它不会运行它。
【讨论】:
函数内的函数或所谓的嵌套函数非常有用,如果您需要执行一些递归过程,例如循环真正的多层数组或文件树而不多个循环,或者有时我使用它来避免为需要在多个功能之间划分和隔离功能的小型作业创建类。但是在使用嵌套函数之前,您必须了解这一点
这是否意味着您不能使用嵌套函数?不,您可以使用以下解决方法
第一种方法是在函数存在的情况下使用条件块来阻止子函数重新声明到全局函数堆栈中,这样可以防止函数被多次声明到全局函数堆栈中。
function myfunc($a,$b=5){
if(!function_exists("child")){
function child($x,$c){
return $c+$x;
}
}
try{
return child($a,$b);
}catch(Exception $e){
throw $e;
}
}
//once you have invoke the main function you will be able to call the child function
echo myfunc(10,20)+child(10,10);
第二种方法是将子函数的作用域限制为局部而不是全局,为此,您必须将函数定义为匿名函数并将其分配给局部变量,然后该函数仅在本地范围内可用,并且每次调用主函数时都会重新声明和调用。
function myfunc($a,$b=5){
$child = function ($x,$c){
return $c+$x;
};
try{
return $child($a,$b);
}catch(Exception $e){
throw $e;
}
}
echo myfunc(10,20);
记住子函数在主函数或全局函数堆栈之外是不可用的
【讨论】:
使用嵌套的第二次函数后,我们得到“重新声明”错误。但是..我们可以这样使用:
function x( $some_value ){
$nested_function = function($x){ return $x*2; };
return $nested_function( $some_value );
}
【讨论】: