Csontvázak a szekrényből

Kiderült, hogy az egyik szerverünkön van egy hostolt cucc egy jó ideje, aminek most újra jelentkezett a gazdája. Gondoltam megnézem, hogy mégis micsoda. A kód úgy indul, hogy némelyik fájl .php3 kiterjesztéssel flangál. Sebaj, less akarmi.php3:

Így indul:

<?
function inarray($ar,$a) { for ($i=0; $i<sizeof($a); $i++) if ($a[$i] == $ar) $res = 1;
if ($res == 1) return true; else return false; }

[...]

Hozzászólások

szerintem alapveto, opensource hardwaret a nepnek! implementaljunk bitszinten! ne bizzunk a nagy cegek libjeiben! igenis irjunk inarray functionoket! milyen backdoort rejtegettek a megvalositasokban, hogy rakenyszeritetek minket a hasznalatukra, amikor mi is kepesek vagyunk megirni!

[insert line here]
B.C. 3500 - DIY Vehicle / A.D. 30 - DIY Religion / A.D. 1991 - DIY OS

Eleve az a $res minek oda? Ha a for ciklus kozepen megtalalja az elemet, akkor return true; for ciklus lefutasa utan meg return false; mert nincs ott, ha addig nem tertunk vissza.

De tegyuk fel, hogy ez most csak felesleges kotekedes, akkor is illett volna azt a szerencsetlen $res valtozot mondjuk 0-ra inicializalni a fuggveny elejen. Ertem en, hogy "de hat igy is mukodik" (c) PhPistike Quality, de azert megis.

szerk.: latom alattam is irtak

Kimaradt fentről:)

$res meg lehet egyszerűen bool, inicializálva mondjuk false-ra, így adódik egy olyan, hogy:

function inarray($ar,$a)
{
$res = false;

for ($i=0; $i KISEBB sizeof($a); $i++)
{
if ($a[$i] == $ar)
{
$res = true;
break;
}
}
return $res;
}

Nem tudtam gyorsan escapelni a <-t, úgyhogy marad így, nehogy széttúrjam az oldalt.

Én is arra gondoltam, hogy legyen return a ciklus közepén, de aztán elgondolkodtam: Lehet, hogy a fordító megnézi ezt, és az egészet jól kioptimalizálja a fenébe, és a végeredmény ugyanaz futás közben.

Azt nem tudom, hogy a php optimalizál-e egyáltalán, soha nem php-ztem, de egy C fordítótól elvárnám.

Aki szerint elegánsabb a csillió-billió if, esetenként csillió plusz változó bevezetésével, az nyeljen sót.

Jó ideje rászoktam arra, hogy ha valami kivételvizsgálat van, minél előbb return, exception, continue vagy break.

Egyesek szerint a continue se szép, szerintem meg az se egészséges, mikor a valag if miatt nem látom át a lényeget.

Szvsz ha plusz változó kell nekem ahhoz, hogy a vezérlést irányítsam, akkor már érdemes elgondolkozni azon, hogy jól csináltam-e.

----------------
Lvl86 Troll - Think Wishfully™

NDEBUG kiveszi a release valtozatbol, az assert josag.

Mind a kettore ra tud ugrani a debugger, a user egyikkel sem tud mit kezdeni. A NULL-ra manapsag nem trivialis gonosz dolgot teni.

En default a 20ns faster utat valasztom.

Szoval szerinted, miert jobb benne hagyni ?

Amit nem lehet megirni assemblyben, azt nem lehet megirni.

"Szoval szerinted, miert jobb benne hagyni ?"

Pl. mert tobbet er egy normalisan lekezelt informativ hibauzenet, mint egy unhandled exception vagy random elhalas, elszallas. A hibauzenetekre is csunyan neznek a felhasznalok, de amikor az egesz program borul, akkor jelentosen meg tud rendulni a bizalmuk. Ami szvsz tobbet er a 20ns faster way-nal.

----------------
Lvl86 Troll - Think Wishfully™

Valóban azt szállítjuk, amit teszteltünk.

De ami UAT-ra megy, az már nem development verzió, abban már nincs milliónyi extra ellenőrzés és minden szar kilogolása.

Fejlesztés közben ez minden benne van. Aztán ha úgy gondolják kész, készítenek release package-et. Ez már production módban van fordítva. Ezen végigmegy az automatikus tesztelés, kiadjuk UAT-ra, letesztelik, ha megfelelt, mehet élesbe.

A fejlesztők elég sokat dolgoznak adott esetben akár csak 10% teljesítménynövelésen is, elég kiszúrás lenne velük, ha lassítást tennénk az éles rendszerbe.

$mukoggy=array("na ezt talald meg forral"=>"hehe");
...inarray(?,$mukoggy)...

Vagy php3-ban asszociativ tomb se volt?

--
In truly successful relationships...
no one wears the pants.

Végül is annyira nem szörnyű, mert csak az innarray függvény belsejét kell átírni (tight coupling) :) .
Nem értek a php-hez, de gondolom a legdurvább hiba a kódban hogy a $res egy globális változó.

Szerintem még akkor is rémes, ha feltételezzük, hogy a kód írásakor még nem volt erre beépített függvény.
Például mindenképp végig szalad a tömbön. Kiléphet a for-ból, amint talál valamit. lásd fent
De ha ettől eltekintünk, akkor a második sorban is pl. simán lehet

return $res == 1

-et írni, és akkor egy elágazással kevesebb. (A zárójelekben nem vagyok biztos, rég kódoltam php-t, lehet, hogy kellene a boolean expressionünk köré…)

int getRandomNumber() { return 4; }  // ← aláírás
//szabályos kockadobással választva. garantáltan véletlenszerű.  xkcd

Nehogy már ciklust írjunk, ahova nem muszáj… :P


function inarray($needle, $haystack, $index=0) {
	return ($index > count($haystack)) ? 
		false : 
		(($haystack[$index] == $needle) ? 
			true : 
			inarray($needle, $haystack, ++$index)
		);
}
int getRandomNumber() { return 4; }  // ← aláírás
//szabályos kockadobással választva. garantáltan véletlenszerű.  xkcd

Nem tudom, mit akarsz, még identálva is van, de ha akarod, kommentálom is… :-)
Ettől függetlenül a ternary operatort én is jobban szeretem írni, mint olvasni, elágazás helyett azt használnom valóban csak arra volt jó, hogy kevesebb kapcsos zárójelet kelljen írnom. :-)

int getRandomNumber() { return 4; }  // ← aláírás
//szabályos kockadobással választva. garantáltan véletlenszerű.  xkcd

Hízelgő, hogy számodra a fenti megoldás ennyire szép, hogy ilyesmit feltételezel… ;)
Ez a szál alapvetően nem a szép és optimális megoldásokról szólt: biztos vagyok benne, hogy a megoldásom megkerül mindennemű optimalizációt, amit az interpreter a ciklusoknál esetlegesen alkalmazna.

Amikor a fenti megoldásomat írtam, az ugrott be, amikor először scripteltem – mivel scripteket olvasva tanultam meg a nyelvet, nem ismertem bizonyos vezérlőszerkezeteket. Ennek az lett az eredménye, hogy pl. ciklusok helyett elágazásokat használtam goto-val, illetve a logikai operátorokat az elágazások egymásba ágyazásával oldottam meg.

Arra kíváncsi vagyok, hogy vajon egy compiler a rekurzív kódból vagy a ciklusosból csinálna-e gyorsabb binárist?

int getRandomNumber() { return 4; }  // ← aláírás
//szabályos kockadobással választva. garantáltan véletlenszerű.  xkcd

Hol érdemes utánaolvasnom az optimalizációnak (olyat nem tanultam)?
Számomra pl. egyáltalán nem egyértelmű a különbség a függvényben és a ciklusban található utasítások között sem: mitől más, ha a függvény nevével hivatkozok rájuk?

int getRandomNumber() { return 4; }  // ← aláírás
//szabályos kockadobással választva. garantáltan véletlenszerű.  xkcd

A legtobb nyelven ugy mukodik a rekurzio, hogy fv hivaskor:
-van opcionalisan valami bevezeto resz
-a stack-en allokal helyet a fv. parametereknek (ezeket a legtobb adattipus eseten le is masolja, de van, hogy csak pointert kap)
-(esetlegesen par regisztert is felpakolhat oda, ha bent keves lenne)
-lokalis valtozoknak is csinal helyet
-elvegzi ami a fv-ben van
-felszabaditja a lokalis valtozokat (destruktorok lefutnak)
-felpakolja a stack-re a visszateresi erteket (van, hogy ez regiszterben megy vissza, pl. pascal)
-lefut valami opcionalis kod meg pluszban (mondjuk profiler miatt)

Ciklusnal ezt a rengeteg memoriamuveletet (a masolas masolatarol is masolatot keszitesz) meg lehet uszni, mert a rekurzio jellemzoen nem egyszer fut le.. a stack-et sem hasznalod annyiszor, egy melyebb rekurziv hivas siman kitomi a stacket (egy 10000-es ciklus a legtobb mai gepnek nem art, de egy ugyanekkora rekurzio adhat stack overflow-t).
Amiket fent irtam, azok altalanossagok, siman lehetnek kivetelek. Van par rekurziot erosen tamogato nyelv (pl. Prolog), ahol a jobbrekurziv hivasok siman cikluskent futnak le (jobbrekurziv, ahol a rekurziv hivas eredmenyevel nem csinal semmit, hanem return-ol, ebben az esetben ugye a stacken korabban foglalt dolgok mar nem kellenek, siman felhasznalhato a kovetkezo iteraciohoz).

PHP-ben fene tudja mennyire optimalizalt amit irtal. Nagy valoszinuseggel a needle (ami jo nagy) siman lemasolodik minden egyes hivasra (osszesen ugye count($haystack)-szer). A $haystack-et "szerencsere" szinten nem cim szerint adod at, igy - ha nem optimalizalodik - ez is lemasolodik minden egyes iteraciora (ez rengeteg masolgatast jelent total feleslegesen). Az $index valtozik a ++$index miatt, szoval itt meg sem uszhatna a masolast, de ez szerencsere csak egy szam, ugyhogy itt nem szamit. Az elso ket parametert nem modositod, siman atadhatnad referenciakent (&). Ettol persze ugyanugy nem fog mukodni asszociativ tombokre, meg negativ indexekre, esetleg nem folytonosan indexelt tombokre sem. Ez mondjuk javithato lenne array_keys-el, de felesleges. Ott a beepitett megoldas, gyors, mukodik.

--
In truly successful relationships...
no one wears the pants.

Köszönöm, kimerítő válasz – ugyan gondolom a 4–6 lépések a ciklusra is igazak, de a lényegen az sem változtat.
A jövőben nem írok függvényeket (de.☺).

int getRandomNumber() { return 4; }  // ← aláírás
//szabályos kockadobással választva. garantáltan véletlenszerű.  xkcd

Btw:

array

(PHP 4, PHP 5)

array — Create an array

Php3-ban már létezett a $array[]=$x; szintaktika? Vagy explicit meg kellett adni az indexet is ($array[0]=$x;)? Csak mert ha utóbbi, akkor mi van akkor, ha sosem adtam értéket a 0-ás indexű elemnek?

Jobban végiglapozgatva a PHP doksit, nem vagyok meggyőződve, hogy nem volt in_array() PHP3-ban, mert sehol nincs feltüntetve a PHP3, gyakorlatilag 4-től kezdődik az élet a kézikönyvben. Persze, lehet, hogy csak nem néztem utána elég alaposan.

----------------
Lvl86 Troll - Think Wishfully™