Pomoc - Szukaj - Użytkownicy - Kalendarz
Pełna wersja: Nieintuicyjne zachowanie foreach
Forum PHP.pl > Forum > PHP
mike
Witam,

Chciałbym się podzielić pewnym spostrzeżeniem. Kawałek kodu na początek:
  1. <?php
  2.  
  3. $strColumn = 'surname';
  4.  
  5. $arrColumns = array( 'surname', 'name', 'email' );
  6.  
  7. foreach( $arrColumns as $intId => $strColumn )
  8. {
  9. echo $intId . ' => ' . $strColumn . '<br />';
  10. }
  11.  
  12. echo '<br />' . $strColumn; // wyświetli `email` a powinno wyświetlić `surname`
  13.  
  14. ?>

Powiedzcie mi czy ja za wiele wymagam, żeby lokalna zmienna $strColumn była faktycznie lokalna?
Dlaczego się czepia wcześniej ustawionej zmiennej?

Czy to jets bug php czy jest to błąd w mojej interpretacji i moich oczekiwaniach?

Już klika lat piszęw php i dopiero teraz to zauważyłem, ...., a może wcześniej nie miałem nigdy takiej sytuacji, ..., ale to raczej wykluczone.

Wersja php na jakiej pracuję to 5.1.2.

(tylko bez głupich komentaży o Przedszkolu tongue.gif)
pEbE
No nic dziwnego jak zmieniasz wartosc zmiennej...
nospor
zmienne lokalne dotyczą funkcji, a nie kawalkow kodu objętych {}. No przykro mi, ale to trafia na przedszkole smile.gif
http://pl.php.net/manual/pl/language.variables.scope.php
mike
No kurcze,

aż dziw bierze że dopiero teraz mi się to przytrafiło laugh.gif

Człowiek uczy się całe życie.
dr_bonzo
Stane w obronie mike_mecha: patrzcie na to (C++ nie C):
Kod
#include <stdio.h>

int main()
{
        int i = 2323;
        for ( int i = 0; i < 10; i++ )
        {
                printf( "i = %d\n", i );

        }

        printf( "\ni = %d", i );
        return 0;
}


Kod
$ ./C.bin
i = 0
i = 1
i = 2
i = 3
i = 4
i = 5
i = 6
i = 7
i = 8
i = 9

i = 2323


Skoro php jest bazowane na C/C++ mozna bylo oczekiwac takiego zachowania (no chyba za na jakiejs stronie manuala 4pt czcionka jest napisane ze to dziala inaczej tongue.gif)
mike
Dokładnie coś takiego miałem na myśli skoro w konstrukcji
Kod
foreach(wyrażenie_tablicowe as $klucz => $wartość)

Podczas każdej iteracji $klucz otrzymuje wartość aktualnego klucza a $wartość otrzymuje wartość aktualnego elemantu tablicy i są to zmienne jakoby lokalne dla pętli foreach to nie powinny się czepiać tego co na zewnątrz.

Ja to uważam za niekonsekwencję, bo skoro jest tak jak jest do niby dlaczego nie jest od nas wymagane pisanie:
  1. <?php
  2.  
  3. $arrColumns = array( 'surname', 'name', 'email' );
  4.  
  5. $intId  = null; // wcześniejsza deklaracja zmiennych, to oczywiście nie ma sensu
  6. $strColumn = null; // ale jeśli wartość byłaby tablicą to już tak
  7. foreach( $arrColumns as $intId => $strColumn )
  8. {
  9. echo $intId . ' => ' . $strColumn . '<br />';
  10. }
  11.  
  12. ?>

Ja uważam zachowanie php w tym miejscu za nieintuicyjne.
nospor
Cytat
Ja to uważam za niekonsekwencję, bo skoro jest tak jak jest do nieby dlaczergo nie jest od nas wymagane pisania:
Ale czemu? php nie wymaga inicjacji (zadeklarowania) zmiennej, przed przypisaniem jej wartości

ps: przenosze na php bo mnie zywcem zjecie winksmiley.jpg

edit: no i dla mnie to nie jest nieintuicyjne. normalka. lokale w funkcjach, wszystko inne nie smile.gif
mike
Cytat(nospor @ 2006-03-21 14:55:03)
Cytat
Ja to uważam za niekonsekwencję, bo skoro jest tak jak jest do nieby dlaczergo nie jest od nas wymagane pisania:
Ale czemu? php nie wymaga inicjacji (zadeklarowania) zmiennej, przed przypisaniem jej wartości

Oj, no wiesz. Tego to mi mówić nie musisz.

Chodziło mi w tym przykładzie (który jest trochę bardziej hipotetyczny niż realny), że skoro to co jest wewnątrz pętli foreach wpływa na resztę to powinno to być powiedziane.

A po za tym. Zmienne tablicowe trzeba deklarować wcześniej bo dostaniesz E_NOTICE. I dokładnie o to mi chodziło tongue.gif

Nieintuicyjne. Może nie aż tak bardzo. Po prostu miałem taką sytuację, że mnie to zaskoczyło. I uświadomiłem sobie że nie jest to najlepiej rozwiązane.
nospor
Cytat
A po za tym. Zmienne tablicowe trzeba deklarować wcześniej bo dostaniesz E_NOTICE.
zmienne tablicowe tak. ale od kiedy index tablicy to tablica? pozatym foreach inicjuje to sam w sobie.
No i pozatym tablice napewno nie inicjuje się przez przypisanie jej null'a tongue.gif
scanner
Jesli dobrze pamiętam ze szkoły (dawno nie praktykowałem C++) to tam można zrobić lokalny fragment kodu poprzez samo postawienie klamer - wszystko co wewnątrz nich jest jest lokalne i już.
MaKARON
Sto lat temu to robilem, ale przegladalem zrodla kernela linuksa i wydaje mi sie, ze w C tez mozna cos takiego zrobic, ale uzywalo sie haka:

do {
// tutaj kod
} while( 0 );
mike
Cytat(nospor @ 2006-03-21 15:01:34)
(...) zmienne tablicowe tak. ale od kiedy index tablicy to tablica? pozatym foreach inicjuje to sam w sobie.

Tu chodziło mi o wartości, które tablicami już mogą być :-)

A właśnie o to "sam w sobie" mi chodzi. Skoro on robi do własnych celów to powinno być to o zasięgu lokalnym.
kszychu
MIke, zupełnie nie rozumiem, dlaczego takie zachowanie foreach jest dla Ciebie dziwne. Przecież dokładnie tak samo działają inne pętle (for).
Poza tym, napisałeś, że tablice trzeba wcześniej deklarować.... niekoniecznie:
  1. <?php
  2.  
  3. $tablica[] = $wartosc; // to wywali notice
  4. $tablica[$indeks] = $wartosc; // ale to już nie
  5.  
  6. ?>
anopak
z jednej strony mike ma rację, bo np jeżeli includujemy jakiś kod z pętlą forech i nie wiemy jakie tam są zmienne, to może nam to nieźle namieszać w kodzie...

co do tablice, to:
  1. <?php
  2. $tablica[]=1;
  3. $tablica[$in]=2;
  4.  
  5. ?>


nie wyrzyca mi błędów E_NOTICE, ani pierwsze ani drugie...
nospor
Cytat
bo np jeżeli includujemy jakiś kod z pętlą forech i nie wiemy jakie tam są zmienne, to może nam to nieźle namieszać w kodzie...
Ale co to za argumentacja? Rownie dobrze mozemy includowac kod bez pętli i nie wiedziec jakie ma zmienne i tez moze nam "namieszac w kodzie" winksmiley.jpg
bigZbig
mike_mecha zaskoczylo takie zachowanie poniewarz przenosi swoje doswiadczenia z innych jezykow na php, ale w php jest to wlasnie w ten sposob ustalone, co mnie akurat wydaje sie calkiem logiczne bo jesli klamry mialyby okreslac granice zasiegu zmiennych to przy pelnej konsekwencji powinnismy otrzymac cos takiego:
  1. <?php
  2. $aA = array('kicha', 'micha', 'rycha');
  3. $aB = array('bleble');
  4. foreach($aA as $sKey => $sValue) {
  5. //powinna nastapic inicjalizacja zmiennej lokalnej
  6. $aB[$sKey] = 'my_'.$sValue;
  7. }
  8. print_r($aB);
  9. //powinno zwrocic array('0' => 'bleble');
  10. ?>


Zauwazcie ze w php nie trzeba inicjalizowac zmiennych dlatego gdyby klamry wyznaczaly zasieg zmiennych php musialoby podjac decyzje czy tablica $aB jest kontynuacja zmiennej zainicjalizowanej poza petla, czy nalezy zainicjalizowac nowa zmienna.

W ActionScripcie jest to rozwiazane dzieki instrukcji var inicjalizujacej zmienna
Kod
i:Number = 10;
A_array = new Array(1, 2, 3);

for(var i:Number = 0; i < A_array.length; i++) {
  // zwroci kolejno 0 1 2
  trace(i);
}

// zwroci 10
trace(i);

for(i = 0; i < A_array.length; i++) {
  // zwroci kolejno 0 1 2
  trace(i);
}

// zwroci 2
trace(i);
anopak
Cytat(nospor)
Ale co to za argumentacja? Rownie dobrze mozemy includowac kod bez pętli i nie wiedziec jakie ma zmienne i tez moze nam "namieszac w kodzie"


yh, faktycznie smile.gif

Cytat(bigZbig)
Zauwazcie ze w php nie trzeba inicjalizowac zmiennych dlatego gdyby klamry wyznaczaly zasieg zmiennych php musialoby podjac decyzje czy tablica $aB jest kontynuacja zmiennej zainicjalizowanej poza petla, czy nalezy zainicjalizowac nowa zmienna.


no niby tak jest, ale mogłoby to być rozwiązane np tak:
  1. <?php
  2.  
  3. foreach($tablica){
  4.  echo $this->key .'=>'.$this->value.'<br>';
  5. }
  6.  
  7. ?>


i wtedy nie było by problemów z nadpisaniem zmiennych, tylko byłby kolejny problem z wykorzystaniem takiej konstrukcji w klasach sad.gif
bigZbig
@anopak - sam sobie odpowiedziales
anopak
@bigZbig - no niby tak, ale to mogły być poprostu zmienne zarezerwowane (tak jak $this)... no cóż może w któreś wersji ogólnie będzie to inaczej rozwiązane winksmiley.jpg
bigZbig
@anopak - no OK, ale potrzebne Ci to? Moim zdaniem wystarczy izolowanie zmiennych w funkcjach i klasach.
Immanuel
Cytat
Ale czemu? php nie wymaga inicjacji (zadeklarowania) zmiennej, przed przypisaniem jej wartości.


sorry, że się czepiam, ale powinno się pisać: inicjalizacji smile.gif

cytat z Symfonii C++ Jurka Grębosza:

Cytat
Mówimy "inicjaLIZAcja", a nie "inicjacja". Jest ogromna różnica między tymi słowami. Jeśli będziesz uparcie mówił "inicjacja" to zajrzyj sobie kiedyś do encyklopedii i sprawdź, co to słowo znaczy. Trochę się pośmiejesz, a potem już zawsze będziesz mówił tylko: "inicjalizacja".
nospor
no bo ja mówilem własnie o inicjacji winksmiley.jpg laugh.gif
ok, dzięki za zwrócenie uwagi smile.gif

Cytat
no niby tak, ale to mogły być poprostu zmienne zarezerwowane (tak jak $this)... no cóż może w któreś wersji ogólnie będzie to inaczej rozwiązane
To juz jest kombinowanie. NIe jestem pewien czy takie rezerwowane zmienne przy foreach mialyby byc takie lepsze
To jest wersja lo-fi głównej zawartości. Aby zobaczyć pełną wersję z większą zawartością, obrazkami i formatowaniem proszę kliknij tutaj.
Invision Power Board © 2001-2025 Invision Power Services, Inc.