Twitter iPhone pliant OnePlus 11 PS5 Disney+ Orange Livebox Windows 11

Valeur par defaut d'un parametre vari ant

12 réponses
Avatar
Sylvain SF
Soit une fonction à param. variant que l'on souhaite
pouvoir appeler sans transmettre de paramètre:

function foo(&$a = null){ ... }

a) est-ce que /null/ est une "bonne valeur par défaut" ?
(j'ai l'impression que cela créé localement un variable
$a initialisée à null).

b) comment savoir si un paramètre est effectivement transmis?

isset($a), ($a == null) ne semble pas permettre de décider.

nota: j'ai bien lu §17 "Making arguments be passed by reference"
et "Default argument values", mais je n'ai trouvé aucun passage
combinant les 2.

Sylvain.

10 réponses

1 2
Avatar
Bruno Desthuilliers
Sylvain SF a écrit :
Soit une fonction à param. variant



? "variant" ?

que l'on souhaite
pouvoir appeler sans transmettre de paramètre:

function foo(&$a = null){ ... }

a) est-ce que /null/ est une "bonne valeur par défaut" ?



C'est à toi de le savoir. Disons qu'en général oui, du moins si tu veux
indiqué que le paramètre n'a pas été transmis *ET* que NULL n'est pas
une valeur licite pour cet argument.

(j'ai l'impression que cela créé localement un variable
$a initialisée à null).



nan ?

b) comment savoir si un paramètre est effectivement transmis?



Dans la mesure où rien n'empêche d'appeler la fonction en lui passant
explicitement NULL, tu ne peux pas savoir !-)

Maintenant, si ta question est "comment savoir si la valeur de $a est
NULL", tu a deux tests possibles:

* is_null($a)
* $a === NULL (note les *3* '=')

isset($a), ($a == null) ne semble pas permettre de décider.



D'après la doc, isset() devrait fonctionner (=>"Determine if a variable
is set and is not NULL."). Par contre, c'est un peu overkill puisque tu
sais que $a sera définie de toute façon.

pour ce qui est de "$a == NULL", (et de tout autre test d'"égalité" -
hum...), je te recommande de bien lire la doc (opérateurs de
comparaison), la notion d'"égalité" en PHP étant pour le moins
particulière :-/


nota: j'ai bien lu §17 "Making arguments be passed by reference"
et "Default argument values", mais je n'ai trouvé aucun passage
combinant les 2.



Ca ne fait guère de différence pratique dans ton cas, il me semble.
Avatar
Mickael Wolff
Sylvain SF a écrit :
Soit une fonction à param. variant que l'on souhaite
pouvoir appeler sans transmettre de paramètre:

function foo(&$a = null){ ... }



Tu confonds deux notions : les fonctions à paramètres ayant une
valeur par défaut et les fonctions variadiques (comme en C).

Tout d'abord, faire une référence à null en PHP5 est interdit. En
effet, il n'est possible de ne passer que des variables par référence.
null étant un scalaire, ce n'est pas une variable. Ton code par défaut
lèvera une Fatal error « Only variables can be passed by reference »

Quand aux fonctions à nombre variables d'arguments, tu as les
fonctions func_num_arg et func_get_args (attention au pluriel !) qui
fournissent respectivement le nombre d'arguments passés à la fonction et
un tableau des arguments passés à la fonction.

a) est-ce que /null/ est une "bonne valeur par défaut" ?



Oui, mais pas pour une référence ;)

(j'ai l'impression que cela créé localement un variable
$a initialisée à null).



Oui.

nota: j'ai bien lu §17 "Making arguments be passed by reference"
et "Default argument values", mais je n'ai trouvé aucun passage
combinant les 2.



C'est parce que tu ne regardais pas au bon endroit ;)
<http://fr.php.net/manual/en/book.funchand.php>

--
Mickaël Wolff aka Lupus Michaelis
http://lupusmic.org

Seeking for a position <http://lupusmic.org/pro/>
Avatar
Sylvain SF
Mickael Wolff a écrit :
Sylvain SF a écrit :
Soit une fonction à param. variant que l'on souhaite
pouvoir appeler sans transmettre de paramètre:

function foo(&$a = null){ ... }



Tu confonds deux notions : les fonctions à paramètres ayant une valeur
par défaut et les fonctions variadiques (comme en C).



non je ne confonds pas !

le but est bien (ici) d'avoir un seul(!) paramètre variant (passé par
référence).

le proto n'est pas variadique, si tu lis bien les *accolades* et non
les parenthèses, tu liras que le corps de la fonction est ici sans
objet (ou presque), peut être que l'écriture suivante permettra de
limiter les mauvaises interprétations:

function foo(&$a = null)
{
// il y a surement un corps de fonction
// mais ce n'est pas l'objet de la question
}

Tout d'abord, faire une référence à null en PHP5 est interdit.



je ne sais pas ce que voudrais dire "faire une référence" !

"transmettre une référence nulle" ou mieux inexistante devrait
être interdit / impossible, je m'attendais à cela, ce n'est pas le cas.

effet, il n'est possible de ne passer que des variables par référence.
null étant un scalaire, ce n'est pas une variable. Ton code par défaut
lèvera une Fatal error « Only variables can be passed by reference »



nullement, as-tu essayé ?
j'aurais préféré qu'il couine sur un des appels mais ce n'est pas
le cas:

function foo(&$a = null){
$a++;
}

$k = 0;
echo $k;
foo($k);
echo $k;
foo();
echo $k;

affiche:
0
1
1

et pas la moindre fatal error.
or en effet, la référence à un "$a" quand rien n'est transmis ne devrait
pas exister.

Quand aux fonctions à nombre variables d'arguments



elles ne sont pas le sujet.

a) est-ce que /null/ est une "bonne valeur par défaut" ?



Oui, mais pas pour une référence ;)



alors on mets quoi ?

en clair, quelle est l'approche la plus PHP possible de:

/* code C++ */

void foo(int* i = NULL)
{
if (i)
*i++;
}

int a = 0;
foo(&a);
foo();

C'est parce que tu ne regardais pas au bon endroit ;)
<http://fr.php.net/manual/en/book.funchand.php>



cela n'a rien à voir.

Sylvain.
Avatar
Sylvain SF
Sylvain SF a écrit :

C'est parce que tu ne regardais pas au bon endroit
<http://fr.php.net/manual/en/book.funchand.php>



cela n'a rien à voir.



ok, hormi func_num_args() qui permet (ici) de décider.

je note 'ici' car par extension, on pourrait regretter
qu'il ne comptabilise pas les paramètres substitués
dans les passages par valeurs, ie

function foo($a = ??){
echo func_num_args();
}

foo(/any/); => 1
foo(); => 0

mais dans ce cas on voudra généralement traiter la valeur
sans distinction (transmisse ou valeur par défaut).

Sylvain.
Avatar
Mickael Wolff
Sylvain SF a écrit :

le but est bien (ici) d'avoir un seul(!) paramètre variant (passé par
référence).


Qu'est-ce que tu appelles « variant » ?

le proto n'est pas variadique, si tu lis bien les *accolades* et non
les parenthèses, tu liras que le corps de la fonction est ici sans
objet (ou presque), peut être que l'écriture suivante permettra de
limiter les mauvaises interprétations:


J'avais bien compris que tes ... ne devaient pas être confondus avec
la liste de paramètres. J'essayais de faire avec ce que tu appelle « une
fonction à param. variant ». Les paramètres sont variables par défaut,
j'essayais juste de comprendre si tu voulais des fonctions avec des
paramètres avec une valeur par défaut ou des fonctions totalement
variadiques.

Dans le cas des paramètres à valeurs par défaut, le nombre de
paramètres est **toujours** le même, que tu les indiques à l'utilisation
ou non. Dans l'autre cas, le seul moyen est d'utiliser func_get_args.

function foo(&$a = null)
{
// il y a surement un corps de fonction
// mais ce n'est pas l'objet de la question
}

Tout d'abord, faire une référence à null en PHP5 est interdit.



je ne sais pas ce que voudrais dire "faire une référence" !


<http://fr2.php.net/manual/en/language.references.php>


"transmettre une référence nulle" ou mieux inexistante devrait
être interdit / impossible, je m'attendais à cela, ce n'est pas le cas.


Ça l'est. Tu es tombé sur un bogue.

nullement, as-tu essayé ?


Oui. Mais pas en donnant le scalaire en valeur par défaut.

et pas la moindre fatal error.
or en effet, la référence à un "$a" quand rien n'est transmis ne devrait
pas exister.


Vivi, c'est aussi un bogue pour moi. Car si tu écris foo(null), il
couine. Toi aussi tu as le droit de contribuer <http://bugs.php.net/> ;)
J'ai cherché un bogue éventuellement déjà déclaré, mais je n'ai rien trouvé.

je viens de tomber sur ça
<http://stackoverflow.com/questions/280385/php-by-reference-parameters-and-default-null>
mais ça ne nous avance pas beaucoup.

Quand aux fonctions à nombre variables d'arguments



elles ne sont pas le sujet.


Ben si, le seul moyen de savoir si on a passé un argument est de
demander commbien d'arguments ont été passés à la fonction. Et pour
connaître ce nombre, il faut utiliser func_num_args.

alors on mets quoi ?


Rien. Tu peux passer des paramètres surnuméraires sans que
l'interpréteur couine, et de les exploiter avec func_get_args.

en clair, quelle est l'approche la plus PHP possible de:

/* code C++ */

void foo(int* i = NULL)
{
if (i)
*i++;
}



Les pointeurs n'existent pas en PHP, et les références n'en sont pas
l'équivalent. Les références en PHP5 se comportent comme les références
de Java. Mais pas comme celles de C++, ce serait plutôt équivalent à un
std::auto_ptr.

C'est parce que tu ne regardais pas au bon endroit ;)
<http://fr.php.net/manual/en/book.funchand.php>



cela n'a rien à voir.



Ben si, complètement.

--
Mickaël Wolff aka Lupus Michaelis
http://lupusmic.org

Seeking for a position <http://lupusmic.org/pro/>
Avatar
Sylvain SF
Mickael Wolff a écrit :
Sylvain SF a écrit :

le but est bien (ici) d'avoir un seul(!) paramètre variant (passé par
référence).


Qu'est-ce que tu appelles « variant » ?



c'est explicité dans la texte quoté ("passé par référence",
soit "non par valeur"). je ne pensais pas ce terme ambigu.

J'avais bien compris que tes ... ne devaient pas être confondus avec
la liste de paramètres. [...]



bien, on peux s'en désintéresser alors.

Tout d'abord, faire une référence à null en PHP5 est interdit.



je ne sais pas ce que voudrais dire "faire une référence" !


<http://fr2.php.net/manual/en/language.references.php>



hmmm, je sais ce qu'est une référence, merci.
par contre "faire une référence" ?!... (faire et avoir ne
sont pas les verbes les plus explicites).

"transmettre une référence nulle" ou mieux inexistante devrait
être interdit / impossible, je m'attendais à cela, ce n'est pas le cas.


Ça l'est. Tu es tombé sur un bogue.
[...]


Vivi, c'est aussi un bogue pour moi. Car si tu écris foo(null), il
couine. Toi aussi tu as le droit de contribuer <http://bugs.php.net/> ;)



bien sur, il traite correctement le passage (effectif) de tout scalaire
(dont 'null') et l'interdit; mais la possibilité de définir une valeur
par défaut pour une variable-référence est ambigue (pas nécessairement
un "bug", juste "ambigu", ce support est peut être voulu mais je ne
trouve aucun exemple ni commentaire dans les docs).

Quand aux fonctions à nombre variables d'arguments


elles ne sont pas le sujet.


Ben si, le seul moyen de savoir si on a passé un argument est de
demander combien d'arguments ont été passés à la fonction. Et pour
connaître ce nombre, il faut utiliser func_num_args.



oui, ma 2nd réponse, func_num_args() permet en effet de savoir
si le paramètre est effectivement transmis et si c'est la valeur
par défaut.

en clair, quelle est l'approche la plus PHP possible de:
/* code C++ */


Les pointeurs n'existent pas en PHP, et les références n'en sont pas
l'équivalent. Les références en PHP5 se comportent comme les références
de Java. Mais pas comme celles de C++, ce serait plutôt équivalent à un
std::auto_ptr.



on va dire que je sais ce qu'est un pointeur ou une réf, hein.
une réf. Java est toujours une instance or ici on parle (aussi)
de scalaire passé par référence ce qui n'existe pas en Java.
le '&$' de PHP ressemble plus au '&' de C++ et lui interdirait
foo(type& x = /scalar/).

Sylvain.
Avatar
Pascal PONCET
Sylvain SF a écrit :

function foo(&$a = null){
$a++;
}

$k = 0;
echo $k;
foo($k);
echo $k;
foo();
echo $k;

affiche:
0
1
1

et pas la moindre fatal error.
or en effet, la référence à un "$a" quand rien n'est transmis ne devrait
pas exister.



Bonjour Sylvain,

As-tu regardé là ? (note #3, exemple #2) :
http://fr.php.net/manual/fr/language.references.whatdo.php

Cordialement,
Pascal
Avatar
Sylvain SF
Pascal PONCET a écrit :

As-tu regardé là ? (note #3, exemple #2) :
http://fr.php.net/manual/fr/language.references.whatdo.php



merci, cela justifie le comportement observé.
Sylvain.
Avatar
Mickael Wolff
Sylvain SF a écrit :
c'est explicité dans la texte quoté ("passé par référence",
soit "non par valeur"). je ne pensais pas ce terme ambigu.


Très ambigu, surtout quand on a un jour touché à boost::variant
<http://www.boost.org/doc/libs/1_39_0/doc/html/variant.html> ;)

hmmm, je sais ce qu'est une référence, merci.
par contre "faire une référence" ?!... (faire et avoir ne
sont pas les verbes les plus explicites).


Certes, par « faire une référence à », j'entends « déclarer une
référence à ».

bien sur, il traite correctement le passage (effectif) de tout scalaire
(dont 'null') et l'interdit; mais la possibilité de définir une valeur
par défaut pour une variable-référence est ambigue (pas nécessairement
un "bug", juste "ambigu", ce support est peut être voulu mais je ne
trouve aucun exemple ni commentaire dans les docs).


J'ai posé la question sur la ML. On va voir si ça déclenche une
flamewar et éventuellement un rapport de bogue ;) Entre temps, j'ai
aussi regardé le source de PHP, mais je ne suis pas parvenu à déterminer
ce qui se passe à ce niveau. Je ne maîtrise malheureusement pas bison.

on va dire que je sais ce qu'est un pointeur ou une réf, hein.
une réf. Java est toujours une instance or ici on parle (aussi)
de scalaire passé par référence ce qui n'existe pas en Java.
le '&$' de PHP ressemble plus au '&' de C++ et lui interdirait
foo(type& x = /scalar/).


Ne te fâche pas, je préfère dissiper les mal-entendus. J'ai moi-même
déjà été embrouillé par ces histoires de référence (mais c'est surtout
dû au fait que je jongles parfois entre PHP4 et PHP5).

Je reviendrais quand j'aurais des réponses pertinentes sur la ML.


--
Mickaël Wolff aka Lupus Michaelis
http://lupusmic.org

Seeking for a position <http://lupusmic.org/pro/>
Avatar
Mickael Wolff
Mickael Wolff a écrit :
Je reviendrais quand j'aurais des réponses pertinentes sur la ML.



Bon, il suffisait de demander au bon endroit. La raison est tellement
évidente que j'ai honte de ne pas y avoir pensé ^^; Bon, ben c'est
définitivement un effet de bord. Voici la réponse d'un participant
(David Otton) de la ML PHP General :

« The problem is that you can't pass literals by reference (which makes
sense):

function f(&$a) {}
f(45); // error

But default values must be literals (which also makes sense):

function f($a = $_POST) {} // error

So there's some serious impedance mismatch going on there to make both
features to work together. »

--
Mickaël Wolff aka Lupus Michaelis
http://lupusmic.org

Seeking for a position <http://lupusmic.org/pro/>
1 2