2009-10-27 14 views
50

Ten kod daje wynik jako 56.Funkcja wewnątrz funkcji.?

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

    return($y+3); 
} 

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

jakiś pomysł, co się dzieje w środku? Jestem zdezorientowany.

+18

Brzmi jak zadanie domowe, ale nadal jest to dobre pytanie haha. – hobbes3

Odpowiedz

81

X powraca (wartość + 3), a Y powraca (wartości a * 2)

względu wartość 4, co oznacza, (4+3) * (4*2) = 7 * 8 = 56.

Chociaż funkcje nie są w ograniczonym zakresie (co oznacza, że ​​można bezpiecznie definicje funkcji „gniazdo”), w tym szczególnym przykładem jest podatna na błędy:

1) Nie można nazwać y() przed wywołaniem x(), ponieważ funkcja y() nie zostanie faktycznie zdefiniowana, dopóki nie zostanie wykonana jedna operacja: x().

2) Wywołanie x() dwukrotnie spowoduje PHP do funkcji y() redeclare, co prowadzi do śmiertelnego błędu:

Fatal error: Cannot redeclare y()

Rozwiązaniem zarówno byłoby podzielić kod tak, że obie funkcje są uznane za niezależne od siebie inne:

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

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

Jest to również bardziej czytelne.

+51

Inną różnicą jest to, że jeśli masz funkcję y wewnątrz funkcji x, i wywołujesz funkcję x dwa razy, otrzymasz komunikat o błędzie dla ponownego deklarowania funkcji y. (Jeśli naprawdę tego potrzebujesz, musisz otoczyć funkcję y sprawdzeniem, czy (function_exists ("y")) {...) –

+3

@Eugena M: Nigdy nie wiedziałem o tym .. Dzięki za wskazanie tego! (Po prostu przetestowałem to, po ponownym uruchomieniu komentarza.) " – Duroth

+3

" co oznacza, że ​​możesz bezpiecznie "zagnieździć" definicje funkcji, wciąż będąc w stanie wywoływać je w dowolnym miejscu w pliku "- to jest okropna właściwość językowa. – Michael

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

Należy zauważyć, że PHP tak naprawdę nie obsługuje "funkcji zagnieżdżonych", jak w zdefiniowanym tylko w zakresie funkcji nadrzędnej. Wszystkie funkcje są zdefiniowane globalnie. Zobacz docs.

+0

Dzięki, więc funkcja wewnętrzna nie zostanie wywołana. – Posto

+2

Oczywiście, że tak, to wynik w części '(4 * 2)'. –

+1

Po wywołaniu X wewnętrzna funkcja jest zdefiniowana - nie wywoływana. Tak więc wynik. To owłosiona część o funkcjach w funkcjach =) – mauris

3

Zapytanie robi 7 * 8

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

co się dzieje, gdy funkcja X nazywamy go tworzy funkcji y, to nie ma go uruchomić.

+1

Chciałam tylko dodać, że to nie jest dobra praktyka. Zauważysz także, że jeśli użyjesz $ y = y ($ y) * x ($ y); że kod zginie, ponieważ x nie zostało utworzone. Kodowanie w ten sposób doprowadzi do błędów i zamieszania. –

+0

tak, to prawda; Osobiście użyłem tego tylko raz w praktyce do opisu różnych stylów magicznych cytatów. chociaż było to w instrukcji if zamiast funkcji() –

14

Nie jestem pewien, co chciał osiągnąć autor kodu. Określenie funkcji wewnątrz innej funkcji NIE oznacza, że ​​wewnętrzna funkcja jest widoczna tylko wewnątrz zewnętrznej funkcji. Po wywołaniu x() po raz pierwszy, funkcja y() będzie również w zakresie globalnym.

+4

+1 To ostatnie zdanie odpowiada bardzo zwięźle. – GZipp

+2

Definicja y() wewnątrz x() oznacza, że ​​x() może zostać wywołane tylko raz. Otrzymasz "już zdefiniowany" błąd krytyczny podczas wywoływania x() po raz drugi. –

5

Możliwe jest zdefiniowanie funkcji z wnętrza innej funkcji. Wewnętrzna funkcja nie istnieje, dopóki nie zostanie wykonana zewnętrzna funkcja.

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

Wyjście

y nie jest zdefiniowane

y jest zdefiniowana

prosta rzecz nie można wywołać przed wykonywany funkcji Y X

6

ta jest przydatna koncepcja rekursji bez statyczne właściwości, numer referencyjny itp .:

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

Wyjaśnić? Wygląda rekurencyjnie, ale go nie widzę. Czy "getReqursiveItems" wewnątrz getItems()? – Josiah

+1

@Josiah nie jestem pewien, jaki był mój pierwotny pomysł .. ale zredagowałem odpowiedź, aby pokazać możliwe zastosowanie. –

+2

to nie wygląda na rekursywne, ale raczej zwraca wszystkie * wnuki * oryginalnego '$ id' – KnightHawk