[PHP5.1] STRING ITERATOR

malalam Messages postés 10839 Date d'inscription lundi 24 février 2003 Statut Membre Dernière intervention 2 mars 2010 - 6 nov. 2007 à 07:58
neigedhiver Messages postés 2480 Date d'inscription jeudi 30 novembre 2006 Statut Membre Dernière intervention 14 janvier 2011 - 9 nov. 2007 à 14:38
Cette discussion concerne un article du site. Pour la consulter dans son contexte d'origine, cliquez sur le lien ci-dessous.

https://codes-sources.commentcamarche.net/source/44623-php5-1-string-iterator

neigedhiver Messages postés 2480 Date d'inscription jeudi 30 novembre 2006 Statut Membre Dernière intervention 14 janvier 2011 19
9 nov. 2007 à 14:38
Cela dit, la question du back() est intéressante...
Le foreach permet de parcourir un objet, du début à la fin. Point. Ca ne sert à rien d'autre, je crois qu'on est tous d'accord sur ça. Si on veut quelque chose de plus complet, on peut toujours le faire. En fait, back() c'est jamais qu'un seek(key() -1).
Si a priori ça n'a pas de raison d'être dans une boucle foreach, il est des cas où, parfois, on peut avoir besoin de revenir en arrière, pour un cas spécifique. Donc même au milieu d'un foreach, rien n'empêche de revenir 1 ou 2 enregistrements en arrière, éventuellement parce que celui-ci a été modifié par le traitement de l'enregistrement situé 1 ou 2 places plus loin.
Bref... Voilà voilà ^^
neigedhiver Messages postés 2480 Date d'inscription jeudi 30 novembre 2006 Statut Membre Dernière intervention 14 janvier 2011 19
9 nov. 2007 à 14:35
Peut-être, mais moi, je posais pas la question dans le contexte ici présent, je voulais juste savoir de quoi il s'agissait, d'une manière générale ;)
Je viens de comprendre avec ta réponse ^^
popGG Messages postés 23 Date d'inscription mardi 31 mai 2005 Statut Membre Dernière intervention 9 novembre 2007
9 nov. 2007 à 13:30
back() (contraire du next()), remove ou autres... ne servent à rien ici donc laisses tomber ce que je viens de dire. Je voulais juste pinailler...

@+
neigedhiver Messages postés 2480 Date d'inscription jeudi 30 novembre 2006 Statut Membre Dernière intervention 14 janvier 2011 19
9 nov. 2007 à 09:48
popGG : "En parlant du remove, je suis d'accord avec toi mais je suis toujours pas convaincu de l'exemple donné ici puisque je ne vois aucun appel aux fonctions de cette classe"
=> C'est parce qu'elles n'ont pas à être utilisées directement par l'utilisateur (le développeur). Ces méthodes sont appelées automatiquement par la boucle foreach.
Lors d'une utilisation avec while, il faut les utiliser manuellement.
C'est là toute la puissance de l'itérateur associé à foreach : apporter à un objet des méthodes que l'on n'a pas à gérer ensuite. On se contente de les définir, ce qui permet de contrôler ce qu'elles font, et elles sont appelées automatiquement.
C'est pourquoi j'utilisais foreach pour itérer, et non while.

"Imaginez que l'on souhaite implémenter une fonction qui réalise un back. On risque d'être emmerdé avec le foreach...."
=> C'est quoi un back ? Pour moi, c'est le dos, mais c'est surement pas ce dont tu parles ici ^^
popGG Messages postés 23 Date d'inscription mardi 31 mai 2005 Statut Membre Dernière intervention 9 novembre 2007
9 nov. 2007 à 09:11
2-neigedhiver: "je préfère utiliser un filtre : FilterIterator"
En fait, si tu souhaite réellement rajouter une autre classe, je te conseille directement de prendre l'iterator objet. Ainsi j'aurais surement pas écris autant ;b

@malalam: "vous êtes encore hors sujet, selon moi"
Je suis d'acc avec toi. Je suis pas là pour débattre sur le remove:

neigedhiver-2-popGG: "Quelle serait l'utilité de la méthode remove() ?
Supprimer le prochain enregistrement ? Mais avant, ou après l'avoir lu ?
Et pourquoi faire ça ? "

J'ai juste expliqué le sens d'un remove puisqu'on me l'a demandé. Mais je veux plus me répéter donc je le dis une dernière fois: Il sert à rien ici!!!!!!!!!
Je ne cherche pas à pinailler puisque je m'en fous du remove LOL... Mon exemple n'a pas été fait pour faire un concours avec l'exemple de neigedhiver. Je pensais que, de cette classe, on pouvait en sortir un but pédagogique pour ceux qui commencait avec les itérateurs.

@malalam: "vous ratez l'essentiel"
En parlant du remove, je suis d'accord avec toi mais je suis toujours pas convaincu de l'exemple donné ici puisque je ne vois aucun appel aux fonctions de cette classe donc c'est comme réaliser un exemple qui n'a rien avoir avec la classe. Imaginez que l'on souhaite implémenter une fonction qui réalise un back. On risque d'être emmerdé avec le foreach.... Mais bon, je veux plus me répéter donc je n'insiste plus... En tout cas, c'était simpa. Je pense qu'on se reverra sur d'autres post ;b

Hasta pronto chiquillos
malalam Messages postés 10839 Date d'inscription lundi 24 février 2003 Statut Membre Dernière intervention 2 mars 2010 25
8 nov. 2007 à 19:59
Eh, les gars : pourquoi vous restez bloqué sur les exemples que vous avez produit?
Si cette classe n'a pas d'intérêt, expliquez-moi l'intérêt de ceci :
interface Iterator {
public function valid();
public function next();
public function key();
public function rewind();
public function current();
}
Ca ne sert à RIEN. Enfin...ça ne sert à RIEN...seul.
Mais ça sert beaucoup quand a été créé SplFileObject, DirectoryIterator, ArrayObject...etc.

Je pourrais, à partir de cette interface, développer un exemple sur lequel -visiblement- vous débatriez des heures parce qu'il est simpliste et finalement, ne sert pas non plus à grand chose en l'état. Mais c'est un exemple...on ne va pas écrire une application complète juste pour montrer comment on peut implémenter une classe ?

Comme je l'ai dit un peu avant, vous êtes encore hors sujet, selon moi.

Si j'ai mis 10 à cette source, c'est parce qu'elle est parfaite par rapport à ce qu'elle veut faire, selon moi encore (les modifications de Kankrelune mises à part, j'avoue que je n'avais pas prêté attention aux petits manques côté optimisation).

Un exemple de pinaillage : je pourrais dire à popGG que son exemple :
$ptitMot = 'Bonjour';
for($i=0 ; $i<strlen($ptitMot);$i++){
echo $ptitMot[$i]; // <- Réalisation de ton itérateur sans aucune autre fonction définie dans ta classe
}
n'est absolument pas optimisé. Parce qu'on ne met pas strlen() au sein de l'expression d'un for().
Mais c'est du pinaillage, parce que j'ai très bien compris où il voulait en venir. Le strlen() mal placé n'a aucun intérêt ici. On s'en fout.

La discussion est intéressante, aucun problème de ce côté-ci, mais vous ratez l'essentiel.
OUI, un remove() aurait son intérêt. Voire un replace() puisqu'on y est.
Ca enlève quoi que ce soit à l'idée de base : utiliser les itérateurs pour remplacer le type string de base ? Moi je ne le pense pas! Je pense que l'idée est très bonne. Charge aux développeurs de se servir de l'idée. Comme les dév de PHP l'ont fait à partir de leur idée de base de l'interface Iterator (et que personne ne vienne pinailler en me disant qu'ils ne sont pas partis de Iterator, mais que c'était un projet global dès le départ: je le sais!).
neigedhiver Messages postés 2480 Date d'inscription jeudi 30 novembre 2006 Statut Membre Dernière intervention 14 janvier 2011 19
8 nov. 2007 à 16:08
"Ici mon remove a un sens tu trouves pô? "
Ben non... Parce que pour ne m'occuper que des lettres et pas des autres caractères, je préfère utiliser un filtre : FilterIterator en faisant un itérateur qui soit une classe étendue de FilterIterator.
La méthode accept() me renseignerait alors sur le besoin de traiter ou non le caractère. Ainsi, je produis une chaine sans toucher à la chaine d'origine, ce qui me semble important.
popGG Messages postés 23 Date d'inscription mardi 31 mai 2005 Statut Membre Dernière intervention 9 novembre 2007
8 nov. 2007 à 16:00
"Donc ton exemple, s'il a pour seul but de produire une chaine dans laquelle on a supprimé quelques caractères ne me semble pas illustrer StringIterator et ne justifie pas, à mes yeux, la méthode remove()."

Ummh. Restons sur mon exemple deux secondes...

Donc considère que ta première itération constitue une chaine de caractères spéciaux (!,é,ç,ñ,...)...
Le remove n'est pas si idiot ici... Et je suis resté fidèle à ton StringIterator...

Rappel :
Wikipedia:
ROT13: Le défaut de ce chiffrement est que s'il s'occupe des lettres, il ne s'occupe pas des chiffres, des symboles et de la ponctuation. C'est pourquoi on supprime du texte à chiffrer toute accentuation, et si on veut conserver un texte correctement chiffré, il est nécessaire d'écrire les nombres en toutes lettres.

Ici mon remove a un sens tu trouves pô?

"c'est pas parce que je suis un peu passionné dans mes messages que je m'énerve"
Je ne t'ai pas senti énervé. Moi je trouve nos échanges intéressants. 2 ans inscrits et j'ai jamais autant écrit. LOL
neigedhiver Messages postés 2480 Date d'inscription jeudi 30 novembre 2006 Statut Membre Dernière intervention 14 janvier 2011 19
8 nov. 2007 à 14:18
popGG : ben oui... Mais je me posais depuis le début la question de l'utilité de cet itérateur. En fait, si je n'en ai pas trouvé sur le net de déjà développé, c'est peut-être pour une raison...
Comme je le disais aussi, la plupart des opérations sur les chaines peuvent être réalisées par des fonctions natives. Donc côté performances, c'est vite vu... Entre une fonction en C et une classe en PHP, pas besoin de benchmark pour savoir laquelle est la plus performante.

Cependant... Certaines fonctions nécessitent un traitement caractère par caractère. C'est le cas, notamment, d'une transformation par rotation, comme par exemple ROT13.
La transformation ROT13 existe déjà en php sous la forme d'une fonction native C. Cependant, une transformation par rotation avec un décalage de X caractères, X pouvant être une valeur allant de -25 à 25 (c'est à dire n'importe quel ebtier naturel modulo 26), se fait caractère par caractère.
Là, deux écoles : la récursivité et l'itération. L'une est procédurale, l'autre objet.
Mon exemple, qui n'est pas une transformation par rotation mais par remplacement, illustre l'école itération. On pourrait faire pareil avec une fonction récursive. On pourrait aussi utiliser un tableau de correspondance avec des paires clés/valeurs. Tout dépend du contexte du script en fait.

Donc ton exemple, s'il a pour seul but de produire une chaine dans laquelle on a supprimé quelques caractères ne me semble pas illustrer StringIterator et ne justifie pas, à mes yeux, la méthode remove().

Le mien peut être discuté, mais il n'est pas possible de le remplacer par 3 lignes de codes utilisant des fonctions natives (ou alors j'ai la tête trop dans les choux). Cependant, on peut peut-être y trouver un remplaçant sans itérateur et plus performant.
Si StringIterator ne permet pas plus de clarté, dégrade nettement les performances, alors il est inutile.
S'il ne dégrade pas les performances dans certains cas et permet un peu de clarté, alors pourquoi ne pas l'utiliser ?
Simplement, les cas où cette classe peut être utile sont sûrement très très rares et très très spécifiques.

Donc oui, ici, on s'intéresse à l'itération. Mais pour moi, l'itération ce n'est pas juste une manière de penser le développement. C'est aussi des performances et de la clarté dans le code. Et je m'intéresse aussi à ces deux points...

Bref, je pense que d'une manière générale, on est sur la même longueur d'onde. On chipotte pour pas grand chose. Mais chippoter pour pas grand chose, ça me semble important. Les discussions théorico-abstraites de Programmation Objet m'intéressent, et c'est pas parce que je suis un peu passionné dans mes messages que je m'énerve.
Pinaillons donc, moi, j'adore ça.
popGG Messages postés 23 Date d'inscription mardi 31 mai 2005 Statut Membre Dernière intervention 9 novembre 2007
8 nov. 2007 à 13:16
Je pense que tu n'as pas bien compris ce que je viens de dire:

Tu pars d'une classe qui sert à rien à priori...
Mais tu l'as fais non? Donc:

Si tu dis ensuite
"Euh... Si c'est juste pour supprimer des caractères, c'est pas sorcier :

$aLettresEnTrop = str_split('aeiou');
$sChaineAEpurer = 'Bonjour monsieur le controleur...')
echo str_replace($aLettresEnTrop, '', $sChaineAEpurer);"

Alors que je te rappelle qu'ici on s'intéresse à l'itération! Alors
Ta phrase:
"Ce qui me semble être le résultat des deux boucles d'itération. Ou alors j'ai pas compris (ce qui est tout à fait possible).
Là, je crois que question perf, y'a pas photo..."
est en train de te contredire sur tout ce que tu as fait jusqu'ici....
neigedhiver Messages postés 2480 Date d'inscription jeudi 30 novembre 2006 Statut Membre Dernière intervention 14 janvier 2011 19
8 nov. 2007 à 11:46
@popGG :
"Je suis d'accord avec toi mais si je suis ton idée, alors ta classe StringIterator perd également tout son sens également"

=> C'est bien ce que je dis depuis le début... Qu'elle n'a peut-être aucune utilité...
popGG Messages postés 23 Date d'inscription mardi 31 mai 2005 Statut Membre Dernière intervention 9 novembre 2007
8 nov. 2007 à 10:13
@neigedhiver : Je suis d'accord avec toi mais si je suis ton idée, alors ta classe StringIterator perd également tout son sens également car je peux facilement réaliser ceci:

$ptitMot = 'Bonjour';

for($i=0 ; $i<strlen($ptitMot);$i++){
echo $ptitMot[$i]; // <- Réalisation de ton itérateur sans aucune autre fonction définie dans ta classe
}

Là aussi, question perf, y'a pas photo ;b
Moi je donnais juste un exemple utilisant ta classe (afin que celle-ci ait également un sens ;b) et également te montrer l'utiliter du remove iterator (en général)

@audayls: "Surtout qu'en gros tout le monde pense pareil mais ne l'exprime pas de la même manière"
-> Moi je voulais juste un exemple... C'est qui m'a fait réagir dans ce post ainsi que la présence d'un 10 alors que je trouvais la source trop légère. Sans démonstration, personnellement, même si le reste est beau, bah ça reste incomplet donc c'est incompréhensible de voir une note parfaite.

"je pensais pas qu'un itérateur aussi idiot provoquerait autant de discussions"
Pour finir, on en conclut tous que cette classe ne vaut pas l'itérateur d'objet mais j'aime cette classe car elle permet d'initier certaines personnes (je parle des futurs programmeurs) aux iterators et de bien comprendre le principe avant de passer à la version objet qui est plus complète et puissante donc moins facile à maitriser. Tout ça pour dire que cette classe n'est pas si idiote...

"Je vois bien comment ça fonctionne, mais l'utilité (on parle du remove)... Je veux dire, y'en a surement une, mais ton exemple ne me parle pas. Mais alors pas du tout. J'arrive pas à voir l'utilité d'imbriquer deux boucles d'itération."
Ici, il n'y en a pas c'est sûr. Mais si tu utilises des iterators objets, alors tout change et la fonction remove a un sens
neigedhiver Messages postés 2480 Date d'inscription jeudi 30 novembre 2006 Statut Membre Dernière intervention 14 janvier 2011 19
8 nov. 2007 à 01:36
Salut,

"au lieu de passer par une multitude de fonction "str_*" qui aurait fait exactement le même résultat."
=> Euh... Si c'est juste pour supprimer des caractères, c'est pas sorcier :

$aLettresEnTrop = str_split('aeiou');
$sChaineAEpurer = 'Bonjour monsieur le controleur...')
echo str_replace($aLettresEnTrop, '', $sChaineAEpurer);

Affiche : Bnjr mnsr l cntrlr
Ce qui me semble être le résultat des deux boucles d'itération. Ou alors j'ai pas compris (ce qui est tout à fait possible).
Là, je crois que question perf, y'a pas photo...
audayls Messages postés 373 Date d'inscription samedi 9 juillet 2005 Statut Membre Dernière intervention 11 août 2008
8 nov. 2007 à 00:42
Salut,

(Petit commentaire avant dodo et cours demain (Oh my god >_<))

Moi j'l'aime bien l'exemple de popGG =P Dans cet exemple on peut facilement afficher les modifications que subit la chaîne au lieu de passer par une multitude de fonction "str_*" qui aurait fait exactement le même résultat.

La discution que provoque cette source est tout de même extrement interessante =) Surtout qu'en gros tout le monde pense pareil mais ne l'exprime pas de la même manière XD
neigedhiver Messages postés 2480 Date d'inscription jeudi 30 novembre 2006 Statut Membre Dernière intervention 14 janvier 2011 19
8 nov. 2007 à 00:22
@popGG : Désolé, j'ai rien compris... Je vois bien comment ça fonctionne, mais l'utilité... Je veux dire, y'en a surement une, mais ton exemple ne me parle pas. Mais alors pas du tout. J'arrive pas à voir l'utilité d'imbriquer deux boucles d'itération.
Quel doit être le résultat de ton exemple ?
Désolé, j'arrive pas à exprimer ce qui me chiffonne...

@Malalam : en y repensant, je vois pas non plus pourquoi mon exemple est con lol
Bêtement, str_rot13 doit très certainement itérer sur la chaine passée en argument. On pourrait écrire une fonction qui s'appellerait str_rot qui prendrait deux arguments : une chaine et un entier, pour ne pas nécessairement faire de décalage de 13. Dans ce cas, un itérateur simplifie grandement le code.
Pour mon exemple, pareil : on a beosin d'itérer sur la chaine pour traiter tous les caractères un par un. On pourrait utiliser une fonction récursive, comme on en trouve une dans les commentaires de la doc php de la fonction str_rot13. Je ne me pose pas la question des performances, juste celle de la lisibilité.

Ben en tout cas, je pensais pas qu'un itérateur aussi idiot provoquerait autant de discussions... Epatant. Mais tant mieux :)
neigedhiver Messages postés 2480 Date d'inscription jeudi 30 novembre 2006 Statut Membre Dernière intervention 14 janvier 2011 19
7 nov. 2007 à 22:53
LoL

Désolé, j'ai pas trouvé mieux. Si t'en as un moins con, je prends :D
malalam Messages postés 10839 Date d'inscription lundi 24 février 2003 Statut Membre Dernière intervention 2 mars 2010 25
7 nov. 2007 à 20:08
Je le trouve plus tordu que con, moi, ton exemple :-) Mais il est très intéressant et pédagogique : but atteint.
De tte manière, moi, je n'avais pas besoin d'être convaincu de l'intérêt d'un "remove()". Je le voyais très bien. Je ne le mettrais juste pas dans une classe StringIterator, mais dans une classe StringObject, justement. Etendant StringIterator. Mais ça, c'est du pinaillage et tient seulement de la préférence.

Je trouve l'exemple de neige bcp plus con que le tien, en fait :-p
popGG Messages postés 23 Date d'inscription mardi 31 mai 2005 Statut Membre Dernière intervention 9 novembre 2007
7 nov. 2007 à 10:57
@Malalam: "remove() cher à popGG"
LOL. En fait, remove comme je l'ai signalé plus haut est optionnel en JAVA donc pas vraiment cher à mes yeux.

"Quelle serait l'utilité de la méthode remove() ?
Supprimer le prochain enregistrement ? Mais avant, ou aprèsl'avoir lu ?
Et pourquoi faire ça ? Quel besoin de vider la variable sur laquelle on itère ?"

Arfff. Je vais t'avouer que je ne manipule des iterators qu'à partir de collections d'objet qui sont en générale des listes chainées... Donc j'utilise principalement remove des listes, pas celle ces iterators....

Maintenant, en cherchant bien un exemple (con sinon j'arriverais pas à m'en sortir), imagines que tu réalises une opération qui nécessite 2 boucles d'itérateurs, dont celles-ci sont assez lourdes (en règle générale, on évite cette situation, mais comme c'est un exemple con, ça passe...). Maintenant que nous avons ces deux boucles, imagines que tu réalises à l'intérieur une comparaison bidon du style: "si objet = objet, alors ACCION". Pour finir, imagine que chaque objet provenant de l'iterator1 est unique donc ce qui signifie que dans ton iterator2 chaque élément portant le nom objet devienne inutile (en trop)...... Je supprime donc chaque élément de mon second iterator afin d'aléger ma deuxième boucle lors d'un nouveau passage de ma première boucle.

OK, je donne l'exemple mais je suis un bleu en php donc soyez pas trop dur avec moi:

// Création de mes 2 échantilloneurs (iterator)
$iterator1 = new StringIterator('oaeiu....'); // Lettres non répétées (unique). Dans notre cas, il n'y a que 26 lettres donc rien de lourd mais les iterators sont souvent utilisés pour des objets uniques
$iterator2 = new StringIterator('Bonjour monsieur le controleur...');

// Je réaliserais mon propre exemple. Désolé mais je n'arrive pas à adhérer au foreach ici...
while($iterator1->valid()){
$iterator1->next(); // Si next = next + current, cette ligne disparait
while($iterator2->valid()){
$iterator2->next(); // Pareil
if($iterator1->current() $iterator2->current()){ // Si next next + current, current devient next
echo $iterator1->current();
$iterator2->remove(); // supprime le caractère courant!!! -> celui-ci $iterator2->current()
}
}
$iterator2->rewind();
}

Pas à pas:
$iterator1->current() = 'o'
$iterator2->current() = 'M'
-> rien

$iterator2->next()

$iterator1->current() = 'o'
$iterator2->current() = 'o'
-> p'tit echo + on supprime l'échantillon de l'iterator2

... On continue jusqu'à la deuxième boucle de l'iterator1

-> Maintenant, à ce moment précis, lorsque ton iterator correspond à :
$iterator2 = new StringIterator('Bnjur mnsieur le cntrleur...');

Conclusion: le remove d'un iterator te permet ici d'exécuter l'opération plus rapidement. Maintenant, c'est un exemple con...

J'espère avoir pu t'éclaircir un peu sur la puissance que peut produire un remove d'un iterator. Cela évite d'instancer un nouvel iterator par la suite

-------

Bon, maintenant, je rapelle encore une fois: ce qui m'intéressait avant toute chose, c'était l'exemple et hasnext (valid ici mais je l'avais pas reconnu). Bien que j'ai fait la remarque sur le remove, ici il ne te servira pas car si chacun de tes échantillons est un char, tu n'auras que 26 clés uniques pour ton premier iterator, donc ça n'a pas vraiment d'importance...
En tout cas, merci d'avoir fourni un exemple. Bonne continuation pour la suite
malalam Messages postés 10839 Date d'inscription lundi 24 février 2003 Statut Membre Dernière intervention 2 mars 2010 25
7 nov. 2007 à 07:51
Heu....je demanderai à l'auteur. On verra bien :-)
neigedhiver Messages postés 2480 Date d'inscription jeudi 30 novembre 2006 Statut Membre Dernière intervention 14 janvier 2011 19
7 nov. 2007 à 02:23
Voilà... Histoire de faire plaisir à tout le monde, j'ai rajouté un petit exemple :)
Une fonction de codage par remplacement suivant un tableau de correspondance.
L'exemple est loin d'être complet et sécurisé : il ne tient compte que des lettres, le reste, je sais pas comment c'est géré...

@malalam : y'a moyen d'avoir la source dont tu parles pour ceux qui ne sont pas inscrits sur phpclasses.org ou qui ont perdu leur login/pass et qui ont la flemme de le récupérer ?
malalam Messages postés 10839 Date d'inscription lundi 24 février 2003 Statut Membre Dernière intervention 2 mars 2010 25
6 nov. 2007 à 23:21
Oui, je parlais bien de type hinting :-)
Je profite de cette discussion parce que je viens justement de découvrir quelque chose : il y a sur phpclasses.org un code tout récent de type hinting! Je n'ai pas encore eu le temps de le tester ni d'approfondir ma lecture du code, mais il m'a l'air très intéressant et très bien foutu! Il surcharge les types php pour les rendre utilisables comme typage des paramètres dans l'appel d'une méthode : string, integer, boolean etc...
Bref : public myFunction(in $iInt, bool $bBool, string $sString...);
neigedhiver Messages postés 2480 Date d'inscription jeudi 30 novembre 2006 Statut Membre Dernière intervention 14 janvier 2011 19
6 nov. 2007 à 23:08
LOL je viens de percuter... Je souligne que je comprends pas ton exemple, et je parle ensuite de typage objet... Ah bravo... Je sais pas si je suis trop ou pas assez fatigué moi...
neigedhiver Messages postés 2480 Date d'inscription jeudi 30 novembre 2006 Statut Membre Dernière intervention 14 janvier 2011 19
6 nov. 2007 à 23:07
@Malalam
"...en faisant une classe dérivée, utilisant le StringIterator, on pourrait en arriver à faire ceci :
public myMethod(string $sString);"

=> Pas compris...

L'intérêt d'un StringObject, concrètement, je n'en vois pas l'application directe.
En fait, si je n'en vois pas l'application directe, ce n'est pas pour autant que je n'aime pas l'idée (sinon je n'en aurais pas parlé). Depuis que je m'amuse avec la SPL (merci Malalam d'avoir insisté dans un tuto en disant que tu étais en croisade, et merci à d'autres qui mettent des itérateurs partout) j'ai tendance à vouloir avoir des objets pour tout. Que ça ait une application concrète ou non. En fait, avoir des objets partout (ou presque) ça permet :
- d'avoir une logique de développement vraiment orientée objet
- d'utiliser le typage objet implicite (explicite plutôt...?)
Je regrette qu'on ne puisse pas surcharger les opérateurs comme en Python.

Bref. Malalam, tu le verrais comment ce StringObject ?
malalam Messages postés 10839 Date d'inscription lundi 24 février 2003 Statut Membre Dernière intervention 2 mars 2010 25
6 nov. 2007 à 21:21
@popGG => je ne suis pas non plus idiot : tu ne m'as pas compris. J'avais très bien saisi que tu ne confondais pas LITTERALEMENT java et php. Je tentais de te dire de ne pas faire d'amalgame. Ce n'est pas parce qu'un type/une classe se comporte d'une certaine manière dans un langage, qu'il faut en reproduire le schéma exact dans un autre.

@tous => (et ça concerne aussi les remarques de popGG), attention à ne pas vous tromper de sujet. Le but ici était de montrer ce que donnerait un overloading du type string via les itérateurs. TRès exactement comme ArrayIterator. ArrayIterator rajoute plusieurs méthode,s certes : des sort()...dont je ne vois pas l'intérêt pour un StringIterator, un append, et des accès DONT le "remove()" cher à popGG. Mais, les accès (dont le "remove()", offsetUnset() en fait, et un ...heu...) ne font pas directement partie de la classe ArrayIterator; ils sont hérités de ArrayAccess. C'est ainsi que les dév de php ont choisi d'implémenter ces classes d'itération. Si on ajoute à une classe StringIterator un "remove()" (offsetUnset irait très bien), il y ajouter un append ET un offsetSet (c'est différent, append() ajoutant une nouvelle entrée au tableau...offsetSet() modifiant la valeur d'une entrée du tableau).
Personnellement, je le verrais ailleurs, justement, dans une classe d'accès.

Ce qui m'étonne, c'est que vous demandez des fonctionnalités, quand le but du code est de donner une base.

Maintenant, l'intérêt de tout ça? Il y en a beaucoup, en fait. Déjà, étendre afin d'obtenir, justement, des fonctionnalités. Ensuite, une éventualité : la surcharge. Cela permet de surcharger le type string. Ce qui peut parfois être très intéressant, parce qu'en faisant une classe dérivée, utilisant le StringIterator, on pourrait en arriver à faire ceci :
public myMethod(string $sString);
Et du coup, je vois très bien, moi, l'intérêt d'un StringObject. Mais pas dans le sens ArrayObject, plutôt de celui d'un SplFileObject.
coucou747 Messages postés 12303 Date d'inscription mardi 10 février 2004 Statut Membre Dernière intervention 30 juillet 2012 44
6 nov. 2007 à 19:47
comme on a pas d'overloading de fonctions, je ne vois pas l'utilite d'une classe StringObject personellement.

en java, t'as comme en php des types de bases (int, char, etc...) c'est pas parce-que String est, tout comme Integer une class, qu'il n'y a pas de types de bases
neigedhiver Messages postés 2480 Date d'inscription jeudi 30 novembre 2006 Statut Membre Dernière intervention 14 janvier 2011 19
6 nov. 2007 à 19:26
@Kankrelune : pour tes deux dernières corrections, je crois que je vois... J'ai remplacé count() par iLen...
neigedhiver Messages postés 2480 Date d'inscription jeudi 30 novembre 2006 Statut Membre Dernière intervention 14 janvier 2011 19
6 nov. 2007 à 19:21
merci Kankrelune pour tes commentaires.

Les deux premières corrections apportent effectivement un gain de performance non négligeable (après test, y'a vraiment pas photo).

Pour les deux derniers, par contre, euh...

if ($this -> count() == 0)

>>

if($this->iKey === 0)

Là, je suis pas d'accord.

// iKey vaut X, on s'en fout
$si -> rewind();
// iKey vaut alors 0
if($this->iKey === 0)
// La variable n'est pas forcément vide, je ne dois pas lever d'exception...

Et le dernier correctif, t'as du te planter dans ton copier/coller, parce que tu me proposes de corriger avec le code d'origine...

Pour ce qui est de mettre un exemple, il faudrait quasiment développer une application complète qui met en oeuvre StringIterator. Et euh bon...
En fait, ça fait un peu long à caser dans mon emploi du temps : je préfère passer du temps à coder des clasess plutôt que des exemples...
kankrelune Messages postés 1293 Date d'inscription mardi 9 novembre 2004 Statut Membre Dernière intervention 21 mai 2015
6 nov. 2007 à 18:58
Bonjour tout le monde... .. .

Concernant le code en lui même...

return substr($this -> sString, $this -> iKey, 1);

>>

return $this->sString[$this->iKey];

et

return $this -> iKey < strlen($this -> sString);

>>

return isset($this->sString[$this->iKey]);

-------

if ($this -> count() == 0)

>>

if($this->iKey === 0)

------

if ($iPos >= $this->iKey || $iPos < 0)

>>

if($iPos >= $this->iKey || $iPos < 0)

sera quand même mieux... .. .

Sinon je sais que ça a déjà été abordé mais je ne vois effectivement pas l'utilité de cette classe en l'état... je sais que tu (neigedhiver) as précisé que l'on pouvait faire la même chose avec des fonctions natives de php, que l'on pouvait faire une classe plus complète permettant la manipulation des données, et que ce n'était pas ton but de faire une tel classe... je n'en dirais donc pas plus mais l'idée d'une classe stringObject peut être interessante (?)

Sinon je trouve que cette classe peut avoir un but "pédagogique" pour illustrer les itérateurs de php... par contre, toujours dans l'idée du pédagogique, un petit exemple aurait effectivement été pas mal car une personne voulant s'informer sur le sujet mettra peut être du temps à comprendre l'utilité de ces méthodes... .. .

@ tchaOo°
neigedhiver Messages postés 2480 Date d'inscription jeudi 30 novembre 2006 Statut Membre Dernière intervention 14 janvier 2011 19
6 nov. 2007 à 18:17
@popGG : Quelle serait l'utilité de la méthode remove() ?
Supprimer le prochain enregistrement ? Mais avant, ou aprèsl'avoir lu ?
Et pourquoi faire ça ? Quel besoin de vider la variable sur laquelle on itère ?
neigedhiver Messages postés 2480 Date d'inscription jeudi 30 novembre 2006 Statut Membre Dernière intervention 14 janvier 2011 19
6 nov. 2007 à 17:12
Hum...

Il y a une différence d'utilisation entre while et foreach. Même si les deux peuvent être utilisés pour faire la même chose.
Quand tu fais while($si -> valid()) , c'est à toi de gérer plusieurs choses :
- l'incrémentation
- la récupération de la valeur
Quand je fais foreach ($si as $sLetter) ma boucle foreach fait tout pour moi : elle incrémente toute seule l'index (iKey), elle récupère le contenu ($sLetter) et elle vérifie que le résultat est valide (valid()).
Mon foreach va mettre dans la variable $sLetter le résultat de $si -> current().
Quand j'itère sur un répertoire, chaque item est un fichier (fichier qui peut aussi être un dossier, puisque pour Unix tout est fichier).
Quand j'itère sur une chaine, chaque item est une lettre. Donc ma variable $sLetter n'est pas inutile...
Quant à faire un jeu du pendu, c'est sûrement utilisable dans ce contexte. Je ne me suis pas posé la question.
En fait, j'ai juste pensé, comme ça, d'un coup, que techniquement, je pouvais faire un itérateur sur un chaine de caractères. Je l'ai fait.
Il manque d'illustration, certes : encore une fois, je n'en avais pas sur le moment.
Je me suis même posé la question de l'utilité de ce code, c'est dire si je croulais sous les exemples...

Ma classe avait pour but uniquement d'être un itérateur.
Si on regarde un peu la SPL, on constate que l'interface Iterator ne définit pas plus de méthodes que celles que j'ai implémentées. Par contre, on constate qu'il existe d'autres classes qui implémentent d'autres méthodes : RecursiveIterator, DirectoryIterator, RecursiveDirectoryIterator, etc.
Si tu trouves que ma classe qui n'a pour vocation que de présenter un itérateur strictement, tu peux tout à fait proposer ici même une classe qui étend ma classe StringIterator et qui y ajoute quelques méthodes qui permettent de faire autre chose.

Je n'ai pas une formation de développeur, ni d'analyste, ni rien. Je suis qu'un technicien de maintenance de formation. Mais depuis presque 10 ans que je pratique php, j'ai pu apprendre quelques rudiments, comme notamment qu'en POO, ce qui prime, c'est la portabilité, la modularité et la maintenance du code. Faire des classes très générales que l'on étend par des classes plus spécifiques, c'est, à mon sens, la base de la POO. Si je fais une seule classe qui propose 250 000 méthodes juste parce qu'elles pourraient toutes être utiles dans un cas précis, ça me semble ne pas correspondre aux règles et aux standards de XP (eXtrem Programming), dont je n'ai que quelques notions, mais quand même.

Pour conclure, je suis d'accord avec toi : on peut rajouter à ma classe méthodes qui font plein de choses intéressantes. Mais ce n'était pas son but premier. C'est une classe de base, qui mérite peut-être d'être étendue.
D'ailleurs, tu as su me convaincre : je ne lui trouvais aucun intérêt, mais finalement... Elle en a peut-être plus que je ne pensais...
Donc c'est avec plaisir que j'écrirai d'autres classes qui étendront mon StringIterator pour lui appoorter d'autres méthodes pour d'autres utilisations.
popGG Messages postés 23 Date d'inscription mardi 31 mai 2005 Statut Membre Dernière intervention 9 novembre 2007
6 nov. 2007 à 15:44
@Malalam : "Ces 4 méthodes sont les 4 méthodes que TOUT itérateur php DOIT implémenter". Tu ne convaincras pas quelqu'un déjà convaincu. Je ne critiquais pas sur le fait que ces 4 fonctions de la classe stringIterator devaient être implémenter car je suis de même convaincu que l'on doit les définir. Le nom de la méthode importe peu du moment que sa fonctionnalité existe... Je n'ai pas essayé la source et j'ai pas fait la relation entre valid et hasnext

"tu confonds Java et PHP" -> Je suis pas idiot mec... Faut pas abuser non plus.... Je n'ai jamais fait de comparaison entre les deux languages de programmation mais je faisais, ici, un clin d'oeil sur la DEFINITION d'une itération... J'ai eu le temps de m'informer sur la classe avant de savoir que remove n'y était pas défini. Mais en COMPARANT ces deux DEFINITIONS d'un itérateur, j'ai trouvé dommage l'absence de remove d'un coté. Si j'avais vraiment confondu, alors j'aurais également parlé de la fonction next java qui, ici, correspond aux fonctions next()+current() en même temps.

Maintenant, pour en revenir à ce que j'ai dit tout au début. Ce qui me dérange, c'est de n'avoir aucun exemple d'utilisation de cette classe. Je ne critique pas l'auteur. Je respecte d'ailleurs la clartée de ce code ainsi que sa maitrise. Mais si il n'y a pas d'illustration (des fonctions), et si l'intéret de l'itération n'est pas mis en avant, alors je ne vois pas l'intéret de la source. Pire, je ne vois pas pourquoi cette source a été noté à 10...

Je ne te critique pas Neigedhiver. Sache que je respecte tout ce que tu as réalisé sur ce site. Mais cette source est incomplète. Elle démarre bien, c'est dommage. Attention, je me répète: je ne critique pas l'utilité de ta classe... C'est son absence d'illustration qui me gène (illustration d'itération):

Si tu écris "$si = new StringIterator('Bonjour');"
J'en conclus que $si est ton iterator. Donc utiliser un $letter est complètement inutile. Maintenant que tu possède la fonction valid, un simple: while($si->valid()) aurait fait ta boucle (tout en sachant que si tu ne "next" pas, ta boucle ne te servira à rien).

Voilou. Moi je suis convaincu que ton iterator peut être un outil puissant donc ce serait bête de laisser le code ainsi. Imagine un jeu du pendu où ta collection (de String ici) sont toutes les lettres du mot à deviner. Avec un remove en plus, tu te fais le jeu en 5 minutes (sans compter bien sur la création du dico) (tu vois, j'adhère déjà ;b)
neigedhiver Messages postés 2480 Date d'inscription jeudi 30 novembre 2006 Statut Membre Dernière intervention 14 janvier 2011 19
6 nov. 2007 à 14:03
@popGG : je ne me suis pas senti offensé par ton commentaire ;)

Pour ce qui est de l'exemple, je n'ai pas mieux à proposer, parce que je disais justement que je n'étais pas convaincu de l'utilité de cet itérateur...
La plupart des opérations surles chaînes peuvent être effectuées avec des fonctions déjà existantes...
La seule "application" pratique que j'ai trouvé ce matin sous la douche, c'est pour effectuer une transformation de type rot13. Là, on peut utiliser l'itérateur pour faire une transformation de type rot14, rot15, ou ce qu'on veut.

Alors à la limite, je mettrai cet exemple tout à l'heure, dans la source.

C'est juste que j'étais pas convaincu de l'utilité de la classe, que j'ai simplement écrite parce que ça me semble plus facile avec ça de visualiser le fonctionnement d'un itérateur...

Pour compléter ce que dis Malalam, effectivement, il ne s'agit là que d'un simple itérateur, qui ne sert, comme son nom l'indique, qu'à itérer. On peut tout à fait écrire une classe StringObject et lui coller tout un tas de méthodes de traitement du contenu. Ca permettrait de simuler en PHP5 la notion objet de tout type de variable comme en Java, et qui n'existe pas en PHP... (ce que je regrette parfois)

Voilà c'est tout ^^

Merci pour les commentaires en tout cas.
malalam Messages postés 10839 Date d'inscription lundi 24 février 2003 Statut Membre Dernière intervention 2 mars 2010 25
6 nov. 2007 à 13:19
@popGG => Iterator::valid(), Iterator::next() etc...sont définis par l'interface built-in de php : Iterator. Ces 4 méthodes sont les 4 méthodes que TOUT itérateur php DOIT implémenter.

Une classe stringIterator doit effectivement déjà implémenter ces 4 méthodes triviales.
Une classe spécialisée pour ujn traitement ou des ajouts de méthodes spécifiques devra hériter de cette classe-ci, voilà tout. Ici, nous avons la classe de base.

Quand tu dis "J'avoue que j'ai un peu exagéré sur l'importance du remove ce qui n'empêche qu'il s'agit d'un élément propre de l'itérateur.", tu confonds Java et PHP. Le code ci-dessous est parfaitement correct dans la mesure où il implémente bien l'interface Iterator. Rien n'empêche ensuite d'étendre cette classe de base. Mais le but de l'auteur n'était pas là...
En clair, cet itérateur-ci ne sert QUE à parcourir, justement. C'est un outil à étendre.
popGG Messages postés 23 Date d'inscription mardi 31 mai 2005 Statut Membre Dernière intervention 9 novembre 2007
6 nov. 2007 à 13:00
Désolé, je ne veux pas être offensif dans mes propos mais à quoi cela sert de créer une classe itérateur si c'est pour ensuite me faire un exemple qui aurait pu être plus rapide avec une simple array $tab[]...

Tu n'élustre rien de ce que tu viens de créer et je trouve cela dommage... Lorsque je te parle d'un exemple, je parle de montrer toutes les fonctionnalité de ta classe afin que l'on puisse juger sur la puissance qu'est un itérateur...

Montre nous au moins que valid (ton hasNext si j'ai bien compris) sert à quelque chose (pourquoi ne pas l'utiliser dans ta boucle par exemple)...

J'avoue que j'ai un peu exagéré sur l'importance du remove ce qui n'empêche qu'il s'agit d'un élément propre de l'itérateur.

Je sais que c'est hors sujet mais je te montre l'interface d'un itérateur en java. La méthode remove (restant optionnelle) fait tout de même partie d'un élément itérateur donc rien d'inutile et montre qu'un itérateur ne sert pas QUE à parcourir:
http://java.sun.com/j2se/1.4.2/docs/api/java/util/Iterator.html

Bon j'avoue, c'est PHP ici donc je laisse le bénéfice du doute, cependant je trouve ça dommage de ne pas tout avoir alors que tu nous parle d'itérateur.
neigedhiver Messages postés 2480 Date d'inscription jeudi 30 novembre 2006 Statut Membre Dernière intervention 14 janvier 2011 19
6 nov. 2007 à 11:18
Salut,

Merci Malalam.

@popGG : détrompe toi... La méthode hasNext() n'est pas utile, parce que c'est la méthode valid() qui fait ça. Elle est appelée juste après l'appel à next(). C'est donc elle qui dit s'il y a un suivant valide ou non.
Pour remove() je ne vois pas l'utilité. Un itérateur n'a pas pour but de manipuler les données, juste de parcourir le conteneur pour les lire.

Pour l'exemple, il est tellement trivial...

<?php
$si = new StringIterator('Bonjour');
foreach($si as $letter)
// Do something with this letter
}
?>

... que ça ne me semblait pas utile de le mettre... ^^
popGG Messages postés 23 Date d'inscription mardi 31 mai 2005 Statut Membre Dernière intervention 9 novembre 2007
6 nov. 2007 à 10:14
Hola,

un petit commentaire pour insister à fournir un exemple à chaque fois (vu la complication du code, cela t'aurait demandé 5 secondes). Je doute que tout le monde visitant ce site sache ce qu'est un itérateur et je trouve dommage que ce genre de source ne soit pas assez illustré surtout que l'itérateur est un élément puissant dans la programmation objet.

A part ça, moi je trouve que ta classe est trop simple. Un itérateur qui se respecte doit pouvoir avoir une méthode qui vérifie la présence d'une prochaine clé (hasNext -> renvoie true si oui) et une méthode qui supprime le prochain élément retourné par l'itérateur (remove). Un itérateur perd énormément de sa puissance sans ces deux fonctionnalités.

Hasta luego,
malalam Messages postés 10839 Date d'inscription lundi 24 février 2003 Statut Membre Dernière intervention 2 mars 2010 25
6 nov. 2007 à 07:58
hello,
"Depuis peu, je vois des itérateurs partout... J'ai vaguement cherché et je n'en ai pas trouvé qui touche les chaines de caractères..."
Il n'y en a pas. Il ne tient qu'aux développeurs de créer leurs itérateurs spécialisés avec les outils fournis par la SPL justement :-)

J'ai rien à dire, c'est parfait. Tu as même pensé à utiliser les exceptions spécifiques aux itérateurs.
Rejoignez-nous