Tous les articles par Pascal MARTIN

RFC: Scalar Type Declarations (v0.5)

L’idée d’introduire des type-hints scalaires pour les paramètres de fonctions et méthodes est revenue plusieurs fois sur le devant de la scène ces dernières années.

Une première RFC « Scalar Type Hints » a récemment été jusqu’à la phase de votes (ceux-ci étant particulièrement serrés avec un nombre record de participants), mais a été retirée suite au départ de son auteur.

La demande de type-hints scalaires étant visiblement forte au niveau de la communauté (au vu des échanges sur twitter, du nombre de blog-posts sur le sujet, des réactions sur reddit, …), Anthony Ferrara a relancé l’idée quelques jours plus tard, avec une RFC forkée depuis celle d’Andrea :

Cette nouvelle version de la RFC introduisait quelques différences relativement mineures par rapport à la précédente version 0.3, qui était en cours de vote une semaine avant :

  • L’instruction declare() doit désormais être la première du fichier.
  • Elle ne peut plus être utilisée en mode bloc ; seulement en mode fichier entier.
  • Les aliases integer et boolean ont été supprimés.
  • Et un entier est maintenant considéré comme valide pour le type-hint float ; y compris en mode strict.

Une longue section « Discussion points » a également été ajoutée, visant à répondre à de nombreuses questions habituelles sur le sujet et la proposition.

L’adoption de cette RFC demandait une majorité des 2/3 des voix. Les votes ouvert le 26 février ont été clôturés le 13 mars 2015. Comme pour la version précédente de cette proposition, nous avons exprimé un avis positif sur internals@.

Finalement, avec 108 votes « pour » et 48 votes « contre » (un tel nombre de votes, c’est un record !), cette RFC a été acceptée ! PHP 7.0 disposera donc de type-hints scalaires !

RFC: Generator Return Expressions

Voici une première RFC qui visait à élargir le périmètre fonctionnel des générateurs ajoutés avec PHP 5.5 :

Note : cette proposition conditionne la RFC Generator Delegation, qui a été rédigée quelques jours plus tard.

Cette RFC proposait de permettre aux fonctions générateur l’utilisation de return avec une valeur (ce qui provoque aujourd’hui une Fatal Error). Une méthode Generator::getReturn() serait alors ajoutée pour permettre l’obtention de cette valeur de retour. Elle ne pourrait bien sûr être appelée qu’une fois la fonction génératrice terminée.

En somme, cela permettrait d’avoir une vraie valeur de retour explicite pour les générateurs, plutôt que de considérer que la dernière valeur yieldée joue ce rôle.

Les votes ont été ouvert le 09 mars pour être clôturés le 16 Mars 2015. Nous avons exprimé un avis positif sur internals@.
Et cette RFC a été acceptée à l’unanimité (33 votes « pour » et 0 vote « contre »).

RFC: Make empty() a Variadic

Voici une courte RFC autour de la construction empty() :

Cette RFC partait de l’idée qu’il est commun de vouloir utiliser empty() sur plusieurs variables, en vue de déterminer si l’une d’entre elles est vide ou si aucune ne l’est ; ce qui passe actuellement par une portion de code de ce type :

if (empty($a) || empty($b) || empty($c)) {
    // Une des variable est vide
}

if (!empty($a) && !empty($b) && !empty($c)) {
    // Aucune variable vide
}

Pour simplifier l’écriture de ce type de test, cette RFC proposait de rendre empty() variadique (comme l’est déjà isset()), ce qui permettrait d’utiliser l’écriture suivante :

if (empty($a, $b, $c)) {
    // Une des variable est vide
}

if (!empty($a, $b, $c)) {
    // Aucune variable vide
}

Passer plusieurs expressions à empty() reviendrait à effectuer un OR entre empty() de chaque expression.

Les votes ont été ouverts le 7 mars 2015 pour être clôturés le 21 mars. Considérant que cette proposition apporterait un fort risque de confusion (est-ce qu’on vérifie qu’au moins une donnée est vide ? Ou est-ce qu’on vérifie que toutes les données sont vides ?), nous avons exprimé un avis négatif sur internals@.

Une majorité des 2/3 était requise pour l’adoption de cette RFC et elle a été rejetée, avec 26 votes « pour » et 26 votes « contre ».

RFC : Improve array to string conversion

Voici une RFC qui tourne autour de la conversion de tableaux (array) en chaînes (string) : Improve array to string conversion

Cette RFC partait du constat que, aujourd’hui, convertir un array vers une string entraîne la levée d’une E_NOTICE et donne « Array » comme résultat… Autrement dit, une chaîne peu utile et seulement une semi-erreur.

Elle proposait au départ deux alternatives (opposées) visant à éliminer ce comportement problématique :

  • Interdire totalement la conversion array → string en levant une « catchable fatal error« , comme c’est déjà le cas pour la conversion object → string pour les classes n’ayant pas de méthode __toString().
  • Supporter réellement la conversion arraystring, en déterminant et implémentant un algorithme réalisant la conversion.

Après discussions sur internals@, la seconde option a été supprimée avant l’ouverture des votes, qui n’ont donc porté que sur la première.

Considérant que la conversion array → string n’était que rarement voulue et correspondait quasiment toujours à des cas de bugs, nous avons indiqué sur internals@ que nous étions en faveur de cette proposition.
La RFC a finalement été acceptée, avec 34 votes « pour » et 10 votes « contre ».

 

 

RFC: Expectations

Voici une RFC destinée à servir principalement en environnements de développement :

L’idée derrière cette RFC, basée sur la fonction assert(), est de permettre l’exécution de code de débogage, en développement uniquement. Cela permettrait à la fois d’identifier des problèmes (encore une fois, en environnements de développement) et de documenter le code. Plusieurs exemples illustrant les différents cas d’usage sont donnés dans la RFC.

En cas d’échec, la condition spécifiée en premier paramètre de assert() n’étant pas vraie, une exception de type AssertException (soit spécifiée en second paramètre, soit générée automatiquement) sera levée — passer par une exception plutôt qu’une erreur permettant d’obtenir plus facilement une stacktrace.

L’activation ou non des assertions serait paramétrée par le biais d’une directive .ini nommée zend.assertions, qui pourrait valoir :

  • 1 : pour générer et exécuter le code correspondant aux assertions : c’est la valeur qui sera généralement utilisée en environnement de développement
  • 0 : pour générer le code mais ne pas l’exécuter
  • -1 : pour ne pas du tout générer le code de l’assertion (coût nul, à utiliser en production)

L’API proposée par cette RFC est globalement compatible avec celle actuellement en place pour la fonction assert() existante : il s’agit surtout d’améliorer celle-ci, notamment en supprimant complétement la génération et l’exécution du code de l’assertion en mode « production ».

Les votes se sont tenus du 19 au 26 février et nous avons exprimé un avis plutôt négatif sur internals@, considérant principalement que mélanger le code et les tests n’était pas l’approche qui nous semblait la meilleure et ne souhaitant donc pas encourager l’utilisation de assert().
Les résultats ont finalement été les suivants, cette RFC est donc passée :

  • 20 « oui » avec exceptions personnalisées
  • 11 « oui » sans exception personnalisée
  • 1 seul et unique « non »

RFC: Group Use Declarations

Voici une RFC qui proposait d’ajouter une possibilité syntaxique à PHP, visant à faciliter l’utilisation d’espaces de noms : Group Use Declarations

Pour résumer, cette RFC partait du constat qu’écrire de multiples utilisations d’espaces de noms à plusieurs niveaux de profondeur entraîne une longueur de code impressionnante. Elle proposait donc l’introduction d’une nouvelle syntaxe, qui permettrait de réduire l’espace utilisé par ces use multiples et de rendre le code moins verbeux.

Par exemple, la portion de code suivante :

use Doctrine\Common\Collections\Expr\Comparison;
use Doctrine\Common\Collections\Expr\Value;
use Doctrine\Common\Collections\Expr\CompositeExpression;

Pourrait être ré-écrite de la manière suivante :

use Doctrine\Common\Collections\Expr\{ Comparison, Value, CompositeExpression };

La RFC présente d’autres cas d’exemples, avec des « use ... as ...« , des use function ou const et montre que la syntaxe n’est pas limitée au dernier niveau de chaque espace de noms. Elle répond également à certains retours « communs » sur la proposition et sa syntaxe.

Les votes ont été ouverts le 11 février 2015 et pour être clôturés le 25 février, avec deux options :

  • « Oui », avec un \ à la fin de l’inclusion (le dernier : dans l’exemple reproduit plus haut ...\Expr\{} ),
  • « Oui », sans cet \ à la fin de l’inclusion — on aurait donc ...\Expr{}
  • Et, bien sûr, « non »

Les discussions que nous avons menées sur notre mailing-list ne nous ont pas permis d’atteindre un consensus et nous avons exprimé sur internals@ les principaux arguments auxquels nous étions arrivés.

Une majorité de 2/3 était requise pour son adoption, et cette RFC a été approuvée avec les résultats suivants :

  • Oui, avec un \ à la fin de l’inclusion : 32 voix;
  • Oui, sans le \ à la fin de l’inclusion : 7 voix;
  • Non : 19 voix

RFC: Loop… or

La RFC Loop… or… proposait d’ajouter un bloc, optionnel, aux structures de boucles (for, while et foreach) de PHP, exécuté dans le cas où on n’entre jamais dans la boucle — la condition n’étant pas vérifiée, dès le premier passage. Ce bloc aurait été introduit par le mot-clef or, afin d’éviter d’ajouter un nouveau mot réservé.

Il est ressorti de nos échanges que la majorité d’entre nous était plutôt pour cette fonctionnalité, même si n’étions pas à 100% de oui et que plusieurs auraient aimé pouvoir utiliser else plutôt que or, ou disposer de quelque chose de plus complet répondant à plus de cas. J’ai donc posté en ce sens sur internals@.

Arrivée au moment de la phase de votes, cette RFC a été quelque peu mise de côté et elle n’a pas été acceptée. À voir si une solution plus complète, répondant à plus de cas que le seul « on n’est jamais entré dans la boucle » reviendra sur le devant de la scène dans le futur !

RFC: Suppression des tags alternatifs

La RFC Remove alternative PHP tags partait du principe que les tags alternatifs (tags « ASP » <% ou <%= et %>, ainsi que <script language="php"> et </script>) ne sont quasiment jamais utilisés — sans compter qu’ils entrent parfois en conflit avec certains langages de templating.

Nous avons été assez nombreux à échanger sur le sujet, majoritairement d’accords sur le fait que ces tags ne sont quasiment jamais utilisés et qu’il serait acceptable de les supprimer, pour ne laisser que les balises <?php, <? et <?= les plus connues. J’ai donc posté en ce sens sur internals@.

Cette RFC a été acceptée, avec une large majorité. Les tags alternatifs disparaitront donc, pour PHP 7.

RFC: Interdire l’usage de plusieurs ‘default’ dans un ‘switch’

La RFC Make defining multiple default cases in a switch a syntax error partait du constat qu’il est aujourd’hui possible, en PHP, de placer plusieurs sections default dans un bloc switch.

Par exemple, en PHP 5.6, il est possible d’écrire ceci :

$a = 10;
switch ($a) {
    case 1:
        echo "cas 1\n";
        break;
    default:
        echo "premier default\n";
        break;
    default:
        // C'est dans ce second default qu'on passe, pas dans le premier
        echo "second default\n";
        break;
}

Dans ce cas, c’est la dernière section default qui est utilisée par PHP (là où, différences d’implémentation oblige, HHVM utilise la première).

Bien sûr, les discussions sur la mailing-list php-internals@afup ont montré que nous étions tous d’accord sur le fait qu’utiliser deux cas default dans une même structure switch n’a pas de sens et devrait donc être interdit et lever une erreur de syntaxe (en PHP 7). De plus, si PHP 5.7 sort un jour, cela devrait lever un avertissement E_DEPRECATED, pour préparer l’arrivée de PHP 7.  J’ai donc posté en ce sens sur internals@.

Cette RFC ayant été acceptée quelques jours après, PHP 7 sera plus cohérent sur ce point.

RFC: Opérateur null-coalesce ??

La RFC Null Coalesce Operator proposait d’introduire un nouvel opérateur ?? qui renverrait le résultat de sa première opérande s’il existe et est différent de NULL (en comparaison stricte), et celui de sa seconde opérande sinon.

Le constant de départ était que l’opérateur ?: introduit avec PHP 5.3 est pratique, mais pas parfait : il peut notamment entrainer des levées de notices si sa première opérande n’existe pas (ce qui force souvent à utiliser isset()).

Avec le nouvel opérateur ?? proposé par cette RFC, il deviendrait possible d’écrire quelque chose de ce type, qui ne lèverait pas de notice si $_GET['user'] n’existe pas :

$username = $_GET['user'] ?? 'nobody';

Les échanges que nous avons eu sur la mailing-list php-internals@afup ayant montré que notre avis était plutôt positif et qu’un tel opérateur apporterait une valeur à PHP, j’ai posté en ce sens sur internals@.

La RFC correspondante à été acceptée et ce nouvel opérateur ?? devrait arriver avec PHP 7 !

Notons que l’ajout d’un opérateur d’affectation ??= n’a pour l’instant pas été jugé utile. Il pourra, bien sûr, être ajouté dans le futur, s’il s’avère qu’il est nécessaire.