On parle peu d'informatique en ces colonnes en ce moment, ainsi me suis-je dis qu'un bon troll du mardi serait peut être sympa.
Comme je ne savais pas de quoi vous parler, je vais vous faire partager ma haine pour ce qui me torture en tant qu'analyste programmeur vulgus de métier : les boucles.
Je pourrai parler d'inculture informatique dans l'industrie (comme un de mes chefs à qui j'ai appris ce qu'est une regexp ou une table de hashage, ou d'un autre qui m'a répondu lorsque je lui parlais de langage fonctionnel "fonctionnel ? qui fonctionne ?" quand je pense qu'ils sont chefs censés codé et effectivement programmeurs...), mais non parlons de boucles.
Au commencement, il y avait ça (merci Lurker) :
10 print i
20 i = i +1
30 if i< MAX then goto 10
Ensuite, comme vous le savez on a eu
for ( i = 0 ; i< MAX ; i++)
printf("%d\n",i);
ensuite on pourra avoir ça
(1..MAX).foreach {
int i;
print i;
}
Puis (là ça devient beau)
(1..MAX).map print
Je passe la programmation par contraintes.
Alors comme j'ai lancé ma dissertation de but en blanc, je parlerai de 2 sous problèmes.
Le premier est la sous formation. A l'image de l'anecdote que je rapportai plus haut pour pleurer en passant sur votre épaule (des fois c'est dur), on forme les informaticiens bac+2/bac+4, voire les ingénieurs à l'impératif, à java, etc...
Comme ce sont des gens pour lesquels la définition d'une fonction soit est flou, soit est une notion philosophique qui ne sert à rien (souvent les deux), ils vont avoir un peu de mal si on leur propose de coder en Lisp ou en Caml.
De plus, ce sont en général des GENS (selon la définition GCU : http://imil.net/wp/lexique/ ) qui ont pour caractéristique de se contenter de ce qu'ils ont et de ne pas rechigner à réécrire 100 fois la même chose, chaque jour.
Le mot généricité est un mot vaguement philosophique pour eux. Ils s'en approchent parfois, quand le client gueule parce que le projet a un mois de retard et reste effroyablement buggé.
Le second est lié aux langages. Ecrire un map, un fold ou un filter(1) en java, est une gageure, en on code beaucoup de chose en javouille.
J'ai trouvé ici ou là des tentatives, mais c'est syntaxiquement affreux. Je réessaierai un jour avec la réflexivité.
Une autre raison de la profusion de boucles-qui-ne-servent-à-rien est l'absence d'une sorte de SQL objet dans le langage (je parle pour les langages objets).
Kro$oft en a sorti un depuis quelques années, ça s'appelle LINQ, et je pense que ça va faire un carton.
Par exemple j'ai Objet1 contenant une liste de Objet2, contenant lui même une liste de Objet3, Objet3 possède un champ toto, une chaîne.
Je veux tous les objets de type Objet3 que Objet1 contient mais, seulement ceux sur lesquels la fonction Quelconque(String quoi), appliqué au champ Objet3.toto, renvoi true :
select Objet3 from Objet1 where Quelconque(Objet1.listeObjet2.listeObjet3.toto)
Bah non, je dois faire trois boucles.
Pareil, j'ai deux liste d'objets représentant la liste du personnel d'une boite à deux dates distrinctes. Je veux les comparer(une appli d'analyse d'évolution de la masse salariale par exemple), faut que je fasses des boucles... Et je vous dis pas comme c'est casse gueule de refaire une clause where avec un "not in" pour un dyscalculique comme moi...
Je pense qu'il nous faudrait un outil pour générer du code à partir d'une requête du genre. Je vous en reparlerai bientôt, car j'ai commencé à travailler sur la question.
Bref je crois que dans notre croisade contre les bugs, et avant qu'on arrive à faire des compilateurs sémantique (ie. des langages axiomatiques turing complet, en d'autres termes ou l'on se contente de décrire ce que l'on veut, comme en sql (voir un trip perso là dessus : http://wiki.loria.fr/wiki/Lisaac/M%C3%A9talangage ))
(1)http://www.zvon.org/other/haskell/Outputprelude/filter_f.htm(...)
Comme je ne savais pas de quoi vous parler, je vais vous faire partager ma haine pour ce qui me torture en tant qu'analyste programmeur vulgus de métier : les boucles.
Je pourrai parler d'inculture informatique dans l'industrie (comme un de mes chefs à qui j'ai appris ce qu'est une regexp ou une table de hashage, ou d'un autre qui m'a répondu lorsque je lui parlais de langage fonctionnel "fonctionnel ? qui fonctionne ?" quand je pense qu'ils sont chefs censés codé et effectivement programmeurs...), mais non parlons de boucles.
Au commencement, il y avait ça (merci Lurker) :
10 print i
20 i = i +1
30 if i< MAX then goto 10
Ensuite, comme vous le savez on a eu
for ( i = 0 ; i< MAX ; i++)
printf("%d\n",i);
ensuite on pourra avoir ça
(1..MAX).foreach {
int i;
print i;
}
Puis (là ça devient beau)
(1..MAX).map print
Je passe la programmation par contraintes.
Alors comme j'ai lancé ma dissertation de but en blanc, je parlerai de 2 sous problèmes.
Le premier est la sous formation. A l'image de l'anecdote que je rapportai plus haut pour pleurer en passant sur votre épaule (des fois c'est dur), on forme les informaticiens bac+2/bac+4, voire les ingénieurs à l'impératif, à java, etc...
Comme ce sont des gens pour lesquels la définition d'une fonction soit est flou, soit est une notion philosophique qui ne sert à rien (souvent les deux), ils vont avoir un peu de mal si on leur propose de coder en Lisp ou en Caml.
De plus, ce sont en général des GENS (selon la définition GCU : http://imil.net/wp/lexique/ ) qui ont pour caractéristique de se contenter de ce qu'ils ont et de ne pas rechigner à réécrire 100 fois la même chose, chaque jour.
Le mot généricité est un mot vaguement philosophique pour eux. Ils s'en approchent parfois, quand le client gueule parce que le projet a un mois de retard et reste effroyablement buggé.
Le second est lié aux langages. Ecrire un map, un fold ou un filter(1) en java, est une gageure, en on code beaucoup de chose en javouille.
J'ai trouvé ici ou là des tentatives, mais c'est syntaxiquement affreux. Je réessaierai un jour avec la réflexivité.
Une autre raison de la profusion de boucles-qui-ne-servent-à-rien est l'absence d'une sorte de SQL objet dans le langage (je parle pour les langages objets).
Kro$oft en a sorti un depuis quelques années, ça s'appelle LINQ, et je pense que ça va faire un carton.
Par exemple j'ai Objet1 contenant une liste de Objet2, contenant lui même une liste de Objet3, Objet3 possède un champ toto, une chaîne.
Je veux tous les objets de type Objet3 que Objet1 contient mais, seulement ceux sur lesquels la fonction Quelconque(String quoi), appliqué au champ Objet3.toto, renvoi true :
select Objet3 from Objet1 where Quelconque(Objet1.listeObjet2.listeObjet3.toto)
Bah non, je dois faire trois boucles.
Pareil, j'ai deux liste d'objets représentant la liste du personnel d'une boite à deux dates distrinctes. Je veux les comparer(une appli d'analyse d'évolution de la masse salariale par exemple), faut que je fasses des boucles... Et je vous dis pas comme c'est casse gueule de refaire une clause where avec un "not in" pour un dyscalculique comme moi...
Je pense qu'il nous faudrait un outil pour générer du code à partir d'une requête du genre. Je vous en reparlerai bientôt, car j'ai commencé à travailler sur la question.
Bref je crois que dans notre croisade contre les bugs, et avant qu'on arrive à faire des compilateurs sémantique (ie. des langages axiomatiques turing complet, en d'autres termes ou l'on se contente de décrire ce que l'on veut, comme en sql (voir un trip perso là dessus : http://wiki.loria.fr/wiki/Lisaac/M%C3%A9talangage ))
(1)http://www.zvon.org/other/haskell/Outputprelude/filter_f.htm(...)
> Lire le journal (84 commentaires, moyenne: 2,4).
Vous avez demandé le commentaire #823202.



Ruby
Pour les print, il y a les versions ruby qui s'en rapprochent un peu quand même (et en étant très lisible - mais non, je parle pas de python ;) )
5.upto(10) { |i| print i, " " }
-> 5 6 7 8 9 10
[^]Re: Ruby
j'oublais : question lisibilité et compréhension je trouve 1.upto(MAX) largement plus lisible qu'un (1..MAX)
La première version est lisible telle quelle, la deuxième demande d'interpréter le '..'
[^]Re: Ruby
Le "upto" nécessite de connaitre l'anglais, le "..." est compréhensible par n'importe qui ayant fait un tout petit peu de math.
Sinon, quelques manières de le dire en Perl.
print join ' ', 5...10
map { print "$_ "} 5...10
print "$_ " for 5...10
Free Softwares Users Group Arlon (Sud Luxembourg, Belgique)
pertinent, e adj. Approprié ; qui se rapporte exactement à ce dont il est question.
[^]Re: Ruby
oué enfin pour écrire print, join ou n'importe quel code il faut connaître l'anglais (un minimum)
et ça reste à mon sens verbeux mais concis
(mais je me doutais bien qu'on pouvais faire 'mieux' en perl (j'adore perl et ruby... ;) )
[^]Re: Ruby
Pour ajouter de l'eau au moulin: en Python, on dirait
print " ".join(( str(x) for x in xrange(5,11) ))
Ou plus efficacement:
print " ".join(map(str, xrange(5,11)))
[^]Re: Ruby
Il existe des langages qui n'ont pas de mots clés ou fonctions de base en anglais (les langages de macro de Microsoft Office et OpenOffice sont localisés par exemple) ou même des langages sans mots clés/fonctions faisant partie d'un « langage humain » (bf, APL apparement,...). C'est justement le genre de langage qui est généralement considéré comme « illisible ».Il me semble que, quel que soit le langage, il faut de toute façon apprendre un minimum de syntaxe avant de pouvoir coder ou comprendre quoi que ce soit. Il n'y a pas de langage vraiment « intuitif » et essayer d'en créér un est vain (« Build a system that even a fool can use and only a fool will want to use it. »).
Free Softwares Users Group Arlon (Sud Luxembourg, Belgique)
pertinent, e adj. Approprié ; qui se rapporte exactement à ce dont il est question.
[^]Re: Ruby
les ranges existent aussi en Ruby si on y tient vraiment
(5..10).each { |i| print "#{i} " }
(5..10).to_a.join(' ')
il y a juste le fait que Ruby fait la distinction entre un range et un tableau, d'où le .to_a pour transformer en tableau et pouvoir utiliser .join()
mais là aussi, rien n'empêche de définir la méthode .join() qui s'appliquerait directement à un range
class Range
def join(s)
self.to_a.join(s)
end
end
on peut alors utiliser ceci sans problème :
(5..10).join(' ')
Free Softwares Users Group Arlon
[^]Re: Ruby
C'est quoi l'intérêt ?Free Softwares Users Group Arlon (Sud Luxembourg, Belgique)
pertinent, e adj. Approprié ; qui se rapporte exactement à ce dont il est question.
[^]Re: Ruby
Comme en python je suppose: quelle est la différence entre:
for i in range(2000000000): print i
et
for i in xrange(2000000000): print i
La première version va essayer de te créer un tableau de 2000000000 entiers, puis de le parcourir. À mon avis, ça a peu de chances de fonctionner de manière optimale :)
Si tu n'es pas convaincu, essaye ces deux versions dans une console python :p
[^]Re: Ruby
Oui et donc ma question c'est « quel est l'intérêt de range par rapport à xrange » ?
Free Softwares Users Group Arlon (Sud Luxembourg, Belgique)
pertinent, e adj. Approprié ; qui se rapporte exactement à ce dont il est question.
[^]Re: Ruby
Je viens de le dire: la première version va te bourrer la mémoire et mettre à genou ton CPU, parce qu'elle va créer un tableau de 20000000 entiers pour ensuite le parcourir
La deuxième version va simplement créer un itérateur, qui ne mémorise que l'état courant et qui ne sait rien faire d'autre qu'aller à l'état suivant. C'est plus économique en mémoire et en temps CPU.
En gros:
>>> x = range(5)
>>> print x
[1, 2, 3, 4]
>>> x = xrange(5)
>>> print x
xrange(5)
>>> print x.next()
0
>>> print x.next()
1
>>> print x.next()
2
...
Remplace 5 par 2000000. Tu vois tout de suite que ton range va sacrément bourrer à la fois ta mémoire et ton CPU, tandis que le xrange ne coutera rien en plus.
C'est quelque chose de bien plus général qu'un simple intervalle. S'il est évident qu'un programmeur d'écrira JAMAIS range(2000000), on peut par contre voir par exemple:
data = [line.split(',') for line in open('data.csv').read().splitlines()]
qui fonctionnera pour des tests basiques, mais qui est plutôt inefficace:
- ton fichier est entièrement gardé en mémoire (read())
- il est gardé une deuxième fois en mémoire (chaque ligne comme un élément d'un tableau: splitlines())
- enfin, il est gardé une troisième fois en mémoire (chque ligne séparée en champ)
Tu auras aussi du utiliser 3 fois le contenu de ton fichier pour simplement afficher tous les premiers champs par exemple:
- d'abord en lisant entièrement le fichier (le read())
- ensuite en itérant sur les données pour les traiter ligne par ligne (le splitline)
- ensuite en itérant sur data
Avec un itérateur:
data = (line.split(',') for line in open('data.cvs').xreadlines())
ton fichier n'est lu qu'une fois en mémoire, les données ne dont itérées que si nécessaire: cout mémoire virtuellement nul et efficacité optimale. Si ton fichier fait 300 Mo et que tu ne veux que les trois premiers enregistrements, la première version nacéssitera de parse et de garder en mémoire les 300 Mo. La deuxième ne prendra pas plus de mémoire que si ton fichier faisait 5 Go ou 5 octets, et ne prendra que le temps nécessaire à lire les trois premiers enregistrements
La différence, c'est que le premier est un tableau. Le deuxième est un itérateur (plus précisement, un générateur). C'est la même différence qu'entre un range et un tableau. Vois tu l'intérêt de les différencier, maintenant ? :p
[^]Re: Ruby
J'oubliais: les tableaux aussi ont leur utilité (parce que si les itérateurs étaient si merveilleux, on utiliserait plus que ça ;)): avec un tableau, on accède très rapidement à un élément quelconque. range(5000)[4999] te répondra immédiatement, xrange(5000)[4999] nécessite de calculer les 4999 éléments précédents. Tu vas me dire, range aussi, pour construire la tableau. Bien entendu, mais si juste après tu as besoin du 4998 ème élément, ce sera quasi-instantanné pour range. Pour xrange, il devra à nouveau recalculer tous les éléme,nts précédents
(bon, ça, c'est la théorie, en pratique, xrange peut te calculer immédiatement un élément quelconque, mais c'est une optimisation spécifique à xrange)
De plus, avec un tableau, un résultat est calculé une fois pour toutes. Si tu fais 10 itérations sur une séquence, un tableau te calcule 1 fois le résultat puis le met en mémoire. Un itérateur te calculera 10 fois chaque résultat.
[^]Re: Ruby
C'est peut être pourquoi les langages où il n'existe pas de tableau sont parfois considérés comme merveilleux :)C'est un travail pour une table de hachage ça (ou même un arbre, qui peut être implémenté par des listes).
Et pourquoi le langage ne pourrait-il pas mémoizer (sic) les résultats tout seul ?
Free Softwares Users Group Arlon (Sud Luxembourg, Belgique)
pertinent, e adj. Approprié ; qui se rapporte exactement à ce dont il est question.
[^]Re: Ruby
> C'est un travail pour une table de hachage ça (ou même un arbre, qui peut être implémenté par des listes).
Pas forcément. Si tes éléments sont indexés par les premiers entiers (comme un tableau, quoi), il peut être intéressant de tout classer séquentiellement en mémoire (ensuite, tab[i], est équivalent à une simple addition de pointeurs, ce qui est plus intéressant qu'une fonction de hachage, tu en conviendras)
oui, je sais, ça convient pas dans tous les cas Pas la peine de me refaire un cours d'algo, là c'est itérateur vs tableau, pas liste vs table de hachage (tableau != liste, de toute manière, et toc ! ;)).
> Et pourquoi le langage ne pourrait-il pas mémoizer (sic) les résultats tout seul ?
Comment le langage pourrait il savoir ce qui est pertinent de mémoriser ou pas ? (oui, on pourrait s'inspirer des algos de gestion de la mémoire des OS, mais franchement, si tu veux recoder les caractéristiques de ton OS dans le langage, fais du Java ;))
[^]Re: Ruby
Précisement. La seule utilisation légitime des tableaux que tu m'as citée peut être remplacée par l'utilisation de tables de hachage qui sont de toute façon une structure de données qui doit être disponible dans tout langage qui se respecte.Il serait sans doute utile que tu revois ton cours d'algo quand même parce que dans une table de hachage, les éléments sont bien contigüs aussi en mémoire (à moins d'utiliser un chaînage externe pour la résolution de collisions mais c'est de toute façon pas une bonne idée).
Dans des langages tels que Python, Ruby ou Perl, tab[i] implique plus qu'une addition de pointeurs. Évidemment le temps d'accès à un élément dans un tableau restera généralement marginalement plus efficace que dans une table de hashage (pas la peine de me refaire un cours d'algo non plus :) mais si on peut éviter d'avoir deux concepts très similaires/redondants mais distincts, ça peut être intéressant d'en éliminer un des deux si ça ne pose pas de problème à l'utilisation (ce qui est le cas si le langage a été un minimum pensé pour).
Je vois pas comment tu peux implémenter la mémoization au niveau de l'OS mais c'est relativement simple à mettre en place au niveau du runtime d'un langage pas trop mal foutu (même gcc peut le faire pour du C si j'en crois certains attributs de fonctions non standards).
http://en.wikipedia.org/wiki/Memoization#Automatic_memoizati(...)
Free Softwares Users Group Arlon (Sud Luxembourg, Belgique)
pertinent, e adj. Approprié ; qui se rapporte exactement à ce dont il est question.
[^]Re: Ruby
> Il serait sans doute utile que tu revois ton cours d'algo quand même parce que dans une table de hachage, les éléments sont bien contigüs aussi en mémoire
Au temps pour moi, je cours me cacher tout de suite, j'arrête pas de sortir des conneries énormes en ce moment..
C'est à cause de la chaleur, ça empèche mon cerveau de travailler de manière optimale
Pour ce qui est du troll tableau/table de hachage:
en ruby, je sais pas (même si ça fait 3 mois que je dit que j'allais m'y mettre, avec le Lisp et l'Objective-C ;)), mais en Python tu as effectivement des tables de hachage dans le langage, et c'est "à peu près" de même utilisation (s'entend: c'est pas la même classe, mais à l'utilisation c'est vaguement la même chose: la notation foo[key])
Il faut voir aussi qu'en python qu'avec un tableau tu as un ordre garanti, tandis qu'avec la table de hachage, puisque la fonction de hachage est un machin interne succeptible de changer, tu peux pas garanit que les clefs seront ordonnées comme tu le penses. Les tableaux sont donc fortement utilisés également pour des trucs genre piles et files, et pas seulement parce que c'est "un peu plus" rapide.
> Je vois pas comment tu peux implémenter la mémoization au niveau de l'OS mais c'est relativement simple à mettre en place au niveau du runtime d'un langage pas trop mal foutu (même gcc peut le faire pour du C si j'en crois certains attributs de fonctions non standards).
Commence pas à tout confondre hein :)
J'ai pas réussi à trouver les attributs dont tu parles, mais de ce que j'ai compris de l'article de Wikipedia, c'est simplement du sucre syntaxique pour quelque chose que tout le monde a déjà fait (exemple avec la STL, j'ai la flemme de faire le tableau en C):
typedef std::map<int,int> fmap;
using std::make_pair;
int factorielle(int n) {
int f; static fmap res;
if(res.find(n) != res.end()) return res[n];
if(n == 0 || n == 1) return 1;
f = n * factorielle(n-1);
res.insert(make_pair(n, f));
return f;
}
C'est donc bien le programmeur qui décide quand il faut mémoriser, pas le langage qui devine tout seul
[^]Re: Ruby
Le langage lua ne dispose que d'une seule structure de donnée, la table. La table est optimisée pour des accès type tableau (indices entiers se suivant en mémoire) mais peut aussi s'utiliser avec des clefs de n'importe quel type.
par exemple :
t[1000000]=true
ne va te créer qu'une seule paire clef/valeur alors que :
t = {true, false, true, false}
va utiliser des accès de type tableau pour ces valeurs.
La Roue du Temps
[^]Re: Ruby
xrange(5)
>>> print x.next()
Traceback (most recent call last):
File "", line 1, in ?
AttributeError: 'xrange' object has no attribute 'next'
xrange(5000)[4999] nécessite de calculer les 4999 éléments précédents.
Ha bon pourtant xrange(y)[x]=x, ou j'ai pas suivit quelque chose...
Je n'y connais rien en python, mais le xrange a l'air d'etre un simple intervale alors que le xrange que tu decrit serait plutot une liste chainée...
D'ailleurs il semble que on ne peut rien affecter dans un xrange :
x[2]=4
Traceback (most recent call last):
File "", line 1, in ?
TypeError: object does not support item assignment
[^]Re: Ruby
> Ha bon pourtant xrange(y)[x]=x, ou j'ai pas suivit quelque chose...
cf:
> (bon, ça, c'est la théorie, en pratique, xrange peut te calculer immédiatement un élément quelconque, mais c'est une optimisation spécifique à xrange)
Bon, d'accord, pour le reste, je me suis royalement embrouillé, j'admets: j'ai joyeusement mélangé xrange et son itérateur...
Il fallait donc lire:
>>> x = iter(xrange(5))
>>> print x
<rangeiterator object at 0xb7c213e0> # C'est mieux, effectivement ;)
>>> x.next()
0
>>> x.next()
1
>>> for i in x:
... print i
2
3
4
>>>
> le xrange que tu decrit serait plutot une liste chainée...
Alors là pas du tout:
- xrange n'est qu'une fonction qui génère des nombres et qui peut fournir un itérateur
- le xrange que je décrivait était un itérateur, qui n'a rien à voir avec une liste chainée.
En gros: une liste chainée, c'est grosso modo comme un tableau: tu la construits, puis tu l'utilises
L'objectif de l'itérateur est de construire les éléments "à la demande" et de ne rien garder en mémoire (histoire de ménager la mémoire, justement). L'intérêt par rapport à la liste chainée est de ne pas avoir à construire des éléments dont on a pas besoin et de garder une empreinte mémoire faible.
Pour être imagé, tu peux voir une liste chainée comme une matrice ligne à N éléments, et un itérateur comme une suite récurrente. D'ailleurs, voilà ce que je peux faire avec les itérateurs, qui est impossible avec les tableaux:
class naturels:
def __init__(self): self._i = 0
def __iter__(self): return self
def next(self): i = self._i ; self._i += 1 ; return i
for i in naturels():
if est_premier(i): print i
En gros, je viens de faire une sorte de range(0, infinity). Tu remarqueras que l'appel construction de naturels() ne prend ni un temps infini ni un espace mémoire infini.
Avec un tableau (ou une liste chainée), tu aurais été obligé de construire un tableau contenant tous les naturels (ça t'aurait pris un temps infini, mais bien heureusement, ta mémoire sera saturée bien avant) avant de pouvoir itérer dessus.
Tiens, un exemple amusant qui me vient à l'esprit: c'est équivalent à:
class premiers(naturels):
def next(self):
i = naturels.next(self)
if est_premier(i): return i
else: return self.next()
for i in premiers():
print i
> D'ailleurs il semble que on ne peut rien affecter dans un xrange :
Avec une liste chainée, tu pourrais...
[^]Re: Ruby
Surtout l'itérateur fait avant tout référence au design pattern du même et peut être mis en oeuvre dans n'importe quel langage
http://en.wikipedia.org/wiki/Iterator_pattern
La différence c'est que certains langages l'ont repris dans leur syntaxe
http://en.wikipedia.org/wiki/Iterator
[^]Re: Ruby
> Sinon, quelques manières de le dire en Perl.
> print join ' ', 5...10
> map { print "$_ "} 5...10
> print "$_ " for 5...10
pour les 2 derniers exemple les "$_" sont inutiles (implicites)
map {print} 5...10
print for 5...10
et on peut même encore faire plus court (et finalement plus lisible):
print 5..10
[^]Re: Ruby
>print for 5...10
>et on peut même encore faire plus court (et finalement plus lisible):
>print 5..10
Tu veux dire, même le for est implicite ?
À ce train là, en Perl, mêne un programme vide fera quelque chose...
--->[]
[^]Re: Ruby
Non, il y a un espace après le $_.Free Softwares Users Group Arlon (Sud Luxembourg, Belgique)
pertinent, e adj. Approprié ; qui se rapporte exactement à ce dont il est question.
[^]Re: Ruby
Hum, pour moi une syntaxe ou tu appelle un membre d'un nombre pour faire un truc c'est vraiment mal....
(1..MAX).foreach action;
Est pas si mal en revanche le reste est vraiment bizarre et pas tellement intuitif...
Ne pas oublier un truc pour vos règle de nommage :
ObjectAction
Dans ton 5.upto(10)....
C'est Objet.Action.Objet
Mais bon, je suis sans doute pas objectif vu que je viens surtout du monde :
C/perl/c++/php/bash/sql
site perso : http://rapsys.free.fr/
[^]Re: Ruby
C'est vrai que c'est un peu déséquilibré parce que dans la plupart des langages objets, le concept objet "message" est directement rendu par l'invocation de la méthode de l'objet auquel il s'adresse (On appelle directement la méthode alors qu'en théorie un message est envoyé à un objet qui déclenche la méthode appropriée en reponse ... ou non)
http://en.wikipedia.org/wiki/Message_passing#OOP
http://en.wikipedia.org/wiki/Method_%28computer_science%29
On devrait donc avoir
Objet1 Objet2
genre 5 10
Je suis étonné qu'aucun afficionados de Smalltalk/Squeak ne l'ait encore relevé.
http://en.wikipedia.org/wiki/Smalltalk#Messages
Mais bon une fois qu'on a compris le système on y fait plus attention
[^]Re: Ruby
Pourquoi ?
J'y vois simplement le concept d'objet poussé un peu plus loin que dans les langages "objets" mais non complètement objets classiques (j'ai rien contre c++ hein, je l'utilise tous les jours, mais ça pue quand même ;) )
De la même manière, une chaine est aussi un objet
on doit pouvoire faire un :
En ruby tout est objet, est c'est ce qui fait qu'il est vraiment sympa je trouve.
mais c'est sur qu'entre un :
et :
il y a une sacré différence. Un for est quelque chose que je trouve souvent horrible car il n'est relié à rien (je sais pas trop comment ça s'appel, c'est juste un mot clé qui est tout seul dans son coin). Alors que le each, le upto sont lié directement à l'objet qu'on manipule et c'est vraiment plus logique je trouve
D'ailleurs, j'aurais plutôt du comparer montab.each a une syntaxe du type :
On voit bien que dans ce cas foreach arrive de nul part alors que le each est réellement une méthode de mon tableau (je ne compare pas les syntaxe mais vraiment la construction logique du langage)
(oui, tout ça pour dire que je trouve ça logique et que j'aime beaucoup Ruby. D'ailleurs si certains connaissent des langages objets au même point que Ruby ça m'intéresse ;-) )
[^]Re: Ruby
Lisaac*. Tout y est objet, comme en ruby, même le booléen.
En lisaac, le for est un message de INTEGER
1.to 10 do { i.print;};
Il prend en paramètre un BLOCK, c à d, une liste d'instruction, auquel il donne la valeur de i en argument.
De la même manière, grâce au type block, tu peux faire des map/fold/filter à pas cher.
Dans COLLECTION :
- map blc : BLOCK : SELF<- (
+ result : SELF := SELF.create 0;
lower.to upper do { i : INTEGER;
result.add (blc.value item i);
};
result
);
donc ça donnerai
montab.map { elt : TABLO;
elt.print;
};
Oui faut déclarer un elt, donc c'est plus un foreach en fait.
Mais tu as ça à la vitesse du C**
Je me suis amusé à faire joujou avec les listes à la caml, du genre
let rec toto = function
[] -> 0 |
e::[] -> e |
t::q -> 10+t+toto q;;
Les fonctions dans COLLECTION :
- when_empty blc : BLOCK <- (
blc.value;
);
- when_alone blc : BLOCK <- (
(count = 1).if {
blc.value first;
};
);
when_list blc : BLOCK <- (
(count > 1).if {
blc.value first,(slice (lower+1) to upper);
};
);
Ca permettra de faire :
+ lst : LIST[INTEGER_32].create 5;
+ res : INTEGER_32;
lst.add 1;
lst.add 2;
lst.add 3;
lst.add 4;
lst.add 5;
lst.when_empty {res := 1;};
.when_alone {
x : INTEGER_32;
res := x;
};
.when_list {
x : INTEGER_32;
y : LIST[INTEGER_32]
res := 10+x+y.map {x,y : INTEGER_32; x+y};
};
* Oui je sais, je l'avais pas encore faite ;-)
** http://isaacos.loria.fr/li_benchs.html
[^]Re: Ruby
Il faudra finir de traduire la page de bench en anglais :
les ko et Mo devraient être kB et MB, le "en -" être "less" et les petites notes (1), (2) et (3) sont intégralement en français. Ou alors ce sont des restes du premier avril et vous avez fait le même poisson d'avril que gmp (arithmetic without SANS limitations).
[^]Re: Ruby
Oui c'est clair que c'est à la limite du honteux, tu n'es pas le premier à me faire la réflexion.
Modifier ce site hébergé au loria est une horreur (2 ssh coup sur coup, edition avec un vi sur SunOS 5.7 qui déconne, etc...) Donc j'ai la grosse flemme. Normalement il va migrer bientôt, on en profitera pour le nettoyer.
Je retiens ta correction à l'encre rouge ! ;)
[^]Re: Ruby
<privé>
Pourquoi 2 ssh imbriqués ? Le site est dans /local/isaacos/htdocs/ sur loria1 (ou 2) qui possède un magnifique vim6 et est une formidable mandrake (moui, j'exagère sur les adjectifs). Et puis il y a moyen de faire du ssh dans ton vim local de toute façon, donc...
</privé>
[^]Re: Ruby
<privé>
Non, il est plus accessible de loria1 :(
Il faut faire un ftp sur bar
Peut être de 2, j'essaierai et si ça marche grand merci, car ras le bol des allers/retour en ftp
</privé>
[^]Re: Ruby
Et ya moyen d'avoir ça avec une syntaxe potable ? (désolé, ignorez ça, c'est un réflexe, un instinct de survie qui me pousse à réagir violemment à la simple vue de := )
Plus sérieusement, Lisaac, j'aime bien le concept, mais la syntaxe me fait fuir. C'est volontaire ou ça vient de moi ? (du genre INTEGER_32, tout en majuscule, je trouve ça moche - et pas pratique à taper surtout. L'opérateur d'affection de deux lettres, je trouve ça chiant au possible aussi).
Questions vraiment sérieuses (promis cette fois):
- LIST[INTEGER_32]: le [ ], il est défini comment (et où, surtout): dans le langage, comme en C++ avec un operator[] ou en python __getitem__ ?
- pour le .when_alone { foo }, comment on sait que ça s'applique sur lst ? C'est du sucre syntaxique du langage ou un truc astucieux de COLLECTION (du genre when_empty renvoie la liste donc le truc équivaut vaguement à lst.when_empty(bloc_1).when_alone(bloc_2))
[^]Re: Ruby
Je trouve aussi personnellement que que Lissac a une syntaxe particulierment rebutante. Mais, comme le souligne Moonz qui dit que "j'aime bien le concept, mais la syntaxe me fait fuir", il est important de ne pas s'arreter a la seule syntaxe mais de bien comprendre ce que le langage peut amener de nouveau ou d'interessant.
En fait cela m'a rappelé une reflexion qu'a eu Wadler lorsqu'il a travaillé à poser les bases de haskell.
------------------
My experience on the Haskell committee caused me to formulate 'Wadler's Law': time spent in debating a feature doubles as one moves down the following list:
* Semantics
* Syntax
* Lexical syntax
* Lexical syntax of comments
------------------
Je trouve cette reflexion particulierement interessante. Je trouve d'ailleur qu'il est plus souvent question dans ce fil de discussion de syntaxe que reflexion sur la difference semantique des langages et le rapport de cette semantique avec le besion de faire des boucles.
Ensuite, c'est ma vie ;-), mais j'aime bien la syntaxe d'haskell ;-) , même si c'est ce qu'il y a derriere que je trouve d'encore plus interessant (transparence referencielle, concept des monads, evaluation paresseuse, etc...).
Je voulais enfin demander à Ontologia ce qu'il pense de la syntaxe de Lissac en dehors de toute autre consideration sur le langage. Je suis curieux et ouvert à son avis car je me demande ce qui peut plaire aux personnes dans cette syntaxe.
PS : Pour en revenir sur le sujet de ce journal, il est interessant de voir que haskell ne presente tout simplement pas de probleme de boucle tels que presentés dans ce journal (je precise que j'entend ici boucle de controle au sens imperatif) car le langage n'en permet pas
(meme si il est possible de construire certaine fonction qui denote le fonctionnement de telle boucle, via les monades, mais bon).
[^]Re: Ruby
La Wadler's Law m'a fait hurler de rire, c'est particulièrement bien vu ! ;-))
Qu'est-ce qui me plait dans la syntaxe de Lisaac ?
Déjà mon propre historique a pu influer :
Basic à 7 ans
Pascal à 15 ans
C (mais pas longtemps) à 18 ans
A suivi une période où programmer m'emmerdait plus qu'autre chose, principalement à cause des boucles, j'ai plutôt passé du temps à découvrir Linux, bref...
J'ai été très marqué par Pascal, qui m'a beaucoup marqué, c'est pour cela que j'aime le ':='
Je déteste le concept du = et ==
Un égale '=' mathématiquement, c'est une reflexion binaire réflexive, symétrique, transitive, antisymétrique. Point barre.
Un égale est donc une opération
'a * 'a -> bool
Ca doit donc servir aux tests et à rien d'autres.
Le reste c'est de la bidouille.
Pour les majuscules, je m'y suis fait, c'est une décision ferme de Benoit, qui y est très attaché, et l'impression que le langage nous gueule dessus choque des gens habitué à communiquer en chat, ce qui n'est pas du tout dans sa culture, d'où le fait que ça ne lui ait jamais effleuré l'esprit.
Par contre j'adore la syntaxe à mots clés, je trouve ça géniale
une_matrice.mult_by_matrix_and_by_scalar(autre_matrice, un_reel);
Bof
une_matrice.mult_by_matrix autre_matrice and_by_scalar un_reel;
C'est plus clair déjà, mais mon exemple est très mauvais.
A l'utilisation, et pour faire du java, du caml, du perl et parfois du C++ (arrrrrrg, je hais ce langage), bah à relire, ya pas photo, c'est de très loin le plus clair et immédiatement compréhensible.
En plus la grammaire de Lisaac est minuscule (20 règles), et elle se maîtrise en 1h.
Enfin le langage est très puissant, le type Block permet de faire des choses halucinantes, et dans la version quiva sortir, que je teste déjà, il y a ma feature que je réclamai : la possibilité qu'une fonction rende plusieurs valeurs, comme dans les langages fonctionnels.
Je ne parle même pas des perfs.
Un langage qui peu se targuer d'être un sur-ensemble de SmallTalk (moins la réflexivité, pour le moment) avec la vitesse du C, c'est quand même génial.
[^]Re: Ruby
C'est rigolo, mais je te trouve plutot radicale et vehement dans tes avis.
Ne le prend pas mal hein, c'est juste la maniere dont tu defend certains avis :
------------
Ca doit donc servir aux tests et à rien d'autres.
Le reste c'est de la bidouille.
------------
Je déteste le concept du = et ==
------------
Or je parlais du fait que justement
------------
Je trouve aussi personnellement que que Lissac a une syntaxe particulierment rebutante.
------------
mais que j'etais ouvert aux argument de personne qui la trouve bien, et c'est d'ailleur pourquoi je te demandais ton avis (je me permet de te tutoyer aussi)
C'est pour quoi je te trouve dur et radical envers des gens qui partent justement du fait qu'il 'deteste' la syntaxe de Lissac.
Mais bon, ceci n'est que digression et j'entend bien tes arguments :-)
Cependant, quelque petites choses :
----------
J'ai été très marqué par Pascal, qui m'a beaucoup marqué, c'est pour cela que j'aime le ':='
----------
vi, tout a fait d'accord, c'est important dans un langages imperatif d'avoir fait cette distinction avec le '=' de la logique ou des maths (je me demande en fait si il s'agit bien du meme ? je n'arrive pas encore a me decider)
-----------
Je déteste le concept du = et ==
Un égale '=' mathématiquement, c'est une reflexion binaire réflexive, symétrique, transitive, antisymétrique. Point barre.
Un égale est donc une opération
'a * 'a -> bool
Ca doit donc servir aux tests et à rien d'autres.
-------
justement c'est la que je decroche, si justement on considere que '=' c'est mathematique (c'est une reflexion binaire réflexive, symétrique, transitive, antisymétrique. ) e.g. f (x) = x * x, je ne vois pas necessairement pourquoi ca ne servirait qu'au test et rien d'autre ???
prend le cas du lambda calcul. si tu dit que
f (x) = x + x (x etant un reel par exemple)
ce n'ai pas pour faire quelque test que ce soit, mais juste pour definir la fonction f (de type R -> R ).
mais c'est la meme chose si tu dis
ma_variable = 42
si on considere que ma_variable est un variable mathematique , non ?
ainsi
f(ma_varaible)
sera juste reduite en
ma_variable * ma_variable
il n'y a donc ni affectation (pour laquel l'operateur ':=' qui a ete crée pour ca est bien plus parlant ), ni test.
et d'aileur en fonctionnel on peut aussi avoir besion du ==
is_zero n = n == 0
ensuite le (truc avec trois barre qu'on utilise en marth et que je ne sais pas ecrire ici :-) ) serait peut etre plus judicieux mais pas utilisable en ascii donc je le trouve tres bien ce == pour un test d'egalité.
d'ou ma reponse : je n'ai rien contre = et == bien au contraire.
----------------------
Pour les majuscules, je m'y suis fait, c'est une décision ferme de Benoit, qui y est très attaché, et l'impression que le langage nous gueule dessus choque des gens habitué à communiquer en chat, ce qui n'est pas du tout dans sa culture, d'où le fait que ça ne lui ait jamais effleuré l'esprit.
---------------------
Je pense aussi pour ma part qu'il est important qu'un langage contraigne le codeur, et meme si peut penser que cela le limite, c'est plus souvent pour son bien (et surtout le bien de l'ensemble de gens qui code dans ce langage et qui donc ont un besoin imperieux de partager certaines convention critique de lecture/ecriture du code)
--------------------
la possibilité qu'une fonction rende plusieurs valeurs, comme dans les langages fonctionnels.
-------------------
Heu, je serais plutot en desaccord, ou je ne connais pas de langage retournant plusieur valeur. Peux tu m'eclairer la dessus car en reflechissant a quoi cela pourrait ressembler, je ne m'en fait pas du tout une idée possitive.
voila, au plaisir
[^]Re: Ruby
Oui mais justement, en maths "f(x) = x + x" c'est pas une déclaration de fonction, c'est pas grand chose. Pour déclarer une fonction on fait ça proprement (Soit f : x -> x + x) ou avec une équation (Soit f telle que pour tout x, f(x) = x + x), mais on balance jamais "f(x) = x + x", c'est pas rigoureux.
Il parle sans doute des tuples (let proches x = (x + 1, x - 1)) qui permettent de renvoyer des aggrégats d'objets de types potentiellement distincts, et alors ce n'est pas vraiment "plusieurs valeurs en même temps", c'est juste une valeur qui en contient plusieurs autres, et qui est légère (syntaxiquement) à manipuler (pas comme un struct ou un tableau ou...).
[^]Re: Ruby
---------
Oui mais justement, en maths "f(x) = x + x" c'est pas une déclaration de fonction, c'est pas grand chose. Pour déclarer une fonction on fait ça proprement (Soit f : x -> x + x) ou avec une équation (Soit f telle que pour tout x, f(x) = x + x), mais on balance jamais "f(x) = x + x", c'est pas rigoureux.
---------
Oui effectivement le terme definir n'etait peut etre pas le plus adapté (j'ai penser à denoter ce qui me paraissait meilleur mais 1) n'etant pas plsu sur 2 ) toruvant cela un peu pompeux , je gardais definir).
Cependant, j'ai ecris
f x = x + x
car, je reprenais l'exemple de ce qui se fait en haskell.
pour parler de ce que je connais en haskell, et cela semble propre selon ce que tu dis, on aurait pu ecrire :
f :: a -> a
f x = x + x (pareil que f (x) = x + x)
(c'est presque ce que j'ecrivais a l'ecole me semble t'il)
ou meme
f :: forall a. a -> a
f x = x + x
mais dans les faits je trouve bien aussi qu'un langage INFORAMTIQUE me trouve tout seul le type de la fonction que j'ai ecrit ou me dise si le type de la fonction n'est pas bien typé, ambigue, ou qu'il a besion d'information complementaire.
Apres tout meme si ce n'ai pas tres rigoureux, je n'imagine pas qu'un mathematicien ne se permette pas de temps a autre et lorsqu'aucun doute n'est permis, d'ecrire ce genre de chose ;-)
f (x) = a x² + b x + c
delta = b² - 4ac
mais je me trompe peut etre.
toujours est il que dans le cadre d'un langage inforamtique je trouve tres agreable la maniere dont on peut 'poser' ces fonctions, et encore plus magique le fait que celles ci soient referentiellement transparente , c'est a dire exemptes de tout effet de bord.
Je ne suis pas mathematicien et j'ai (et continue) de coder en C++ mais haskell m'a veritablement apaisé dans ma maniere de coder et considerer les problemes informatiques (que ceux ci soient bas niveau ou haut niveau, l'important reste de toujours penser dans les termes de ce problemes (et d'ailleur le c/c++ est difficile pour ca mais java / etc ne s'en sortent pas toujours tellement mieux ) ).
pour les tuples en retour je suis d'accord avec toi , ca reste une valeur de retour unique (ou je n'ai pas bien saisie alors)
[^]Re: Ruby
Petite correction: son nom est Philip Walder.
[^]Re: Ruby
Soit il n'est pas référencé sur Wikipédia, soit c'est Philip Wadler (soit c'est une erreur sur Wikipédia _et_ sur la page perso du monsieur).
http://en.wikipedia.org/wiki/Walder
http://en.wikipedia.org/wiki/Wadler
http://homepages.inf.ed.ac.uk/wadler/
Free Softwares Users Group Arlon (Sud Luxembourg, Belgique)
pertinent, e adj. Approprié ; qui se rapporte exactement à ce dont il est question.
[^]Re: Ruby
Moi aussi la syntaxe de lisaac me semblait pourris. Mais en fait, il y a _très_ peu de règle à comprendre pour tout faire.
Le c _semble_ simple. Mais la gestion/déclaration des types est catastrophiques. En C++, c'est pire.
[^]Re: Ruby
Pour la postérité, voici la première formulation publique de la loi de Wadler que j'ai trouvé : http://www.informatik.uni-kiel.de/~curry/listarchive/0017.ht(...)
Free Softwares Users Group Arlon (Sud Luxembourg, Belgique)
pertinent, e adj. Approprié ; qui se rapporte exactement à ce dont il est question.
[^]Re: Ruby
Et ya moyen d'avoir ça avec une syntaxe potable ? (désolé, ignorez ça, c'est un réflexe, un instinct de survie qui me pousse à réagir violemment à la simple vue de := )
Plus sérieusement, Lisaac, j'aime bien le concept, mais la syntaxe me fait fuir. C'est volontaire ou ça vient de moi ?(du genre INTEGER_32, tout en majuscule, je trouve ça moche - et pas pratique à taper surtout. L'opérateur d'affection de deux lettres, je trouve ça chiant au possible aussi).
Tu n'es pas le premier :) voire ma réponse à Brouillon.
- LIST[INTEGER_32]: le [ ], il est défini comment (et où, surtout): dans le langage, comme en C++ avec un operator[] ou en python __getitem__ ?
[ ] signifie que LIST est un objet (ya pas de classe en lisaac je le rapelle) ayant pour objet générique INTEGER_32 dans le cas présent.
La définition de LIST est LIST[E], C'est comme un Vector en Java si tu veux.
- pour le .when_alone { foo }, comment on sait que ça s'applique sur lst ? C'est du sucre syntaxique du langage ou un truc astucieux de COLLECTION (du genre when_empty renvoie la liste donc le truc équivaut vaguement à lst.when_empty(bloc_1).when_alone(bloc_2))
LIST hérite de COLLECTION (logique s'en est une)
Je défini la méthode .when_alone dans l'objet COLLECTION, comme défini plus haut.
Tous les fils en héritent.
lst étant une liste, c'est un vulgaire appel de méthode.
BLOCK est un objet "suite d'instructions avec paramètres d'entrés sortis (0,n)(0,n)"
[^]Re: Ruby
Pour ce qui est des majuscules, perso, j'ai rapidement pris l'habitude du CAPS LOCK.
Concernant la syntaxe, elle est très simple et très logique, je te conseille de regarder de plus près car Lisaac est un langage passionant (même si le compilateur v0.1 est un peu limité, mais le 0.2 devrait arriver vite il paraît)
La Roue du Temps
[^]Re: Ruby
Justement, je trouve pas ça si génial que ça moi. Avec ta méthode, du point de vue du sens, le for est un truc qui concerne la première borne : c'est sa méthode qu'on utilise, et à laquelle on donne la deuxième borne et le bloc en arguments (c'est pas forcément la bonne terminologie, mais c'est pas grave).
Moi, je trouve ça laid. Je vois pas pourquoi dans un for, il y aurait une asymétrie entre la première et la deuxième borne.
Dans l'idée, je trouve beaucoup plus joli d'exprimer le for comme une fonction qui dépend des bornes et du bloc :
let for debut fin bloc = ...
En Ocaml/Haskell par exemple, on peut faire ça pour pas cher. Si on ne fait pas d'effet de bords, le "for" n'a à priori pas grand sens, mais imaginons que le for fonctionnel renvoie la liste des valeurs générées par le bloc à chaque itération :
let rec for low up bloc =
if low = up then []
else bloc low :: for (low + 1) up bloc
En Haskell, si on crée un alias de for nommé "to", on peut même faire des contorsions syntaxique amusantes, par exemple
1 `to` 10 $ bloc
(On peut faire pareil en OCaml si on donne un nom d'opérateur à for : 1 >> 10 $ bloc, par exemple)
Je pense que cette asymétrie forcée est un des grands problèmes de l'objet.
[^]Re: Ruby
/me espère pas se gourrer dans ce qui suit :
En général, on utilise for pour deux choses : soit parcourir un tableau, soit pour simplement faire une iteration
Dans le cas d'un parcour d'un tableau (une liste, un vecteur, ...) on ne devrait jamais à mon sens utiliser de for mais utiliser des constructions du type
montab.each()
Dans le cas d'itération (et donc là il y a une certaine disymétrie), écrire 1.to(10) ne me choque pas vraiment mais on peut très bien remplacer par une écriture du type : (1..10).each
Dans ce cas il n'y a aucune disymétrie. Mais pour des itérations partant de 0 (comme c'est souvent le cas en info) le mieux reste nbIter.times qui est franchement plus logique je trouve, il colle beaucoup mieux à l'esprit qu'on a des itérations.
note : sinon, dans les trucs pas logique, pourquoi certains utilisent des for(;;) ?
Mieux vaut à mon sens utiliser dans ce cas un while(true) (même si ça fait la même chose...), non ?
[^]Re: Ruby
Une liste, c'est un tableau ? hérétique ! :p
Je suis pas vraiment convaincu par l'utilisation des each() à tout vent :
- quand on une liste, on fait souvent des manipulations un peu complexes (récursives, toussa), qui sont bien représentées par les map, fold_left et fold_right, mais pas vraiment par each. Évidemment, il y a toujours des cas d'itération simple, mais je pense qu'ils sont largement minoritaires et que ça ne vaut pas le coup de mettre l'emphase dessus
- quand on a un tableau, on fait plus que juste le parcourir linéairement (sinon, on utiliserait une liste) : on a souvent besoin de l'indice, et on se retrouve souvent à modifier la case en question. Donc ça demande déjà pour avoir un truc un peu utile de passer deux argument au each : l'indice et la valeur. À ce moment là, le each est déjà assez lourd pour qu'un for soit syntaxiquement au moins aussi agréable
Par exemple :
tab.each { |i,v| tab[i] <- v + tab[(i + 1) % len] }
for i from 0 to len - 1 do { tab[i] <- tab[i] + tab[(i+1) % len] }
Dans ce cas très simple, je suis pas convaincu que le each soit plus simple à écrire et à lire (j'ai pris une syntaxe pseudo-ruby au pif, mais ça ne change pas grand chose je pense), il n'apporte pas grand chose, à part une gestion implicite des indices (c'est bien) et un paramètre supplémentaire contenant la valeur de la case actuelle (je suis pas convaincu que le rapport réflexion_supplémentaire/gain_lisibilité soit intéressant).
L'avantage principal des itérateurs, si j'ai bien compris, c'est qu'on peut les utiliser de manière plus ou moins transparente sur plusieurs type de données différent (tableaux, tables de hachage, listes à la rigueur). Dans l'idée c'est bien, mais en pratique je trouve que les structures de données que l'on manipule en même temps sont suffisamment différentes pour ne pas avoir besoin de méthodes de manipulations communes : si on commence à implémenter each sur un arbre binaire, c'est qu'il y a un petit problème de conception en général.
L'asymétrie n'est pas tant syntaxique que sémantique (hum, je connais pas assez la sémantique pour parler de ça, mais là je pense que c'est vrai ^^) : dans son exemple l'objet auquel on envoie un message, c'est 1, et 10 n'est qu'un argument. C'est fondamentalement asymétrique.
À mon avis, l'écriture (1..10).each bloc suggère plus une fonction curryfiée où (each 1 10) est une fonction prenant un bloc et lui appliquant l'itération, qu'un appel objet.
[^]Re: Ruby
juste rapidement (manger, toussa ;-) )
Non non, j'ai pas voulu dire ça ;-)
Simplement que je rencontre souvent du code où pour parcourir une liste un for i++ est utilisé (oui, il m'arrive de lire du mauvais code... :( )
sur le principe du each / for, je ne parlais pas forcément du plus simple à écrire/lire mais ce qu'il me semble le plus correct au niveau de la représentation qu'on peut en avoir (je sais pas trop comment dire, mais sur le fond plus que la forme quoi). Il me semble plus logique dans le cas d'un parcour d'un élement de manipuler d'abord cet élement plutôt que de sortir un artefact tout fait qui en réalité est purement inspiré de langages non objets (voir même de contraintes machines, assembleur toussa)
En fait je voyais ça comme (1..10) qui crée un tableau [1, 2, 3 ... 9, 10]
et donc le each se rapport sur l'ensemble et non une fonction prenant un bloc et donc dans ce cas c'est un appel objet. (note : je me trompe peut-être, je ne suis pas allé voir comment ça marche à l'intérieur)
[^]IoLanguage
0 to(5) foreach(print)
C'est quand même plus beau, non ?
L'apocalypse / fin du monde est proche