vergelijken en returnen
De argumentatie "als het geen directory is, dan moet het een bestand zijn" in A is namelijk een drogreden van het uitgesloten midden.
Stel we hebben een functie die true of false teruggeeft, bijv. copy();
Zou jij in deze vergelijkbare situatie dan ook dit doen?
Code (php)
Dit is toch een beetje vreemd :-s
Code (php)
De else wordt hier niet getriggerd op false, maar ruimer op alles dat niet true is. Dat is niet per se hetzelfde wanneer $succes bijvoorbeeld null of undefined zou kunnen zijn.
Daarom lijkt de volgende controlestructuur naar dezelfde twee toestanden A en B te leiden, maar is de achterliggende logica toch een heel andere:
Code (php)
Gewijzigd op 06/01/2014 10:49:58 door Ward van der Put
Lol, maar in het geval $succes een boolean is, maakt het dus helemaal niks uit ;)
In Java of elke andere strict typed taal zou het gebruik van if..else voldoende zijn:
Code (php)
1
2
3
4
5
6
2
3
4
5
6
bool succes;
if (true == succes) {
// Toestand A: true
} else {
// Toestand B: false
}
if (true == succes) {
// Toestand A: true
} else {
// Toestand B: false
}
Gewijzigd op 06/01/2014 11:36:17 door Wouter J
Correct Wouter, maar een functie zoals copy() kan toch alleen maar een boolean teruggeven?
Maar goed, nu gaan we wel echt heeeel erg strict nadenken over de code en wanneer we dat gaan doen moeten van PHP eigenlijk een static typed language maken (dus niet lazy en niet strict)
Maar php.net is toch de officiële documentatie? Kunnen we die niet vertrouwen?
Ozzie, jij bekijkt het nog veel te simpel. In PHP kun je nergens een functie limiteren tot een bepaalde type, je kunt alleen documentatie (dingen die mensen hebben geschreven) gebruiken om het type te weten. En hoewel we best PHP.net kunnen vertrouwen (nou ja...), kan je in de code dus nooit met zekerheid zeggen welk type je nou terug krijgt.
dan kun je ook wel zeggen dat
substr('abc', 0,1);
volgens de documentatie 'a' terug zou moeten geven, maar dat dat niet met zekerheid te zeggen is.
En dat kun je wel testen, maar wie zegt dan weer dat dat niet van het tijdstip, de maanstand en de koers van de AEX afhankelijk is.....
Waar ik het hier over heb is het verschil tussen code level en documentatie level. Op code level kunnen we in PHP nooit aannemen dat copy altijd een boolean teruggeeft. Alleen op documentatie level kunnen we aannemen dat copy een boolean teruggeeft en dat nemen we dus ook aan, aangezien we dat gewent zijn in PHP.
Als we bijv. naar Haskell kijken kunnen we op code level zeker weten dat copyFile een IO teruggeeft. Het documentatie level bevestigt dit alleen maar.
Als je nog wat dieper in internals wilt gaan: PHP is gemaakt in C, een taal die strict typed is. Om een lazy typed language in een script typed language te maken heeft PHP een custom C type gemaakt: zval
Code (php)
1
2
3
4
5
6
7
2
3
4
5
6
7
struct _zval_struct {
/* Variable information */
zvalue_value value; /* value */
zend_uint refcount__gc;
zend_uchar type; /* active type */
zend_uchar is_ref__gc;
};
/* Variable information */
zvalue_value value; /* value */
zend_uint refcount__gc;
zend_uchar type; /* active type */
zend_uchar is_ref__gc;
};
Dit _zval_struct type bevat meerdere properties, 1 daarvan is de value die de value van het type vasthoudt en 1 daarvan is type, die houdt het type van de value vast.
Die value is ook weer een type:
Code (php)
1
2
3
4
5
6
7
8
9
10
2
3
4
5
6
7
8
9
10
typedef union _zvalue_value {
long lval; /* long value */
double dval; /* double value */
struct {
char *val;
int len;
} str;
HashTable *ht; /* hash table value */
zend_object_value obj;
} zvalue_value;
long lval; /* long value */
double dval; /* double value */
struct {
char *val;
int len;
} str;
HashTable *ht; /* hash table value */
zend_object_value obj;
} zvalue_value;
Hier wordt een zvalue_value type gemaakt die een union is, dat betekend dat het een verzameling van types is. Wat voor verzameling dit is staat beschreven in het stuk tussen accolades.
De verzameling bestaat dus uit: long (integers), double (floats), struct { char *val; int len; } (string + string lengte), HashTable (array) en zend_object_value (PHP object type).
Wanneer een functie dus een zval type terug geeft kan die al deze bovenstaande types zijn. Welk type het momenteel is wordt opgeslagen in de type property. Maar dat kan zo veranderd worden door convert_to_* functies. Wat type er in zval zit is dus compleet dynamisch.
Hierdoor kunnen we nooit zeggen welk type een functie teruggeeft als hij een zval type teruggeeft. En hierdoor kunnen we dus ook in PHP code nooit een functie limiteren tot het teruggeven van een bepaalde PHP type, aangezien alle PHP types in totaal 1 type is.
dan lijkt me dat voldoende zekerheid om daar vanuit te gaan.
Mogelijk dat in een uitzonderlijke situatie die functie plotseling een andere value zou kunnen teruggeven, maar dat is dan een bug.
Maar om nu elke functie in twijfel te trekken tijdens het coden in PHP, gaat mij in elk geval te ver.
Het is al erg genoeg dan
NULL, FALSE, 0 en "" allemaal gelijk zijn als je met == vergelijkt.
Als de documentatie zegt dat functie foo een boolean teruggeeft, dan is het toch onzinnig om vervolgens nog eens te gaan controleren of de documentatie het wel bij het rechte eind heeft? Hoe het er achter de schermen ook aan toe gaat, je moet kunnen vertrouwen op de documentatie, of beter gezegd de handleiding. Het lijkt me juist dat je nogal paranoia bent als je zelfs de handleiding niet vertrouwt. Dan kun je alles wel gaan controleren. Dan kun je zelfs als je 2 integers bij elkaar optelt ook nog eens gaan controleren of de uitkomst wel een integer is. Nee, dat lijkt me niet de juiste weg.
En ozzie, nee natuurlijk ga je niet doen:
Code (php)
Wat ik hier vertelde was slechts allemaal door gaan op het verhaaltje van ward, dat het omkeren van een conditie niet hetzelfde resultaat oplevert.
Dat heel erg strict bekijken kun je in PHP simpelweg niet doen en daarom moet je je er ook geen zorgen over gaan maken. Maar je moet wel in je achterhoofd houden dat dat dus de grote beperking van PHP is en dat wanneer je in een situatie het dus wel heel erg strict moet weten (dan denken we over mensen bij NASA en CERN enzo) je dus naar een andere taal over moet stappen.
Gewijzigd op 06/01/2014 14:04:10 door Wouter J
als je het hebt over documentatie van een of andere zelf gemaakte (opensource) class dan mag je wel wat wantrouwiger zijn.
Ivo, ook bij PHP.net mag je wat wantrouwiger zijn... De documentatie bevat best nog wel wat verkeerde dingen.
Maar Wouter, dan gat het om bugs. Ik vind dat je php.net gewoon moet kunnen vertrouwen. Dat er iets mis kan gaan, oké... maar dan is er sprake van een bug.
vele honderden undocumented functions. “Leesbaarheid” wordt nogal een understatement als er niets te lezen is.
Niet alleen bugs, maar bijvoorbeeld ook Ah ja... als het niet gedocumenteerd is weet je dus ook niks en zul je voorzichtiger te werk moeten gaan.