2009-10-27 3 views
50

Этот код выдает результат в виде 56Функция внутри функции.?

function x ($y) { 
    function y ($z) { 
     return ($z*2); 
    } 

    return($y+3); 
} 

$y = 4; 
$y = x($y)*y($y); 
echo $y; 

Любая идея, что происходит внутри? Я запутался.

+18

Звучит как вопрос о домашнем задании, но это все еще хороший вопрос ха-ха. – hobbes3

ответ

81

X возвращает (значение +3), в то время как Y возвращается (значение * 2)

Учитывая значение 4, это означает (4+3) * (4*2) = 7 * 8 = 56.

Хотя функции не ограничены (что означает, что вы можете безопасно определение функций «гнездо»), этот конкретный пример подвержен ошибкам:

1) Вы не можете позвонить y() перед вызовом x(), потому что функция y() фактически не будет определена до тех пор, пока x() не выполнит один раз.

2) Вызов x() дважды заставит PHP для переобъявить функции y(), что приводит к фатальной ошибке:

Fatal error: Cannot redeclare y()

Решение как бы разделить код, так что обе функции объявлены независимыми друг от другое:

function x ($y) 
{ 
    return($y+3); 
} 

function y ($z) 
{ 
    return ($z*2); 
} 

Это также более читаемо.

+51

Другое отличие состоит в том, что если у вас есть функция y внутри функции x, и вы вызываете функцию x дважды, вы получите сообщение об ошибке для повторной объявления функции y. (Если вам это действительно нужно, вам нужно окружить функцию y проверкой на то, что (function_exists ('y')) {...) –

+3

@Eugene M: Я даже не знал этого .. Спасибо, что указали это! (Просто протестировал его сам, после того, как повторил ваш комментарий.) – Duroth

+3

", что означает, что вы можете безопасно определять определения" гнезд ", все еще имея возможность называть их в любом месте файла" - это ужасное свойство языка. – Michael

25
(4+3)*(4*2) == 56 

Обратите внимание, что PHP действительно не поддерживает «вложенные функции», как определено в рамках родительской функции. Все функции определены глобально. См. docs.

+0

Спасибо, поэтому внутренняя функция не вызвана. – Posto

+2

Конечно, это так, в результате получается часть '(4 * 2)'. –

+1

Когда X вызывается, внутренняя функция определена - не называется. Таким образом, результат. Это волосатая часть о функциях в функциях =) – mauris

3

Ваш запрос делает 7 * 8

x(4) = 4+3 = 7 и y(4) = 4*2 = 8

, что происходит, когда функция х называется его создает функцию у, не запустить его.

+1

Просто хотел добавить, что это не очень хорошая практика. Вы также заметите, что если вы используете $ y = y ($ y) * x ($ y); что код умрет, потому что x не был создан. Такое кодирование просто приведет к ошибкам и путанице. –

+0

yes thats true; лично я только когда-либо использовал это однажды на практике, чтобы разыгрывать разные стили магических цитат. хотя это было в выражении if вместо функции() –

14

Не знаете, чего хотел достичь автор этого кода. Определение функции внутри другой функции НЕ означает, что внутренняя функция видна только внутри внешней функции. После вызова x() в первый раз функция y() также будет в глобальной области.

+4

+1 Это последнее предложение отвечает на вопрос очень лаконично. – GZipp

+2

Кроме того, определение y() внутри x() означает, что x() можно вызывать только один раз. Вы получите факультативную ошибку «функция, уже определенная» при вызове x() во второй раз. –

5

Можно определить функцию из другой функции. внутренняя функция не существует, пока не будет выполнена внешняя функция.

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'; 

Выход

у не определен

у определяется

Простая вещь, которую вы не можете вызвать функцию у перед тем выполнена х

6

Это полезное понятие рекурсии без статического свойства, ссылка и т. д .:

function getReqursiveItems($id){ 
    $allItems = array(); 

    function getItemms($parent_id){ 
     return DB::findAll()->where('`parent_id` = $parent_id'); 
    } 

    foreach(getItems($id) as $item){ 
     $allItems = array_merge($allItems, getItems($item->id)); 
    } 

    return $allItems; 
} 
+0

Объясните? Выглядит рекурсивно, но я этого не вижу. Является ли getReqursiveItems внутри getItems()? – Josiah

+1

@ Josiah не уверен, что моя оригинальная идея была здесь .. но я отредактировал ответ, чтобы показать возможный usecase. –

+2

это не выглядит рекурсивным, а скорее возвращает всех * внуков * исходного '$ id' – KnightHawk

Смежные вопросы