Discussion:
Valeur par defaut d'un parametre vari ant
(trop ancien pour répondre)
Sylvain SF
2009-07-03 07:16:59 UTC
Permalink
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.
Bruno Desthuilliers
2009-07-03 10:15:09 UTC
Permalink
Post by Sylvain SF
Soit une fonction à param. variant
? "variant" ?
Post by Sylvain SF
que l'on souhaite
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.
Post by Sylvain SF
(j'ai l'impression que cela créé localement un variable
$a initialisée à null).
nan ?
Post by Sylvain SF
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* '=')
Post by Sylvain SF
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 :-/
Post by Sylvain SF
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.
Mickael Wolff
2009-07-03 16:22:42 UTC
Permalink
Post by Sylvain SF
Soit une fonction à param. variant que l'on souhaite
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.
Post by Sylvain SF
a) est-ce que /null/ est une "bonne valeur par défaut" ?
Oui, mais pas pour une référence ;)
Post by Sylvain SF
(j'ai l'impression que cela créé localement un variable
$a initialisée à null).
Oui.
Post by Sylvain SF
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/>
Sylvain SF
2009-07-03 18:51:08 UTC
Permalink
Post by Sylvain SF
Soit une fonction à param. variant que l'on souhaite
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.
Post by Sylvain SF
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.
Sylvain SF
2009-07-03 20:37:09 UTC
Permalink
Post by Sylvain SF
Post by Mickael Wolff
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.
Mickael Wolff
2009-07-04 07:32:42 UTC
Permalink
Post by Sylvain SF
le but est bien (ici) d'avoir un seul(!) paramètre variant (passé par
référence).
Qu'est-ce que tu appelles « variant » ?
Post by Sylvain SF
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
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.
Post by Sylvain SF
function foo(&$a = null)
{
// il y a surement un corps de fonction
// mais ce n'est pas l'objet de la question
}
Post by Mickael Wolff
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>
Post by Sylvain SF
"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.
Post by Sylvain SF
nullement, as-tu essayé ?
Oui. Mais pas en donnant le scalaire en valeur par défaut.
Post by Sylvain SF
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.
Post by Sylvain SF
Post by Mickael Wolff
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.
Post by Sylvain SF
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.
Post by Sylvain SF
/* 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.
Post by Sylvain SF
Post by Mickael Wolff
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/>
Sylvain SF
2009-07-04 16:05:22 UTC
Permalink
Post by Mickael Wolff
Post by Sylvain SF
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.
Post by Mickael Wolff
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.
Post by Mickael Wolff
Post by Sylvain SF
Post by Mickael Wolff
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).
Post by Mickael Wolff
Post by Sylvain SF
"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.
Post by Sylvain SF
[...]
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).
Post by Mickael Wolff
Post by Sylvain SF
Post by Mickael Wolff
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.
Post by Mickael Wolff
Post by Sylvain SF
/* 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.
Mickael Wolff
2009-07-06 10:16:39 UTC
Permalink
Post by Sylvain SF
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> ;)
Post by Sylvain SF
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 à ».
Post by Sylvain SF
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.
Post by Sylvain SF
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/>
Mickael Wolff
2009-07-06 15:46:33 UTC
Permalink
Post by Mickael Wolff
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/>
Pascal PONCET
2009-07-06 18:53:18 UTC
Permalink
Post by Mickael Wolff
« The problem is that you can't pass literals by reference (which makes
sense) ...
J'ai chopé ça, aussi :
http://bugs.php.net/bug.php?id=6343

PP
Sylvain SF
2009-07-06 19:56:49 UTC
Permalink
Post by Mickael Wolff
« The problem is that you can't pass literals by reference (which makes
function f(&$a) {}
f(45); // error
function f($a = $_POST) {} // error
c'est l'exposé du "problème": j'ai envie de dire que l'on ne
traite pas ici d'une "default value" (valeur stockée par cette
variable) mais bien de l'existence de cette référence.

par exemple, j'apprécierais de pouvoir écrire:

function f(&$a = new myClass()){
}

ce qui donne bien sur une erreur car seul un literal (une
valeur immédiate) est attendu ici.
Post by Mickael Wolff
So there's some serious impedance mismatch going on there to make both
features to work together. »
indeed.

merci pour ton suivi et report.

Sylvain.

Pascal PONCET
2009-07-04 16:05:22 UTC
Permalink
Post by Sylvain SF
function foo(&$a = null){
$a++;
}
$k = 0;
echo $k;
foo($k);
echo $k;
foo();
echo $k;
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
Sylvain SF
2009-07-05 07:03:26 UTC
Permalink
Post by Pascal PONCET
http://fr.php.net/manual/fr/language.references.whatdo.php
merci, cela justifie le comportement observé.
Sylvain.
Continuer la lecture sur narkive:
Loading...