[PHP/Tutor] Functies & 'preset/unknown' vars

Pagina: 1
Acties:

  • Grum
  • Registratie: Juni 2001
  • Niet online
Wat heeft die gast nu weer te zeiken?

Wat mij nu de laatste paar dagen steeds vaker in het oog prikt is dat mensen code posten met constructies als deze:
PHP:
1
2
3
4
5
6
7
8
9
10
<?
function printConcat($inVar, $inVar2, $inVar3)
{
   $tmpString = $inVar;
   if(!isset($inVar2)) $tmpString .= $inVar2;
   if(!isset($inVar3)) $tmpString .= $inVar3;
 
   print $tmpString;
}
?>

of
PHP:
1
2
3
4
5
6
7
8
9
10
11
12
<?
 
function printConcat($inVar, $inVar2, $inVar3)
{
   if(!isset($inVar2)) $inVar2 = '';
   if(!isset($inVar3)) $inVar3 = '';
 
   $tmpString = $inVar.$inVar2.$inVar3;
 
   print $tmpString;
}
?>

En wat is daar dan mis aan?

Zo nutteloos als de functie is laat hij wel een veel gemaakte fout zien.

Je mag _nooit_ in PHP (en in practies alle talen) zo maar argumenten weglaten in de aanroep van de functie en zeker niet op een dusdanige manier controleren of ze bestaan (al is het beter dan helemaal niet).

Note:[edit]
Met 'zo maar weglaten' doel ik op het 'vergeten' van argumenten bij de aanroep van een functie terwijl je ze WEL in de functie-definitie hebt staan. Dus nadrukkelijk _NIET_ als je ze 'default' of een variabele function list gebruikt.

Wat nou man, ik krijg toch geen error ofzo!

Zet voor de grap eens 'error_reporting(E_ALL);' erboven en je zal zien dat je een Warning krijgt dat je variabele niet geset is.

Ok snappez-vous, maar hoe kan ik dan wel variabelen 'weglaten'

Dat kan bv door ze een default waarde te geven in de functie definitie.
PHP:
1
2
3
4
5
6
7
8
9
<?
 
function printConcat($inVar, $inVar2 = '', $inVar3 = '')
{
   $tmpString = $inVar.$inVar2.$inVar3;
 
   print $tmpString;
}
?>

Als je nu het 3e argument leeg laat dan word er automagisch '' (lege string) assigned. Als je het 2e EN 3e argument leeg laat gebeurt het bij beide.

Note: Je mag/kan alleen static values gebruiken, dus wel:
• $a = 'string'
• $a = 123
• $a = DEFINED_VAR

Maar NIET:
• $a = func_result()
• $a = 4/10
• $a = "str"."ing"
• $a = $var

Ok maar ik wil de 3e variabele graag defaulten en de 4e niet

Dan zal je ze moeten omwisselen :+ (of even doorlezen)

Ok maar ik heb nu altijd een variabel aantal variabelen. Hoe moet dat dan!

Daar heeft php 3 leuke functies voor namelijk:
func_num_args
func_get_args
func_get_arg

Nu zijn hier extreem duidelijke manual pages voor maar ik zal een klein (onzinnig) voorbeeldje geven.
PHP:
1
2
3
4
5
6
7
8
9
10
<?
function unknownArgs()
{
   $theArgs  = func_get_args(); // array van de argumenten
   $numArgs  = func_num_args(); // zelfde als count($theArgs)
 
   $firstArg = func_get_arg(0); // het eerste argument 
   $forthArg = func_get_arg(3); // en numero 4
}
?>

Ik hoop dat wat mensen hier iets aan hebben en dat we hier minder van die 'ranzige' (no offence) structuren (hier) tegen komen.

En natuurlijk nog de 2 belangrijkste dingen voor het coden in PHP :)
• indenting! - altijd en overal
• error_reporting(E_ALL)! - netjes leren coden, zonder fouten

  • razor-x
  • Registratie: Februari 2001
  • Laatst online: 05-06 07:37
* razor-x mijn error reporting naar error_reporting(E_ALL) :)
mooie uitleg!

btw grum_ ben je weer terug? , tijdje niet gezien :) .. jammer hoor :+

edit: Druk? niet anders als normaal dus ;)


  • Grum
  • Registratie: Juni 2001
  • Niet online
Zo'n 80 uur per week gewerkt, net 5 dagen gewintersport, ziekelijke deadlines voor over 4 weken liggen. Druk dus ;)

  • drm
  • Registratie: Februari 2001
  • Laatst online: 09-06-2025

drm

f0pc0dert

Grum_ Je verhaal is een beetje krom. Hoezeer ik het er ook mee eens ben, PHP is wat dit soort dingen betreft gewoon een bagger-taal.

Ik zal even aanstippen wat ik bedoel:
  • [i][sup]____________________________________________________________________________________[/sup] Je mag _nooit_ in PHP (en in practies alle talen) zo maar argumenten weglaten in de aanroep van de functie [/i][sup]____________________________________________________________________________________[/sup]
en bij variabel aantal argumenten:
PHP:
1
2
3
<?
function unknownArgs()
?>

Hier laat je in feite ook argumenten weg, die je later toch mee gaat geven...

Ik zou zeggen: probeer altijd een andere oplossing te vinden dan een variabel aantal argumenten. Dit is bijna alle gevallen te doen, behalve bij functies zoals sprintf, waarbij het aantal argumenten afhankelijk is van de inhoud van 1 van de argumenten. (vind ik heel vies, eigenlijk, maar je komt er niet zo goed onderuit...

verder complimenten voor het heldere stukje tekst, en beschouw deze post van mij maar niet als kritiek daarop, maar als miereneukerij :)

Music is the pleasure the human mind experiences from counting without being aware that it is counting
~ Gottfried Leibniz


  • Grum
  • Registratie: Juni 2001
  • Niet online
'Zo maar weglaten' is alleen als je/PHP ze verwacht. Aan de functie def kan je niet zien dat je ze verwacht als je func_get_args gebruikt dus geeft PHP geen warnings.

[edit] even iets verduidelijkt in de eerste post.

btw in c/c++ gaat dit precies hetzelfde alleen dan heb je '...' en va_list's :)

  • drm
  • Registratie: Februari 2001
  • Laatst online: 09-06-2025

drm

f0pc0dert

Grum_:
'Zo maar weglaten' is alleen als je/PHP ze verwacht. Aan de functie def kan je niet zien dat je ze verwacht als je func_get_args gebruikt dus geeft PHP geen warnings.
Dat snap ik wel, maar het is eigenlijk heel erg krom dat PHP je opzadelt met klusjes die eigenlijk voor de compiler zouden moeten zijn. Je roept een functie aan, die eigenlijk op compiler-niveau uitgevoerd moet worden, en niet op runtime niveau. Snap je wat ik bedoel?

Wat dat betreft vind ik PHP sowieso bagger, want als je na gaat denken over functies als "isdefined", "get_class", "is_subclass_of", "class_defined", etcetera moet je sowieso veel te veel opknappen, wat eigenlijk in de compiler verwerkt zou moeten worden.

Maar dat is een mening, en uiteraard sta ik open voor discussie *D

edit:
btw in c/c++ gaat dit precies hetzelfde alleen dan heb je '...' en va_list's
Weet ik, ja :) Vind ik ook niet netjes. Maar ik heb ook geen idee hoe je het anders op zou moeten lossen.

Eigenlijk is variabel aantal argumenten iets wat een "nette taal" (oei, flame? ;)) niet zou mogen ondersteunen. (Dan doel ik natuurlijk niet op default-argumenten)

Music is the pleasure the human mind experiences from counting without being aware that it is counting
~ Gottfried Leibniz


  • Nielsz
  • Registratie: Maart 2001
  • Niet online
Op woensdag 27 februari 2002 14:18 schreef drm het volgende:
Eigenlijk is variabel aantal argumenten iets wat een "nette taal" (oei, flame? ;)) niet zou mogen ondersteunen. (Dan doel ik natuurlijk niet op default-argumenten)
En wat is het verschil? Een argument wat je niet in hoeft te vullen, heeft altijd een defaultwaarde namelijk.

  • drm
  • Registratie: Februari 2001
  • Laatst online: 09-06-2025

drm

f0pc0dert

Nielsz:
En wat is het verschil? Een argument wat je niet in hoeft te vullen, heeft altijd een defaultwaarde namelijk.
Het verschil is dat jij niet het hele topic gelezen hebt

Music is the pleasure the human mind experiences from counting without being aware that it is counting
~ Gottfried Leibniz


  • Grum
  • Registratie: Juni 2001
  • Niet online
heee!! .. Tomato/Jaaap! hij zegt dat perl geen taal is! Haal de bloedhonden! :+
drm:
Het verschil is dat jij niet het hele topic gelezen hebt
kort maar waar ;)

  • drm
  • Registratie: Februari 2001
  • Laatst online: 09-06-2025

drm

f0pc0dert

Grum_:
heee!! .. Tomato/Jaaap! hij zegt dat perl geen taal is! Haal de bloedhonden! :+
:D ;) Ik zou niet durven...

Hoe is dat in Perl opgelost?

/so totally offtopic: goed om te zien dat je lief met een f schrijft, btw :)

Music is the pleasure the human mind experiences from counting without being aware that it is counting
~ Gottfried Leibniz


  • Grum
  • Registratie: Juni 2001
  • Niet online
perl doet niet aan defs :)
code:
1
2
3
4
5
6
7
8
9
10
11
12
13
sub ruigeFunctie
{
   my $inArg1 = shift(@_);
   my $inArg2 = shift;     # idem
   my @inArgs = @_;
}
 
# of

sub ruigereFunctie
{
  my ($inArg1, $inArg2, @inArgs) = @_;
}

liev is voor wannabee internet geweldenaren en voor -bee-losers >:) :+

  • Nielsz
  • Registratie: Maart 2001
  • Niet online
Op woensdag 27 februari 2002 14:29 schreef drm het volgende:

[..]

Het verschil is dat jij niet het hele topic gelezen hebt
Jawel, want door een $blaat='' mee te geven, geef je aan dat hij niet verplicht is om een waarde mee te geven. Als je dat niet doet wordt hij de waarde ''.

  • drm
  • Registratie: Februari 2001
  • Laatst online: 09-06-2025

drm

f0pc0dert

Grum_:
perl doet niet aan defs :)
Bij perl kan je toch kiezen wat je doet?
code:
1
# the perl-way
Ik moet zeggen dat ik dat al een stuk netter vindt.
liev is voor wannabee internet geweldenaren en voor -bee-losers >:) :+
liev is gewoon ranzig >:) *glad to agree*

Music is the pleasure the human mind experiences from counting without being aware that it is counting
~ Gottfried Leibniz


  • Johannes
  • Registratie: Juni 2000
  • Laatst online: 27-08 21:32
Ik wist niet eens dat dit mocht in PHP. Echt raar eigenlijk, zoiets zou toch niet moeten kunnen.
Op woensdag 27 februari 2002 14:18 schreef drm het volgende:
Eigenlijk is variabel aantal argumenten iets wat een "nette taal" (oei, flame? ;)) niet zou mogen ondersteunen. (Dan doel ik natuurlijk niet op default-argumenten)
En dat snap ik dan weer niet. Ik denk namelijk dat het vaak erg handig kan zijn. Als je bijvoorbeeld een class overerft, dan wil je vaak de functies van de onderliggende class overriden, maar ze in die functie wel aanroepen. Dit is vooral duidelijk bij constructors(in Python __init__):
Wat wil je:
code:
1
2
3
class Foo(Bar):
    def __init__(self, EigenVar, Bar1, Bar2, Bar3):
      Bar.__init__(self, Bar1, Bar2, Bar3)

of
code:
1
2
3
class Foo(Bar):
    def __init__(self, EigenVar, *PosArgs, **KwArgs):
      Bar.__init__(self, *PosArgs, **KwArgs)

Op zich lijkt er weinig verschil in lengte tussen, maar het grote voordeel is dat je heel makkelijk alle beschikbare arguments beschikbaar maakt aan de gebruiker van jouw class. Óok als de onderliggende class verandert door bijvoorbeeld een nieuwe versie van de library hoef jij je class niet te veranderen. Helaas is het niet zo makkelijk om dit mooi met multiple inheritance op te lossen.

Uit volle borst op weg naar nergens / Zonder reden zonder doel
Met m'n zeden en m'n zonden / En mijn angstig voorgevoel
Laat mij mijn kont tegen de krib / Laat mij dit goddeloze lied
Hef jij je handen maar ten hemel / Maar red mij niet


  • Grum
  • Registratie: Juni 2001
  • Niet online
drm: Bij perl kan je toch kiezen wat je doet?

I honestly can't remember *schaam*

drm: Ik moet zeggen dat ik dat al een stuk netter vindt.

Nu volg ik even niet waarover het gaat, maar ik denk over et 2e voorbeeld. Ik denk ook niet dat het tengoede komt voor de snelheid hoor zo 'flexibel' als perl is :)

Je kan gewoon ultiem smerige dingen ermee uithalen (zoals ik een tijdje geleden ook heb laten zien)

  • Johannes
  • Registratie: Juni 2000
  • Laatst online: 27-08 21:32
Op woensdag 27 februari 2002 15:02 schreef Nielsz het volgende:

[..]

Jawel, want door een $blaat='' mee te geven, geef je aan dat hij niet verplicht is om een waarde mee te geven. Als je dat niet doet wordt hij de waarde ''.
Dat bedoelt Grum_ dus niet. Het gaat erom dat je dit kan doen:
PHP:
1
2
3
4
5
6
<?
function Foo(Bar, Bar2){
    # Blaat
}
Foo(1) # Bar2 geef je niet op.
?>

Wat ook wel erg lelijk is.

Uit volle borst op weg naar nergens / Zonder reden zonder doel
Met m'n zeden en m'n zonden / En mijn angstig voorgevoel
Laat mij mijn kont tegen de krib / Laat mij dit goddeloze lied
Hef jij je handen maar ten hemel / Maar red mij niet


  • Grum
  • Registratie: Juni 2001
  • Niet online
Dat kan dus alleen maar als je een zielig, slechte, verrotte, door en door intrieste [more and more flames - without any offence] coder bent die gewoon :( !GEEN! :(

[gigantisch]<h1>error_reporting(E_ALL);</h1>[/gigantisch]

gebruikt.



<font color=red>D2k edit: zo groot genoeg Grum_ ;)?</font>

  • drm
  • Registratie: Februari 2001
  • Laatst online: 09-06-2025

drm

f0pc0dert

Grum_: [de trieste coder gebruikt geen error_reportig ( E_ALL );]
*applaudes* :D
Johannes: [ In OO omgeving m.b.t. inheritance is een definitie met variabel aantal argumenten in een over te erven functie wel handig]
Ik begrijp volgens mij niet zo goed wat je bedoelt.
Als je een baseclass maakt met daarin een definitie van een method die overge-erfd gaat worden, dan kan bij overerving het aantal argumenten toch prima aangepast worden?

vb
code:
1
2
3
4
5
6
7
8
9
10
11
12
class Foo
{
   function Bar ( $arg1, $arg2 ) { }
}

class FooChild extends Foo
{
   function Bar ()
   {
    Foo::Bar ( "blaat", "melp" );
   }
}

aangenomen dat je een dergelijke syntax begrijpt :)

Want volgens mij kom je dan meer in de sferen van function overloading, (wat PHP overigens ook niet ondersteunt |:()

Music is the pleasure the human mind experiences from counting without being aware that it is counting
~ Gottfried Leibniz


  • Johannes
  • Registratie: Juni 2000
  • Laatst online: 27-08 21:32
Op woensdag 27 februari 2002 15:25 schreef drm het volgende:
Ik begrijp volgens mij niet zo goed wat je bedoelt.
Als je een baseclass maakt met daarin een definitie van een method die overge-erfd gaat worden, dan kan bij overerving het aantal argumenten toch prima aangepast worden?

vb
code:
1
2
3
4
5
6
7
8
9
10
11
12
class Foo
{
   function Bar ( $arg1, $arg2 ) { }
}

class FooChild extends Foo
{
   function Bar ()
   {
    Foo::Bar ( "blaat", "melp" );
   }
}

aangenomen dat je een dergelijke syntax begrijpt :)
Ik begrijp de syntax wel, maar nu geef je de argumenten in FooChild op. Je wil juist dat die argumenten nog steeds op te geven zijn als je FooChild.Bar() aanroept. Je wil de complete functionaliteit van de onderliggende class beschikbaar maken, zonder dat jij je daar zorgen om moet maken.
In PHP zou het(geloof ik) zo moeten:
code:
1
2
3
4
5
6
7
class FooChild extends Foo
{
    function Bar()
    {
      call_user_func_array(Foo::Bar, func_get_args())
    }
}

Uit volle borst op weg naar nergens / Zonder reden zonder doel
Met m'n zeden en m'n zonden / En mijn angstig voorgevoel
Laat mij mijn kont tegen de krib / Laat mij dit goddeloze lied
Hef jij je handen maar ten hemel / Maar red mij niet


  • Grum
  • Registratie: Juni 2001
  • Niet online
Als het goed is hoeft je als jij een class extend en in de onderliggende class een functie defined en dat NIET doet in de 'bovenste' class geen rare dingen te doen om functies in de 'onderste' class aan te roepen.
PHP:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<?
class Base
{
        function Test($inVar)
        {
                print $inVar;
        }
}
 
class Extended extends Base
{
 
}
 
$theClass = new Extended();
$theClass->Test('Test text');
?>

dat werkt dus

  • tomato
  • Registratie: November 1999
  • Niet online
Overloading zou voor dit soort dingen wel aardig uitkomen in PHP, maar dit zou dan nog alleen maar gebaseerd kunnen zijn op het aantal argumenten:
PHP:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<?
// Functie voor machtsverheffen
function macht ($a, $b) {

   $retval = 1;

   for ($i=0; $i<$b; $i++)
      $retval = $retval * $a;

   return $retval;

}

// Overloaden, a wordt gekwadrateerd
function macht ($a) {

   return macht ($a, 2);

}
?>

Eigenlijk ook niet zo'n mooi voorbeeld, een functie 'kwadrateren ($a)' zou hier beter op zijn plek zijn, maar dit geeft aan wat in PHP gewoon niet kan.
Terwijl dit nog een vorm van overloading is die zonder al te veel moeite in PHP gebouwd zou kunnen worden: function overloading gebaseerd op het aantal argumenten.

Function overloading gebaseerd op de typen van de argumenten wordt sowieso erg lastig in PHP omdat er geen vaste typechecker is en geen type declaratie nodig is.

In Perl 6 gaan we volgens mij zelfs context based function overloading zien (wat nu veel built-in functies en operators al kennen) :9


In Perl kun je overigens wel op deze manier een sub definieren
code:
1
2
3
sub hoi () {
   return 'hoi';
}

om bijvoorbeeld aan te geven dat je 0 argumenten verwacht (en accepteert).


Persoonlijk vind ik het niet echt fout om in PHP default values voor argumenten op te geven en ze eventueel in een functie aanroep weg te laten (maar beperk dit). Waar ik erg op tegen ben is het weglaten van argumenten zonder default values (waar jullie het al over hadden).
Ook ben ik zeker niet gecharmeerd van constructies met 'func_get_args ()' voor functies met een 'ongedefinieerd' aantal argumenten. Zelfs bij een voorbeeld als 'printf ()' zou je kunnen overwegen als tweede argument gewoon een array te gebruiken.

  • Grum
  • Registratie: Juni 2001
  • Niet online
je kan in php niet 2x dezelfde functienaam declareren

  • tomato
  • Registratie: November 1999
  • Niet online
Grum_: je kan in php niet 2x dezelfde functienaam declareren
Precies, dat is een deel van wat ik bedoel ;)

  • drm
  • Registratie: Februari 2001
  • Laatst online: 09-06-2025

drm

f0pc0dert

Johannes: Ik begrijp de syntax wel
ok ;)
nu geef je de argumenten in FooChild op. Je wil juist dat die argumenten nog steeds op te geven zijn als je FooChild.Bar() aanroept. Je wil de complete functionaliteit van de onderliggende class beschikbaar maken, zonder dat jij je daar zorgen om moet maken.
In PHP zou het(geloof ik) zo moeten:
code:
1
2
3
4
5
6
7
class FooChild extends Foo
{
    function Bar()
    {
      call_user_func_array(Foo::Bar, func_get_args())
    }
}
Ja maar goed, het feit dat je hier een variabel aantal argumenten gebruikt met behulp van func_get_args() staat toch los van het OO ontwerp, hier, tenzij je in de baseclass al de mogelijkheid tot een variabel aantal argumenten geeft. Of begrijp ik je nou gewoon verkeerd :?
tomato:
Overloading zou voor dit soort dingen wel aardig uitkomen in PHP, maar dit zou dan nog alleen maar gebaseerd kunnen
idd. Ik vind dat er ook als de gesmeerde bliksem type-checking in PHP moet komen.
Terwijl dit nog een vorm van overloading is die zonder al te veel moeite in PHP gebouwd zou kunnen worden: function overloading gebaseerd op het aantal argumenten.
Mwjah, vind ik niet zo boeiend, eerlijk gezegd. Ik heb wat dat betreft niet zo veel op de ( $arg = "default" ) -constructie tegen.
Function overloading gebaseerd op de typen van de argumenten wordt sowieso erg lastig in PHP omdat er geen vaste typechecker is en geen type declaratie nodig is.
ja, helaas...
Persoonlijk vind ik het niet echt fout om in PHP default values voor argumenten op te geven en ze eventueel in een functie aanroep weg te laten (maar beperk dit). Waar ik erg op tegen ben is het weglaten van argumenten zonder default values (waar jullie het al over hadden).
We waren er idd al over uit dat dat ronduit uit den boze is :)

Music is the pleasure the human mind experiences from counting without being aware that it is counting
~ Gottfried Leibniz


  • drm
  • Registratie: Februari 2001
  • Laatst online: 09-06-2025

drm

f0pc0dert

Grum_:
Als het goed is hoeft je als jij een class extend en in de onderliggende class een functie defined en dat NIET doet in de 'bovenste' class geen rare dingen te doen om functies in de 'onderste' class aan te roepen.
PHP:
1
2
3
<?
meuk
?>

dat werkt dus
da's dus overerving :)

Music is the pleasure the human mind experiences from counting without being aware that it is counting
~ Gottfried Leibniz


  • Johannes
  • Registratie: Juni 2000
  • Laatst online: 27-08 21:32
Op woensdag 27 februari 2002 16:19 schreef drm het volgende:
Ja maar goed, het feit dat je hier een variabel aantal argumenten gebruikt met behulp van func_get_args() staat toch los van het OO ontwerp, hier, tenzij je in de baseclass al de mogelijkheid tot een variabel aantal argumenten geeft. Of begrijp ik je nou gewoon verkeerd :?
Ja, je begrijpt me verkeerd. Ik wil dat de argumenten rechtstreeks doorgegeven kunnen worden, zonder dat de class FooChild die argumenten hoeft te kennen. Hierdoor is het veel makkelijker om de interface van een onderliggende class én je eigen toevoeging te geven.

Uit volle borst op weg naar nergens / Zonder reden zonder doel
Met m'n zeden en m'n zonden / En mijn angstig voorgevoel
Laat mij mijn kont tegen de krib / Laat mij dit goddeloze lied
Hef jij je handen maar ten hemel / Maar red mij niet


  • D2k
  • Registratie: Januari 2001
  • Laatst online: 31-08 10:19

D2k

Doet iets met Cloud (MS/IBM)


  • Grum
  • Registratie: Juni 2001
  • Niet online
haha :P tnx

:* :*

  • drm
  • Registratie: Februari 2001
  • Laatst online: 09-06-2025

drm

f0pc0dert

Johannes:
Ja, je begrijpt me verkeerd. Ik wil dat de argumenten rechtstreeks doorgegeven kunnen worden, zonder dat de class FooChild die argumenten hoeft te kennen. Hierdoor is het veel makkelijker om de interface van een onderliggende class én je eigen toevoeging te geven.
Ja, daar heb je gelijk in. :)

Music is the pleasure the human mind experiences from counting without being aware that it is counting
~ Gottfried Leibniz

Pagina: 1