90

Et j'ai mieux pour les arbres en C pur:

typedef struct arbre {
union {
struct {
struct arbre *a;
struct arbre *b;
} noeud;
struct {
void *zero;
void *data;
} feuille;
};
} arbre;
Et après, il suffit de comparer x.feuille.zero ou x.noeud.a avec 0 pour savoir si on a un nœud ou une feuille.

Mes habitudes caméliennes me font vraiment trouver ça terriblement lourd.
EnCaml, une ligne suffit, ou deux si on veut avoir une jolie présentation
type 'a arbre = feuille of 'a | noeud of ('a arbre)*('a arbre);;

Et un filtrage trivial (noeud/feuille) permet de discriminer les deux cas possibles.
Les droits inaliénables du troll :
1) le droit d'avoir raison
2) le droit d'être péremptoire
3) le droit de ne pas lire
4) le droit de ne pas répondre
5) le droit d'être de mauvaise foi
6) Autant pour moi / Faignant / Vivent Tintin et Milou

91

Met le coefficient du nombre de lignes de code à 1 au lieu de 0, et ocaml *écrase* tout le monde.

Tiens au passage, Kevin, tu peux classer les langages uniquement selon leur utilisation de mémoire => tu constateras que caml est encore en deuxième place, et qu'il consomme autant de mémoire que le C.
Les droits inaliénables du troll :
1) le droit d'avoir raison
2) le droit d'être péremptoire
3) le droit de ne pas lire
4) le droit de ne pas répondre
5) le droit d'être de mauvaise foi
6) Autant pour moi / Faignant / Vivent Tintin et Milou

92

HIPPOPOTAME a écrit :
attention En caml, ce n'est pas une surcharge (ça n'existe pas).

Surcharge ou filtrage par type, ça revient au même!
Mais si, c'est encore un gosub / appel de fonction! L'exécution du programme (c'est à dire la lecture de la démonstration) termine quand on arrive physiquement à la fin de la démo.

Tu n'as jamais lu "et on a fini." au milieu d'une démonstration, dans le traîtement d'un des cas possibles, toi?
Donc le "de même" est un gosub vers une partie précédente, puis la lecture reprend à la fin et termine.
Bien sur, le compilateur (le lecteur) optimisera cet appel en un JMP, mais c'est une basse question d'implémentation smile

grin
Je n'étais pas sérieux en disant ça. Mais il faut arrêter de mesurer l'évolution concrète d'un logiciel au nombre de releases. Ca dépend de la stratégie de l'équipe de développement : sortir publiquement une nouvelle version à la moindre correction, ou regrouper les modifications.

C'est moins bien pour l'utilisateur s'il a a attendre des mois pour avoir une version corrigée!

Tu dois avoir raisontriso D'ailleurs on devrait aussi supprimer les langages compilés (quelle paresse que de ne pas s'occuper des registres soi même!) et recommencer à programmer en assembleur!

Je trouve bien dommage que l'assembleur est utilisé si peu. sad
Cela dit, le C a un grand avantage par rapport à l'assembleur: il est portable!
L'informatique évolue vers plus d'abstraction. Ce n'est pas de la paresse, c'est du progrès.

Donc pour toi, le progrès, c'est d'au lieu d'avoir un programme qui prend une minute sur un 8086, on a un programme qui prend une minute sur un P IV à 2,5 GHz??? Beau progrès... roll Les développeurs de matériel ne travaillent pas pour la paresse du programmeur, ils travaillent pour que les programmes deviennent plus rapides!
Peu importe tes allégations de mauvaise foi, en pratique ce n'est pas ce qui se passe. Caml (comme Java d'ailleurs) n'aspire pas petit à petit toute la mémoire, comme tu semble le croire. Du point de vue de l'OS il utilise la mémoire peu ou prou comme le C.

Mais alors pas du tout! Un système de "garbage collection" n'utilisera jamais la mémoire de manière aussi efficace que la libération manuelle!
Si même sur un 68k d'il y a 30 ans ça ne pose que des problèmes mineurs,

Tu appelles ça des problèmes mineurs que de perdre du temps et de la vitesse, et de soit avoir une instruction de plus, soit sacrifier un registre d'adresses?
imagine sur un P IV ou un athlon.

Comme déjà dit, l'addition est encore le cas le plus favorable. Ça sera pire pour les autres opérations.
mais oui mais oui. C'est aussi un sous anneau du corps des quaternions, tu en déduis que les entiers et les quaternions ont les mêmes propriétés?

Non, mais j'en déduis qu'il n'y a pas de problèmes à utiliser le même signe de multiplication!
Donne des exemples courants... Moi je n'en ai jamais besoin. Ou alors il s'agit de calculs en précision infinie.

Si tu programmes un logiciel de gestion de finances et que tu veux que Bill Gates puisse l'utiliser, tu as intérêt à utiliser plus de 31 bits. smile Sinon tu seras limité à 1 milliard de cents (230, puisqu'il y a aussi le signe), donc 10 millions de dollars ou d'euros.
Un octet c'est un char en caml, et c'est codé sur 8 bits (dans une chaîne de caractères en tout cas).

Et donc l'alignement gaspille de la place si on en a plusieurs.
Idem pour les string en caml...

Bien heureusement!
L'erreur est dans le "à chaque fois". On transtype très peu.

"À chaque fois" que c'est nécessaire, évidemment! roll
C'est plus simple justement parce qu'il n'y a pas besoin d'y réfléchir. Soyons sérieux. Si x=3, alors x est un entier. On ne s'embête jamais à choisir véritablement les types, ils viennent tout seul.

Et ben, ça marche si et seulement si on a un seul type d'entiers (et encore, on pourrait vouloir en faire un flottant). Ça limite donc le langage.
Le filtrage est à un tout autre niveau de simplicité.

Tu ne connais pas bien la RTTI, parce que ça fonctionne exactement de la même manière:
if (typeid(*x)==typeid(Feuille)) {
...
} else if (typeid(*x)==typeid(Noeud)) {
...
} else abort();

ou:
if (dynamic_cast <Feuille *> (x)) {
...
} else if (dynamic_cast <Noeud *> (x)) {
...
} else abort();

(Évidemment, la solution en C pur est un peu plus compliquée, mais pas beaucoup.)
Si j'étais martien et si j'avais à ma disposition un ensemble plus grand de symboles, je l'écrirais différemment.

Mais (presque?) tous les mathématiciens et non-mathématiciens du monde l'écrivent de la même manière!
Les microprocesseurs l'écrivent différemment.

C'est un détail d'implémentation.
Moumou
a écrit : C'est du bricolage, et tu dois le refaire dès que f s'applique à trois éléments, ou tout autre changement...

http://tigcc.ticalc.org/doc/gnuexts.html#SEC77
Met le coefficient du nombre de lignes de code à 1 au lieu de 0, et ocaml *écrase* tout le monde.

Ça n'a aucun rapport avec l'efficacité, et ça dépend fortement de la présentation.
Aussi lourd que de devoir déclarer les types de chaque variable. Et plus rare.

Je ne vois pas en quoi il est plus lourd de mettre un type plutôt que let.
Tu écris ton code comme si le type des variables était déclaré, et c'est le compilo qui se charge de le faire pour toi. Y a pas besoin de réfléchir à quel type choisir, justement.

Si, il y a besoin de réfléchir, parce que le langage est fortement typé, et que si la variable a le malheur de ne pas être du bon type, tu vas te taper un paquet d'erreurs.
C'est le "d'habitude", qui fait tache. L'intérêt de Caml, c'est qu'on n'a plus *jamais* besoin de se soucier des erreurs de type indécelables.

Tu n'as pas compris. Ce que je voulais dire par le "d'habitude", c'est que la plupart des erreurs d'ordre d'arguments ne seront justement pas des erreurs de type, parce qu'on échange par exemple 2 entiers entre eux! (Exemple type: x, y à la place de row, column ou vice-versa.)
GCC rattrape donc uniquement les erreurs les plus courantes, là où Caml les rattrape toutes.

Pour les rares cas où l'erreur n'est pas visible lors de la compilation, on peut toujours utiliser un débogueur.
Oui, mais tu peux dire que 2 * 3 = 3 + 3 = 2 + 2 + 2. Encore, pour 2 * 3,1, tu peux dire que c'est 3,1 + 3,1. Mais que dire de 3,1 * 3,1 ? Ou pire, de Pi * Sqrt(2) ? La multiplication réelle est définie par extension de la multiplication entière pour être une loi de corps, mais on perd des propriétés au passage ! De même pour l'exponentiation : 3^4 = 3 * 3 * 3 * 3, 3 ^ (1/2), on peut encore admettre que c'est sqrt(3), mais pour passer à 3^Pi, c'est une autre paire de manches... Même pour l'addition entière, tu peux dire que 4 + 5 = 4 + 1 + 1 + 1 + 1 + 1, alors que tu ne peux faire de même avec 2,3 + 6,8.
Les lois sur |R sont définies par extension des lois sur Z, mais les différences sont fondamentales ! Bon je sais bien que dans le proc, les réels sont finalement des rationnels, mais la différence, même si elle est moins marquée entre Q et Z, reste. Tu n'utilises d'ailleurs surement pas le même algo pour calculer 2^3 ou racine(3,5). Alors pourquoi considérer que 2 * 3 et 3,5 * 0,5 sont les mêmes opérations ?

Parce que la multiplication sur Z est un cas particulier de la multiplication sur |R!
Toi par exemple, tu ne connais qu'un langage ?

http://tigcc.ticalc.org/people/kevin.html
HIPPOPOTAME a écrit :
Mes habitudes caméliennes me font vraiment trouver ça terriblement lourd.
EnCaml, une ligne suffit, ou deux si on veut avoir une jolie présentation
type 'a arbre = feuille of 'a | noeud of ('a arbre)*('a arbre);;

En C aussi, une ligne suffit:
typedef struct arbre{union{struct{struct arbre*a;struct arbre*b;}noeud;struct{void*zero;void*data;}feuille;};}arbre;
grin
Et un filtrage trivial (noeud/feuille) permet de discriminer les deux cas possibles.

Et if (a->noeud.a) n'est pas "trivial" pour toi?
HIPPOPOTAME
a écrit : Tiens au passage, Kevin, tu peux classer les langages uniquement selon leur utilisation de mémoire => tu constateras que caml est encore en deuxième place,

Oui, mais...
et qu'il consomme autant de mémoire que le C.

... NON! Il a 20 points en moins!

Et d'ailleurs, à ce bench-là, il manque cruellement la mesure de la taille de l'exécutable! Je pense que le C serait loin devant (exécutables nettement plus petits) là...
avatar
Mes news pour calculatrices TI: Ti-Gen
Mes projets PC pour calculatrices TI: TIGCC, CalcForge (CalcForgeLP, Emu-TIGCC)
Mes chans IRC: #tigcc et #inspired sur irc.freequest.net (UTF-8)

Liberté, Égalité, Fraternité

93

Surcharge ou filtrage par type, ça revient au même!

Non.

* le type Entier_ou_flottant qui a été défini est codé en mémoire différemment d'un entier ou d'un flottant. Et la discrimination des opérations effectuées se fait à l'exécution et pas à la compilation. Ce n'est donc pas du tout une surcharge.

* Si un opérateur est surchargé, le compilateur ne peut plus typer.
Tu n'as jamais lu "et on a fini." au milieu d'une démonstration, dans le traîtement d'un des cas possibles, toi?

C'est un RTS, ou bien la fin du programme.
C'est moins bien pour l'utilisateur s'il a a attendre des mois pour avoir une version corrigée!

C'est un autre débat embarrassed mais bon, les bugs dans caml sont peu nombreux (Du fait qu'il s'appuie sur des principes théoriques forts, plus que le C, la structure du compilateur est plus claire).

Je trouve bien dommage que l'assembleur est utilisé si peu.

C'est dans la nature des choses. Les microprocesseurs sont de moins en moins adaptés à l'écriture d'assembleur "à la main". Essaie un peu d'écrire du code pour Ithanium, en ayant en tête les innombrables subtilités d'optimisation et les règles pour le calcul parallèle...
Donc pour toi, le progrès, c'est d'au lieu d'avoir un programme qui prend une minute sur un 8086, on a un programme qui prend une minute sur un P IV à 2,5 GHz??? Beau progrès... Les développeurs de matériel ne travaillent pas pour la paresse du programmeur, ils travaillent pour que les programmes deviennent plus rapides!

Caml est aussi rapide que le C (pardon, 0.13% moins rapide).
Mais alors pas du tout! Un système de "garbage collection" n'utilisera jamais la mémoire de manière aussi efficace que la libération manuelle!

Une voiture n'aura jamais un rendement énergétique aussi efficace que la marche à pieds.

Et les performances de caml montrent comme ton argument est négligeable.
Tu appelles ça des problèmes mineurs que de perdre du temps et de la vitesse, et de soit avoir une instruction de plus, soit sacrifier un registre d'adresses?

Il n'est pas possible de répondre à ta question en tant que telle, il faudrait implémenter caml et mesurer précisément la différence.
Caml serait sans doute 25 à 50% moins rapide que le C. Ce qui en ferait le 2ème langage (non assembleur) évolué sur Ti, par exemple.
Comme déjà dit, l'addition est encore le cas le plus favorable. Ça sera pire pour les autres opérations.

Il faudrait désosser un code objet caml et calculer les cycles.

Mais plutôt que de spéculer dans le vide, autant regarder les benchs.
Si tu programmes un logiciel de gestion de finances et que tu veux que Bill Gates puisse l'utiliser, tu as intérêt à utiliser plus de 31 bits. Sinon tu seras limité à 1 milliard de cents (230, puisqu'il y a aussi le signe), donc 10 millions de dollars ou d'euros.

Etablissons une fortune maximum, et le problème sera réglé smile
Plus sérieusement, les sommes d'argent font partie de bases de données et n'entrent pas vraiment dans les variables courantes du programme.
Il est judicieux, dans une telle application, de définir un type particulier pour les sommes d'argent, sur 64 bits. Ce qui permet au passage au compilateur de pointer les erreurs de type, et donc les erreurs d'arguments, contrairement au C.
Et donc l'alignement gaspille de la place si on en a plusieurs.

Non.
Dans une chaîne de caractères, les caractères sont bien sûrs juxtaposés!
"À chaque fois" que c'est nécessaire, évidemment!

C'est à dire très peu.
Et ben, ça marche si et seulement si on a un seul type d'entiers (et encore, on pourrait vouloir en faire un flottant). Ça limite donc le langage.

D'abord, on ne veut pas en faire un flottant.
Ensuite, ça aurait limité le langage il y a 10 ou 20 ans. Aujourd'hui, les différences de types d'entiers ne se justifient pratiquement plus.
Tu ne connais pas bien la RTTI, parce que ça fonctionne exactement de la même manière:
if (typeid(*x)==typeid(Feuille)) {
...
} else if (typeid(*x)==typeid(Noeud)) {
...
} else abort();
ou:
if (dynamic_cast <Feuille *> (x)) {
...
} else if (dynamic_cast <Noeud *> (x)) {
...
} else abort(); (Évidemment, la solution en C pur est un peu plus compliquée, mais pas beaucoup.)

Bref tu ne fais que me montrer que c'est nettement plus compliqué et nettement plus lourd.
C'est un détail d'implémentation.

Non, ça tient à la différence fondamentale entre int et float.
Ça n'a aucun rapport avec l'efficacité, et ça dépend fortement de la présentation.

On ne peut guère nier que les sources caml sont nettement plus compactes que les sources C.
Je ne vois pas en quoi il est plus lourd de mettre un type plutôt que let.

Si on veut programmer une fonction de tri, qui prend comme arguments une fonction générique de tri ( 'a->'a->bool ) et une liste ( 'a list ), et qui renvoie une liste ( a' list ), est il plus simple d'écrire :

let montri = function ....

et de laisser le compilateur typer, ou bien

( ( 'a -> 'a -> bool ) -> 'a list -> 'a list ) montri = ....

what

[cite]Si, il y a besoin de réfléchir, parce que le langage est fortement typé, et que si la variable a le malheur de ne pas être du bon type, tu vas te taper un paquet d'erreurs.[cite]
Non.
La vision que tu as en tête, c'est celle d'un C « intolérant ». Mais c'est une vision fausse, dans la pratique ça ne se passe pas comme ça. Le typage est limpide pour le programmeur, pas besoin d'y passer du temps.
Pour les rares cas où l'erreur n'est pas visible lors de la compilation, on peut toujours utiliser un débogueur.

C'est très très lourd.
Alors pourquoi considérer que 2 * 3 et 3,5 * 0,5 sont les mêmes opérations ?

Parce que les représentations utilisées, les algorithmes de multiplication utilisées, la vitesse, la taille, la qualité des approximations ne sont pas les mêmes.
typedef struct arbre{union{struct{struct arbre*a;structarbre*b;}noeud;struct{void*zero;void*data;}feuille;};}arbre;

Beurk.
un bel exemple de C illisible.

Bon et bien certes, ça tient sur une ligne en C.
Maintenant, compte les caractères.
Et if (a->noeud.a) n'est pas "trivial" pour toi?

D'une part, c'est nettement plus lourd que Noeud a ->...
D'autre part, comme, dans un type un peu générique, il faut faire des cascades de if/else, c'est *vraiment* lourd, comparé à la liste de cas limpide de caml.
... NON! Il a 20 points en moins!

sick ok, il a vingt petits points en moins sick
La belle affaire.
Les droits inaliénables du troll :
1) le droit d'avoir raison
2) le droit d'être péremptoire
3) le droit de ne pas lire
4) le droit de ne pas répondre
5) le droit d'être de mauvaise foi
6) Autant pour moi / Faignant / Vivent Tintin et Milou

94

HIPPOPOTAME
a écrit : * le type Entier_ou_flottant qui a été défini est codé en mémoire différemment d'un entier ou d'un flottant. Et la discrimination des opérations effectuées se fait à l'exécution et pas à la compilation. Ce n'est donc pas du tout une surcharge.

C'est donc de la RTTI utilisé alors qu'une surcharge suffirait. Vive le code lourd... roll
C'est dans la nature des choses. Les microprocesseurs sont de moins en moins adaptés à l'écriture d'assembleur "à la main". Essaie un peu d'écrire du code pour Ithanium, en ayant en tête les innombrables subtilités d'optimisation et les règles pour le calcul parallèle...

Le Itanium est un processeur excessivement compliqué. L'architecture x86-64 est une évolution beaucoup plus logique, et, à en croire les développeurs de GCC, une architecture nettement moins complexe. Attention, je ne dis pas qu'elle est simple à programmer en assembleur (assembleur x86 -> beurk!), mais il est quand-même plus simple que le Itanium.
Caml est aussi rapide que le C (pardon, 0.13% moins rapide).

Donc plus lent! Et essaye avec de vrais exemples, pas des benchs style fonction de Ackerman...
>Mais alors pas du tout! Un système de "garbage collection" n'utilisera jamais la mémoire de manière aussi efficace que la libération manuelle! Une voiture n'aura jamais un rendement énergétique aussi efficace que la marche à pieds.

Analogie tirée par les cheveux!
La voiture accélère, la "garbage collection" ralentit!
Et les performances de caml montrent comme ton argument est négligeable.

1. Regarde les statistiques de mémoire. Le C bat assez nettement le OCAML!
2. Les benchs en question sont des programmes relativement courts. Pour des applications plus complexes, ça sera certainement différent!
Mais plutôt que de spéculer dans le vide, autant regarder les benchs.

Je ne spécule pas dans le vide, je fais des prédictions en analysant mathématiquement les opérations.
Plus sérieusement, les sommes d'argent font partie de bases de données et n'entrent pas vraiment dans les variables courantes du programme.

Dans une application de finance, tu calcules sans arrêt dessus!
Il est judicieux, dans une telle application, de définir un type particulier pour les sommes d'argent, sur 64 bits. Ce qui permet au passage au compilateur de pointer les erreurs de type, et donc les erreurs d'arguments, contrairement au C.

Quand auras-tu compris qu'une erreur d'argument n'est pas nécessairement une erreur de type? Si elle est détectée en tant que telle, c'est juste un coup de chance, il ne faut pas s'y fier!
Non. Dans une chaîne de caractères, les caractères sont bien sûrs juxtaposés!

Mais dans un tableau?
>"À chaque fois" que c'est nécessaire, évidemment! C'est à dire très peu.

Non. On a souvent besoin de transtyper des variables.
D'abord, on ne veut pas en faire un flottant.

Rien ne te dit ça.
Ensuite, ça aurait limité le langage il y a 10 ou 20 ans. Aujourd'hui, les différences de types d'entiers ne se justifient pratiquement plus.

"pratiquement plus" != "plus". Et les plateformes embarquées, portables et/ou miniaturisées (exemple type: la calculatrice), ça existe aussi!
Bref tu ne fais que me montrer que c'est nettement plus compliqué et nettement plus lourd.

C'est un if tout bête! Ce n'est en rien différent de ton exemple de "filtrage"!
>C'est un détail d'implémentation. Non, ça tient à la différence fondamentale entre int et float.

Qui est un détail d'implémentation.
On ne peut guère nier que les sources caml sont nettement plus compactes que les sources C.

Mais ça n'a quand-même aucun rapport avec l'efficacité!
Si on veut programmer une fonction de tri, qui prend comme arguments une fonction générique de tri ( 'a->'a->bool ) et une liste ( 'a list ), et qui renvoie une liste ( a' list ), est il plus simple d'écrire :

let montri = function ....

et de laisser le compilateur typer, ou bien

( ( 'a -> 'a -> bool ) -> 'a list -> 'a list ) montri = ....

what

La deuxième écriture est beaucoup plus claire (sauf que les déclarations de type sont carrément ilisibles, j'aime nettement plus la syntaxe C pour déclarer un pointeur vers une fonction: int (*funcptr)(int, int); avec ton type générique - qui correspondrait à des templates C++, et qui n'est pas un concept C; en C, on passe nombre d'éléments et taille d'un élément en paramètre à qsort -, ça donnerait bool (*funcptr)('a,'a), ce qui serait toujours nettement plus lisible que la syntaxe bizarre fléchée utilisée par le CAML).
Non. La vision que tu as en tête, c'est celle d'un C « intolérant ». Mais c'est une vision fausse, dans la pratique ça ne se passe pas comme ça. Le typage est limpide pour le programmeur, pas besoin d'y passer du temps.

Tu fais trop confiance en un programme dépourvu d'intelligence!
>Pour les rares cas où l'erreur n'est pas visible lors de la compilation, on peut toujours utiliser un débogueur. C'est très très lourd.

Mais c'est la meilleure solution pour trouver des erreurs rares et bizarres.
D'une part, c'est nettement plus lourd que Noeud a ->...

Et pourtant ça fait 4 caractères de plus seulement...
D'autre part, comme, dans un type un peu générique, il faut faire des cascades de if/else, c'est *vraiment* lourd, comparé à la liste de cas limpide de caml.

Dans ce cas, on met un id au début et on fait un switch!
sick ok, il a vingt petits points en moins sick La belle affaire.

C'est quand-même non-négligeable! Et d'ailleurs, d'après ce que j'ai vu, les benchs C utilisent des int partout, même si ce n'est pas nécessaire (parce qu'un short suffirait). En changeant ça, l'écart serait encore plus net.
avatar
Mes news pour calculatrices TI: Ti-Gen
Mes projets PC pour calculatrices TI: TIGCC, CalcForge (CalcForgeLP, Emu-TIGCC)
Mes chans IRC: #tigcc et #inspired sur irc.freequest.net (UTF-8)

Liberté, Égalité, Fraternité

95

>C'est quand-même non-négligeable! Et d'ailleurs, d'après ce que j'ai vu, les benchs C utilisent des int partout, même si ce n'est pas nécessaire (parce qu'un short suffirait). En changeant ça, l'écart serait encore plus net.


Non pas forcement pasque les compilo on tendance a passer en paramettre les valeurs sur une taille d'un int de la machine, cad que si tu passe en param a une fonction prenant 4 char, le compilo aura tandance a envoyer 4 int sur la pile..
avatar
Proud to be CAKE©®™


GCC4TI importe qui a problème en Autriche, pour l'UE plus et une encore de correspours nucléaire, ce n'est pas ytre d'instérier. L'état très même contraire, toujours reconstruire un pouvoir une choyer d'aucrée de compris le plus mite de genre, ce n'est pas moins)
Stalin est l'élection de la langie.

96

C'est donc de la RTTI utilisé alors qu'une surcharge suffirait. Vive le code lourd...

Tu n'as rien compris, ça n'a rien à voir aussi bien avec de la RTII qu'avec une surcharge.
Donc plus lent! Et essaye avec de vrais exemples, pas des benchs style fonction de Ackerman...

Oui oui, il est 0.13% plus lent sick
calme, calme...
Regarde tout ce qui est testé dans le bench, et regarde les coefficients attribués à chaque test. C'est un bench exhaustif, et ackermann ne compte pas plus que ça. Ackerman est là pour mesurer la performance des appels de fonction et il a donc sa place dans un tel bench.

(Et au passage, les appels de fonction sont beaucoup plus rapides en Caml qu'en C)
Analogie tirée par les cheveux! La voiture accélère, la "garbage collection" ralentit!

Le garbage ne ralentit pas, comme le montre les benchs.
Ca ne mène à rien de faire abstraction de la réalité, comme tu le fais.
Mais dans un tableau?

J'aurais tendance à dire que les chars sont juxtaposés, mais je ne sais pas comment Caml gère ça.
Mais on utilise bien sûr des string, pas des char vect.
Non. On a souvent besoin de transtyper des variables.

*Tu* as souvent besoin.
Mais en général, non, *on* a pas souvent besoin.
"pratiquement plus" != "plus".

Devant tant de mauvaise foi et de chipotages, je reste sans voix.
Et les plateformes embarquées, portables et/ou miniaturisées (exemple type: la calculatrice), ça existe aussi!

Tu reviens sur qq chose que j'ai pourtant déjà dit : caml n'est pas adapté aux calculatrices, par exemple.
C'est un if tout bête! Ce n'est en rien différent de ton exemple de "filtrage"!

Besoin de lunettes?
Mais ça n'a quand-même aucun rapport avec l'efficacité!

Exemple de conversation avec Kevin :
KK> Non A
Moi> Mais si, A
KK> Mais ça n'a aucun rapport avec B!
( ( 'a -> 'a -> bool ) -> 'a list -> 'a list ) montri = ....
La deuxième écriture est beaucoup plus claire

Lol!
Quand on est bouché...
(sauf que les déclarations de type sont carrément ilisibles, j'aime nettement plus la syntaxe C pour déclarer un pointeur vers une fonction: int (*funcptr)(int, int); avec ton type générique - qui correspondrait à des templates C++, et qui n'est pas un concept C; en C, on passe nombre d'éléments et taille d'un élément en paramètre à qsort -, ça donnerait bool (*funcptr)('a,'a), ce qui serait toujours nettement plus lisible que la syntaxe bizarre fléchée utilisée par le CAML).

Lol encore!
Ton explication est tellement embrouillée que je ne vois pas où est la déclaration de type pouvant correspondre à celle de caml - sachant que de toute façon le C est incapable de faire un tri générique comme en Caml, il n'est pas assez fonctionnel et pas assez typé.

Quant à la syntaxe des types de caml, parler de syntaxe "bizarre", c'est vraiment l'hopital qui se moque de la charitéroll. Il n'y a pas plus clair qu'un type caml.
Si 'a est un type, alors 'a list est le type des listes de 'a.
Si 'a et 'b sont des types, alors 'a->'b est le type fonction d'argument 'a et de résultat 'b.

( 'a -> 'a -> bool ) -> 'a list -> 'a list désigne donc une fonction dont le premier argument est une fonction 'a -> 'a -> bool (l'opérateur de comparaison, qui prend deux 'a et qui renvoie un booléen), le deuxième argument est une 'a list et le résultat est une 'a list.
Tu fais trop confiance en un programme dépourvu d'intelligence!

Tu ne sais pas de quoi tu parles.
Mais c'est la meilleure solution pour trouver des erreurs rares et bizarres.

C'est très très lourd.
Et pourtant ça fait 4 caractères de plus seulement...

Plus l'imbriquation des accolades.
Le tout multiplié par une dizaines de lignes.
Ca devient lourd.
Dans ce cas, on met un id au début et on fait un switch!

=> Code moins efficace et plus gros, et qui reste plus lourd de toute façon.
C'est quand-même non-négligeable! Et d'ailleurs, d'après ce que j'ai vu, les benchs C utilisent des int partout, même si ce n'est pas nécessaire (parce qu'un short suffirait). En changeant ça, l'écart serait encore plus net.

L'écart serait le même, comme l'a dit godzil.
Et c'est négligeable.
Les droits inaliénables du troll :
1) le droit d'avoir raison
2) le droit d'être péremptoire
3) le droit de ne pas lire
4) le droit de ne pas répondre
5) le droit d'être de mauvaise foi
6) Autant pour moi / Faignant / Vivent Tintin et Milou

97

HIPPOPOTAME
a écrit : Tu n'as rien compris, ça n'a rien à voir aussi bien avec de la RTII qu'avec une surcharge.

Si. Un filtrage par type (pas par valeur) est équivalent:
* soit à une surcharge, si c'est calculé en temps de compilation.
* soit à de la RTTI, si c'est calculé en temps d'exécution.
Si tu n'es pas d'accord, il faudra que tu m'expliques où dans mon raisonnement tu vois un truc qui cloche.
Regarde tout ce qui est testé dans le bench, et regarde les coefficients attribués à chaque test. C'est un bench exhaustif, et ackermann ne compte pas plus que ça.

Ce sont quand-même des mini-programmes et pas des applications réelles. Et la petite taille des programmes en question réduit la consommation de mémoire des langages à "garbage collection" comme le CAML ou le Java, et les avantage donc injustement.
Ackerman est là pour mesurer la performance des appels de fonction et il a donc sa place dans un tel bench.

Mais c'est quand-même un mini-programme, ce qui mène au problème décrit ci-dessus!
(Et au passage, les appels de fonction sont beaucoup plus rapides en Caml qu'en C)

Essaye avec -mregparm ou __attribute__((regparm)). Supporté d'office sur x86, supporté par le patch TIGCC (ou AmigaOS, mais nous avons porté la partie en question du patch AmigaOS vers les versions récentes de TIGCC) sur 68k.
Le garbage ne ralentit pas, comme le montre les benchs. Ca ne mène à rien de faire abstraction de la réalité, comme tu le fais.

Beurk, à t'entendre dire ça, on ne croirait jamais que tu es mathématicien! sick
Aucun bench n'est exhaustif. Rien ne remplace les raisonnements théoriques. Un exemple n'est pas une démonstration! Et j'ai déja donné (3 paragraphes plus haut, et dans un message précédent) une explication plausible au fait que la "garbage collection" ne se remarque pas beaucoup dans le bench en question. Dans ces micro-benchs, souvent, il n'y aura même pas de "garbage collection", tellement ils sont courts! Ce n'est pas le cas pour une application réelle.
>"pratiquement plus" != "plus". Devant tant de mauvaise foi et de chipotages, je reste sans voix.

Ce n'est pas un chipotage, c'est de la rigeur mathématique. La mauvaise foi, c'est de dire "pratiquement plus", puis de continuer l'argument comme si c'était "plus" tout court.
Tu reviens sur qq chose que j'ai pourtant déjà dit : caml n'est pas adapté aux calculatrices, par exemple.

Donc le C est plus portable, ce qui est un grand avantage!
Besoin de lunettes?

rotfl
Exemple de conversation avec Kevin :
KK> Non A
Moi> Mais si, A KK> Mais ça n'a aucun rapport avec B!

rotfl
Je te signale que le discours d'origine parlait de benchmarks d'efficacité, et que tout d'un coup il a dérivé (et ce n'est pas moi qui l'ai fait dériver!) vers les LOC. J'ai juste fait remarquer cela.
Lol! Quand on est bouché...

Désolé, je préfère nettement la deuxième écriture parce qu'elle contient plus d'informations, et qu'on n'a donc pas besoin de retrouver cette information à chaque fois qu'on lit la source en question. (Une source est là aussi pour être lue, pas seulement pour être écrite!)
Lol encore! Ton explication est tellement embrouillée que je ne vois pas où est la déclaration de type pouvant correspondre à celle de caml

'a list montri('a list l, bool (*funcptr)('a,'a))
(Ce n'est évidemment pas une déclaration C, c'est une déclaration avec une syntaxe style C.)
sachant que de toute façon le C est incapable de faire un tri générique comme en Caml, il n'est pas assez fonctionnel et pas assez typé.

C'est ce que j'ai dit dans ma phrase (assez complexe grammaticalement, je l'avoue smile).
Quant à la syntaxe des types de caml, parler de syntaxe "bizarre", c'est vraiment l'hopital qui se moque de la charitéroll. Il n'y a pas plus clair qu'un type caml.
Si 'a est un type, alors 'a list est le type des listes de 'a. Si 'a et 'b sont des types, alors 'a->'b est le type fonction d'argument 'a et de résultat 'b.

Ça a sa logique, mais je préfère quand-même la logique C "on déclare comme on utilise".
( 'a -> 'a -> bool ) -> 'a list -> 'a list désigne donc une fonction dont le premier argument est une fonction 'a -> 'a -> bool (l'opérateur de comparaison, qui prend deux 'a et qui renvoie un booléen), le deuxième argument est une 'a list et le résultat est une 'a list.

Ah, dans ce cas, ça serait déjà plus clair sous la forme:
( 'a -> ( 'a -> bool ) ) -> ( 'a list -> 'a list )
et je trouve que cette manière de traîter une fonction à 2 variables comme une fonction qui à une variable associe une fonction à une variable (ce qui s'appelle une "curryfication" si j'ai bien compris les messages précédents) est une idée très bizarre et peu lisible.
> Tu fais trop confiance en un programme dépourvu d'intelligence! Tu ne sais pas de quoi tu parles.

Si. Un compilateur n'est pas et ne sera probablement jamais un être intelligent.
C'est très très lourd.

C'est moins lourd que de passer des heures à chercher un bogue dans une source sans comprendre ce qui se passe. (Comme j'ai déjà fait sous-entendre dans les messages précédents, il y a et il y aura toujours des erreurs logiques qui ne peuvent pas être détectés par un compilateur, si intelligent qu'il soit. Par exemple, le passage à l'envers de 2 variables de même type, par exemple des coordonnées.)
Plus l'imbriquation des accolades.

... qui rend le code nettement plus lisible.
Le tout multiplié par une dizaines de lignes. Ca devient lourd.

Tu chipotes vraiment, là.
> Dans ce cas, on met un id au début et on fait un switch! => Code moins efficace et plus gros, et qui reste plus lourd de toute façon.

Et tu crois qu'il fait comment, le compilateur CAML, quand il ne peut pas déterminer le type exact en temps de compilation (ce qui est certainement le cas dans ton exemple avec l'arbre: il peut typer la variable en "Arbre", mais il ne peut pas connaître le type exact, "Noeud" ou "Feuille")? Magie noire? grin
L'écart serait le même, comme l'a dit godzil.

Il n'y a pas que les paramètres. Il y a aussi les variables locales qui sont empilées, et le compilateur C s'arrange souvent pour mettre les types qui nécessitent un alignement plus petit ensemble pour mieux utiliser la place sur la pile.
Et c'est négligeable.

Pas si on a (par exemple) un unsigned char x[10000] et qu'on est obligé d'en faire un int x[10000] avec un int de 32, voire 64, bits. On perd déjà 30 KO sur une seule variable! Et si c'est la variable principale du mini-bench en question, on a une augmentation de la consommation de mémoire de presque 300% (exactement 300% si c'est la seule variable).
avatar
Mes news pour calculatrices TI: Ti-Gen
Mes projets PC pour calculatrices TI: TIGCC, CalcForge (CalcForgeLP, Emu-TIGCC)
Mes chans IRC: #tigcc et #inspired sur irc.freequest.net (UTF-8)

Liberté, Égalité, Fraternité

98

Si. Un filtrage par type (pas par valeur) est équivalent:
* soit à une surcharge, si c'est calculé en temps de compilation.
* soit à de la RTTI, si c'est calculé en temps d'exécution. Si tu n'es pas d'accord, il faudra que tu m'expliques où dans mon raisonnement tu vois un truc qui cloche.

Le problème, c'est que tu veux toujours ramener à du C ce qui n'en est pas. Mettons que ça se rapproche de la RTTI mais il ne faut pas non plus s'illusionner, quand on déclare un type
type truc =
| A of truc
| B of truc -> truc;;

il ne faut pas trop chercher d'équivalent...
Ce sont quand-même des mini-programmes et pas des applications réelles. Et la petite taille des programmes en question réduit la consommation de mémoire des langages à "garbage collection" comme le CAML ou le Java, et les avantage donc injustement.

Pipo complet.
Mais c'est quand-même un mini-programme, ce qui mène au problème décrit ci-dessus!

C'est vrai, c'est un problème, ça. On devrait faire des benchs sans programme.
Essaye avec -mregparm ou __attribute__((regparm)). Supporté d'office sur x86, supporté par le patch TIGCC (ou AmigaOS, mais nous avons porté la partie en question du patch AmigaOS vers les versions récentes de TIGCC) sur 68k.

Je crois qu'il est vain d'essayer de dépasser l'appel de fonctions en Camlsmile
Le C est fort compétitif dans d'autres domaines, mais pas là.
Beurk, à t'entendre dire ça, on ne croirait jamais que tu es mathématicien! Aucun bench n'est exhaustif. Rien ne remplace les raisonnements théoriques. Un exemple n'est pas une démonstration!

Une démonstration infirmée par les faits est une démonstration fausse. Tu manques d'esprit logique.
Donc le C est plus portable, ce qui est un grand avantage!

Tu sais très bien que le C est un langage plus porté, mais qu'il n'est pas du tout plus portable.
C est disponible sur une plus grande variété de microprocesseur, mais les programmes Caml sont vraiment *beaucoup* plus facilement portables que les programmes C.
Quand à dire que c'est un plus grand avantage que C soit présent sur plus de proc... non, on s'en fout!
Caml n'est pas fait pour tourner sur un téléphone portable ou un four micro onde.
Désolé, je préfère nettement la deuxième écriture parce qu'elle contient plus d'informations, et qu'on n'a donc pas besoin de retrouver cette information à chaque fois qu'on lit la source en question. (Une source est là aussi pour être lue, pas seulement pour être écrite!)

Sidérant.
Tu préfèrerais aussi copier/coller les header C au lieu de les inclure?
Tu préfèrerais écrire (int)3 au lieu de 3 à chaque fois qu'il y a un entier dans le code?
Cette mauvaise fois est incroyable. Les sources Caml sont limpides.
'a list montri('a list l, bool (*funcptr)('a,'a)) (Ce n'est évidemment pas une déclaration C, c'est une déclaration avec une syntaxe style C.)

Pardon, j'avais oublié une autre hétérogénéité du C : on ne déclare pas de la même façon le type des fonctions et des valeurs non-fonction (Pour une valeur non fonction, on met le type complet, tandis que pour une fonction, on se contente du type du résultat).
Cette aberration est justifiée à des fins simplificatrices (parce que noter les types est lourd).

Bon, pour revenir à 'a list montri('a list l, bool (*funcptr)('a,'a)), c'est honnêtement incompréhensible au premier coup d'oeil, il faut un effort de désossage pour voir de quoi ça parle. Et c'est chiant.
Ça a sa logique, mais je préfère quand-même la logique C "on déclare comme on utilise".

En Caml aussi on déclare comme on utilise.
Comme l'utilisation est plus claire, la déclaration est aussi plus claire.
Ah, dans ce cas, ça serait déjà plus clair sous la forme: ( 'a -> ( 'a -> bool ) ) -> ( 'a list -> 'a list )

Avec seulement ce qui a été dit, c'est juste.
Mais rajoutons qu'en Caml, le constructeur de type "->" a une priorité à droite, ce qui permet de supprimer des parenthèses inutiles et de rendre le résultat plus clair :
( 'a -> 'a -> bool ) -> 'a list -> 'a list

La morale de l'histoire étant que le type d'une fonction curryfiée a la forme :
arg1 -> arg2 -> ... -> argN -> résultat

Alors qu'un fonction sur des N-uples (berk! C'est incongru!) a le type :
arg1 * arg2 * ... * argN -> résultat

Notations satisfaisantes, devant lesquelles on pousse un grand soupir de bonheur.
et je trouve que cette manière de traîter une fonction à 2 variables comme une fonction qui à une variable associe une fonction à une variable (ce qui s'appelle une "curryfication" si j'ai bien compris les messages précédents) est une idée très bizarre et peu lisible.

1) "une idée très bizarre"
Visiblement tu ne t'en est jamais servi, le C étant extrêmement peu pratique quand il s'agit de fonctions.
La curryfication est une idée intéressante et très utile, qui permet des raccourcis saisissant dans le code. (Et elle est incontournable dans un langage fonctionnel sérieux.)

2) "Très peu lisible"
C'est bien sûr faux, cependant il y a une part de vérité dans ce que tu dis : la notation ne saute pas aux yeux du débutant et il lui faut bien 30 bonnes secondes pour s'y familiariser.
Si. Un compilateur n'est pas et ne sera probablement jamais un être intelligent.

triso qui en doute?
« Je suis Nono le compilateur. Comment allez vous? »
ça ne t'empêche pas de faire confiance à gcc pour mettre les bonne variables dans les bons registres au bon moment.
C'est moins lourd que de passer des heures à chercher un bogue dans une source sans comprendre ce qui se passe.

Mon cher Kevin, tu parles d'or!
... qui rend le code nettement plus lisible.

(rires)
Tu chipotes vraiment, là.

Certainement pas. Rien n'est plus laid qu'une enfilade de if
(Enfin j'exagère peut être. Il y a bien des choses laides en C)
Et tu crois qu'il fait comment, le compilateur CAML, quand il ne peut pas déterminer le type exact en temps de compilation (ce qui est certainement le cas dans ton exemple avec l'arbre: il peut typer la variable en "Arbre", mais il ne peut pas connaître le type exact, "Noeud" ou "Feuille")? Magie noire?

Le compilateur doit être adepte du vaudou, je présume.black
Parce qu'il type TOUJOURS à la compilation...

Notons que "Noeud" et "Feuille" ne sont pas des types mais des constructeurs de type.

La solution que tu préconises (mettre un id au début et faire un switch) conduit à calculer une valeur auxilliaire totalement inutile, et donc à réduire les performances. Alors que caml produit toujours le *meilleur* test possible pour discriminer les différents cas.
Pas si on a (par exemple) un unsigned char x[10000] et qu'on est obligé d'en faire un int x[10000] avec un int de 32, voire 64, bits. On perd déjà 30 KO sur une seule variable! Et si c'est la variable principale du mini-bench en question, on a une augmentation de la consommation de mémoire de presque 300% (exactement 300% si c'est la seule variable).

Si tu as peur pour la taille de tes matrices, utilise le module bigarray et tout est réglé.
Les droits inaliénables du troll :
1) le droit d'avoir raison
2) le droit d'être péremptoire
3) le droit de ne pas lire
4) le droit de ne pas répondre
5) le droit d'être de mauvaise foi
6) Autant pour moi / Faignant / Vivent Tintin et Milou

99

HIPPOPOTAME
a écrit : Pipo complet.

Non! L'inefficacité de la "garbage collection" se fait remarquer de plus en plus plus le programme est grand! Si le programme est petit, il y aura peu d'allocations, donc il n'y aura pas le problème de la mémoire consommée, et la "garbage collection" ne se produira pas, donc pas de ralentissements. Si le programme est plus grand, ça change tout!
C'est vrai, c'est un problème, ça. On devrait faire des benchs sans programme.

Non, on devrait les faire sur de vraies applications! Mais évidemment, le problème est qu'il faut coder la même application en C et en CAML. C'est pour ça que le bench que tu m'as montré se replie sur des mini-programmes. Mais il faut bien garder en tête que ce sont des mini-programmes et pas des benchs représentatifs de la réalité.
Je crois qu'il est vain d'essayer de dépasser l'appel de fonctions en Camlsmile Le C est fort compétitif dans d'autres domaines, mais pas là.

Les appels de fonction en C font le minimum nécessaire demandé par le processeur!
Une démonstration infirmée par les faits est une démonstration fausse. Tu manques d'esprit logique.

La démonstration n'est pas infirmée par les faits. Déjà, les benchs ne sont pas des contre-exemples valides mathématiquement parce qu'ils sont soumis à des erreurs de mesure. (Une mesure n'est pas une démonstration! Ce n'est pas parce qu'il n'y a pas de différence mesurable qu'il n'y a pas de différence.) Et ensuite, j'ai montré que pour des valeurs suffisamment grandes de n (le nombre d'octets alloués par le programme), la "garbage collection" est inefficace de manière mesurable (c'est-à-dire qu'elle dépasse un epsilon fixé qui correspond à l'imprécision de mesure), et toi, tu réponds que tu as des benchs avec de très petites valeurs de n où ce n'est pas le cas. Ce n'est pas un contre-exemple valide, tes exemples n'ont tout simplement pas une valeur suffisamment grande de n.
Tu sais très bien que le C est un langage plus porté
, mais qu'il n'est pas du tout plus portable. C est disponible sur une plus grande variété de microprocesseur, mais les programmes Caml sont vraiment *beaucoup* plus facilement portables que les programmes C.

Tu connais la norme POSIX? Regarde TIGCC pour Linux/Unix. Il tourne sur n'importe quel processeur (à condition qu'il soit supporté comme "host" et comme "target" par GCC), et sur un grand nombre de systèmes d'exploitations. Et c'est le cas pour beaucoup de programmes conformes à la norme POSIX. Et puis, il y a aussi une librairie standard C qui est disponible sur presque tous les systèmes d'exploitation; si on se limite à cette librairie standard, le programme fonctionnera presque partout sans aucun changement. C'est le cas de certains programmes qui font partie de TIGCC: ils marchent sans problèmes sous Windows et sur les plateformes POSIX.
Quand à dire que c'est un plus grand avantage que C soit présent sur plus de proc... non, on s'en fout! Caml n'est pas fait pour tourner sur un téléphone portable ou un four micro onde.

On ne s'en fout pas! Un langage disponible pour plus de plateformes est un langage meilleur!
Sidérant. Tu préfèrerais aussi copier/coller les header C au lieu de les inclure?

Non. Un programmeur C sait déjà ce qu'il y a dedans.
Tu préfèrerais écrire (int)3 au lieu de 3 à chaque fois qu'il y a un entier dans le code?

Non, ça se voit de loin que 3 est un entier!

Mais pour le type de chaque variable, on ne le connaît pas à l'avance, et on ne le voit pas de loin, donc c'est différent!
Cette mauvaise fois est incroyable.

Arrête de m'accuser de mauvaise foi!!!
Les sources Caml sont limpides.

Tu es tellement habitué à ce langage illisible que tu ne te rends même plus compte qu'il est illisible!
Pardon, j'avais oublié une autre hétérogénéité du C : on ne déclare pas de la même façon le type des fonctions et des valeurs non-fonction (Pour une valeur non fonction, on met le type complet, tandis que pour une fonction, on se contente du type du résultat).

On met bien le type complet! Mais on met les argument pris après le nom de la fonction, parce que c'est comme ça qu'on appelle une fonction (encore la convention "on déclare de la même manière qu'on appelle").

[cite]Cette aberration est justifiée à des fins simplificatrices (parce que noter les types est lourd).
Bon, pour revenir à 'a list montri('a list l, bool (*funcptr)('a,'a)), c'est honnêtement incompréhensible au premier coup d'oeil, il faut un effort de désossage pour voir de quoi ça parle. Et c'est chiant.

C'est nettement plus lisible que ( 'a -> 'a -> bool ) -> 'a list -> 'a list, mais tu as trop pris l'habitude des écritures illisibles. Dans 'a list montri('a list l, bool (*funcptr)('a,'a)), on voit de loin que c'est une fonction parce qu'il y a une liste d'arguments entre parenthèses, on voit tout de suite le type retourné parce qu'il est à gauche et la liste d'arguments parce qu'elle se trouve entre le parenthèses. On voit tout de suite le type (et le nom, mon exemple était un entête de fonction, pas un prototype) du premier argument. Pour le deuxième, on voit tout de suite qu'il s'agit d'une fonction, on voit que c'est un pointeur vers une fonction parce que le "nom" de la fonction est (*funcptr), un pointeur déréférencé, et on voit encore une fois tout de suite le type retourné et la liste des arguments. Toutes ces choses sautent à l'œil, alors que dans ( 'a -> 'a -> bool ) -> 'a list -> 'a list, on est perdus dans un labyrinthe de flèches (en partie à cause de la syntaxe, et en partie parce que tu as omis des parenthèses nécessaires pour la compréhension par un être humain).
En Caml aussi on déclare comme on utilise. Comme l'utilisation est plus claire, la déclaration est aussi plus claire.

Non, tu ne déclares pas comme tu utilises!
Tu déclares type_argument -> type_retour et tu utilises nom_fonction type_argument. Ce n'est pas du tout la même chose. Si on suit la logique "on déclare comme on utilise", alors:
* soit on déclare type_argument -> type_retour nom_fonction et on utilise la fonction avec type_argument -> nom_fonction.
* soit on déclare type_retour nom_fonction type_argument et on utilise la fonction nom_fonction type_argument.
Le CAML mélange les 2, donc on déclare de manière différente qu'on utilise.
Avec seulement ce qui a été dit, c'est juste.
Mais rajoutons qu'en Caml, le constructeur de type "->" a une priorité à droite, ce qui permet de supprimer des parenthèses inutiles et de rendre le résultat plus clair :
( 'a -> 'a -> bool ) -> 'a list -> 'a list

J'avais déjà compris ça! Mais ces parenthèses ne sont pas inutiles, leur omission rend le code totalement illisible! On croirait avoir affaire à une fonction de 'a vers 'a et à une fonction de 'a vers bool, alors qu'on est devant une fonction de 'a vers une fonction de 'a vers bool.
1) "une idée très bizarre"
Visiblement tu ne t'en est jamais servi, le C étant extrêmement peu pratique quand il s'agit de fonctions. La curryfication est une idée intéressante et très utile, qui permet des raccourcis saisissant dans le code. (Et elle est incontournable dans un langage fonctionnel sérieux.)

"Utile" et "bizarre" ne sont pas forcément incompatibles! Et ce système a un grand problème: tu peux fixer seulement la valeur du premier argument. Si tu veux fixer la valeur du deuxième argument, ça ne marchera pas. Il serait plus intéressant d'avoir un moyen général de fixer la valeur d'un argument, quelle que soit sa position dans la liste des arguments.
2) "Très peu lisible" C'est bien sûr faux, cependant il y a une part de vérité dans ce que tu dis : la notation ne saute pas aux yeux du débutant et il lui faut bien 30 bonnes secondes pour s'y familiariser.

Tes 30 secondes sont une estimation très optimiste.
ça ne t'empêche pas de faire confiance à gcc pour mettre les bonne variables dans les bons registres au bon moment.

Tu n'es pas obligé de lui faire confiance. Tu peux explicitement déclarer register int variable1 asm("d3");.
>>Plus l'imbriquation des accolades.
>... qui rend le code nettement plus lisible. (rires)

Les accolades montrent clairement où commence et où se termine le code.
Certainement pas. Rien n'est plus laid qu'une enfilade de if

Mais qu'est-ce qu'elles t'ont fait, ces 2 lettres? grin Et rien ne t'empêche de mettre: #define hippopotame if et d'avoir une enfilade d'hippopotames. grin
(Enfin j'exagère peut être. Il y a bien des choses laides en C)

rotfl
Le compilateur doit être adepte du vaudou, je présume.black
Parce qu'il type TOUJOURS à la compilation...
Notons que "Noeud" et "Feuille" ne sont pas des types mais des constructeurs de type.

Et donc le type est "Arbre" comme j'ai dit.
La solution que tu préconises (mettre un id au début et faire un switch) conduit à calculer une valeur auxilliaire totalement inutile, et donc à réduire les performances. Alors que caml produit toujours le *meilleur* test possible pour discriminer les différents cas.

Mais il a bien besoin de faire un test en temps d'exécution, et donc de mettre un identifiant! Ou alors d'utiliser l'astuce que j'ai proposée pour l'arbre, mais ça ne marche qu'en des cas particuliers.
Si tu as peur pour la taille de tes matrices, utilise le module bigarray et tout est réglé.

C'est quoi cette manie de tout mettre dans des modules?
avatar
Mes news pour calculatrices TI: Ti-Gen
Mes projets PC pour calculatrices TI: TIGCC, CalcForge (CalcForgeLP, Emu-TIGCC)
Mes chans IRC: #tigcc et #inspired sur irc.freequest.net (UTF-8)

Liberté, Égalité, Fraternité

100

Non! L'inefficacité de la "garbage collection" se fait remarquer de plus en plus plus le programme est grand! Si le programme est petit, il y aura peu d'allocations, donc il n'y aura pas le problème de la mémoire consommée, et la "garbage collection" ne se produira pas, donc pas de ralentissements. Si le programme est plus grand, ça change tout!

D'abord, tu surestime l'importance des GC. Dans un programme comme ackermann, par exemple, il n'y aura jamais de GC quelque soit la taille de l'argument.
Ensuite, si tu regardes les quantités de mémoire consommées dans les programmes qui réservent vraiment de la mémoire (Regular Expression Matching par exemple), tu verras qu'il y a nécessairement des GC.
Non, on devrait les faire sur de vraies applications! Mais évidemment, le problème est qu'il faut coder la même application en C et en CAML. C'est pour ça que le bench que tu m'as montré se replie sur des mini-programmes. Mais il faut bien garder en tête que ce sont des mini-programmes et pas des benchs représentatifs de la réalité.

Un bench représentatif de la réalité, ça n'existe pas.
A part ça, coder la même application en C et en Caml est délicat car les langages ont des performances très différentes selon les domaines.
Les appels de fonction en C font le minimum nécessaire demandé par le processeur!

Alors il est amusant de constater que c'est encore plus rapide en Camlsmile
Regarde le bench ackerman, c'est flagrant. Alors que :
- le programme C est écrit de manière optimisée, dans ce style illisible caractéristique.
- Caml, pour gérer ses entiers, doit rajouter les opérations qui selon toi pénalisent affreusement la vitesseroll
Déjà, les benchs ne sont pas des contre-exemples valides mathématiquement parce qu'ils sont soumis à des erreurs de mesure.

Tu veux dire que le type s'est planté en recopiant, gcc mettait 0.2 sec là où il a écrit 0.9 sec ?
Bel argument.
Et ensuite, j'ai montré que pour des valeurs suffisamment grandes de n (le nombre d'octets alloués par le programme), la "garbage collection" est inefficace de manière mesurable

C'est faux.
S'il existait des conclusions aussi catégoriques, il y aurait bien longtemps qu'on aurait abandonné les sytèmes garbage-collectés.
Tu connais la norme POSIX? Regarde TIGCC pour Linux/Unix. Il tourne sur n'importe quel processeur (à condition qu'il soit supporté comme "host" et comme "target" par GCC), et sur un grand nombre de systèmes d'exploitations. Et c'est le cas pour beaucoup de programmes conformes à la norme POSIX. Et puis, il y a aussi une librairie standard C qui est disponible sur presque tous les systèmes d'exploitation; si on se limite à cette librairie standard, le programme fonctionnera presque partout sans aucun changement. C'est le cas de certains programmes qui font partie de TIGCC: ils marchent sans problèmes sous Windows et sur les plateformes POSIX.

Tout ce que tu racontes ne change rien au fait qu'un programme C, sauf exceptions très minoritaires, ne se transporte jamais tel quel d'un windows à un linux, à un mac, sur une Ti, un Unix ou autres, sans parler des problèmes de librairies et de toute cette sorte de choses...
On ne s'en fout pas! Un langage disponible pour plus de plateformes est un langage meilleur!

Evidemment non. Tout dépend des buts, des tenants et des aboutissants de ce langage. Et on s'en fout de ne pas pouvoir faire tourner caml dans un four micro ondes.
Non. Un programmeur C sait déjà ce qu'il y a dedans.

Ouaip, et au passage, ils sont chiants et inutiles et alourdissent encore le code source (comme si le C en avait besoin...)
Non, ça se voit de loin que 3 est un entier!

Tu vois, tu deviens raisonnable!
De même, quand tu écris function x -> x+1, ça ce voit que c'est un objet int -> int
Mais pour le type de chaque variable, on ne le connaît pas à l'avance, et on ne le voit pas de loin, donc c'est différent!

Mais si mais si, ne sous estime pas l'intelligence du programmeur. Pour quelqu'un qui est capable de s'arracher les yeux à décortiquer de l'incompréhensible code C, le type d'un objet caml saute aux yeux.
Arrête de m'accuser de mauvaise foi!!!

De quoi d'autre alors?
Tu es tellement habitué à ce langage illisible que tu ne te rends même plus compte qu'il est illisible!

Voilà par exemple une phrase que je peux te retourner telle quelle.
On met bien le type complet! Mais on met les argument pris après le nom de la fonction, parce que c'est comme ça qu'on appelle une fonction (encore la convention "on déclare de la même manière qu'on appelle").

Oui, c'est bien ce que je dis, on déclare le type en petits morceaux. Un bout par ici, un bout par là...
C'est nettement plus lisible que ( 'a -> 'a -> bool ) -> 'a list -> 'a list, mais tu as trop pris l'habitude des écritures illisibles. Dans 'a list montri('a list l, bool (*funcptr)('a,'a)), on voit de loin que c'est une fonction parce qu'il y a une liste d'arguments entre parenthèses,

lol!
On ne voit strictement rien de loin, parce qu'il y a trop de parenthèses (3 paires, c'est vraiment se foutre de la gueule du monde). Doit on déduire des trois paires de parenthèses qu'il y a trois fonctions? visiblement pas... il faut s'échiner à démonter ce truc qui ne va pas dans le sens du cerveau humain.
Toutes ces choses sautent à l'œil, alors que dans ( 'a -> 'a -> bool ) -> 'a list -> 'a list, on est perdus dans un labyrinthe de flèches (en partie à cause de la syntaxe, et en partie parce que tu as omis des parenthèses nécessaires pour la compréhension par un être humain).

lol Tu es vraiment trop fort quand tu t'y mets grin
Je te laisse à ta conception très personnelle de la simplicité...
Non, tu ne déclares pas comme tu utilises!

Bien sûr que si. (Exemples plus bas)
Tu déclares type_argument -> type_retour et tu utilises nom_fonction type_argument.

Non, puisque justement, on ne déclare pas le type smile
Le CAML mélange les 2, donc on déclare de manière différente qu'on utilise.

Tu es tellement obnubilié par le mode de pensée du C que tu es incapable de juger autre chose sans faire un parrallèle qui n'a pas lieu d'être.
Le Caml ne mélange pas du tout les deux, il s'en fout et utilise ses propres méthodes.

L'adéquation entre les déclaration et l'utilisation est flagrante.

DECLARATION DE TYPE
type arbre =
| Feuille
| Noeud of arbre*arbre;;


DECLARATION DE FONCTION
let rec nb_feuille = function
| Feuille -> 1
| Noeud (a,b) -> (nb_feuille a) + (nb_feuille b);;


DECLARATION D'OBJET
Noeud ( Feuille, Noeud (Feuille, Feuille) );;

APPEL DE FONCTION
Si f est définie par
let f x y = x+y-1;;
Alors f 3 4;; renvoie 6
J'avais déjà compris ça! Mais ces parenthèses ne sont pas inutiles, leur omission rend le code totalement illisible!

Ces parenthèses sont inutiles. Totalement inutile.
Je rappelle que *même* dans le C (!), il y a des règles de priorité entre les opérateurs afin (sacrilège!) d'éliminer des parenthèses.

"rend le code totalement illisible"
De toute façon ce type n'apparaît pas dans le coderoll.
Mais il est bien sûr d'une totale lisibilité.
On croirait avoir affaire à une fonction de 'a vers 'a et à une fonction de 'a vers bool, alors qu'on est devant une fonction de 'a vers une fonction de 'a vers bool.

Oui, je l'ai cru moins aussi, les 30 premières secondes où j'ai fait du Camltsss.
"Utile" et "bizarre" ne sont pas forcément incompatibles! Et ce système a un grand problème: tu peux fixer seulement la valeur du premier argument. Si tu veux fixer la valeur du deuxième argument, ça ne marchera pas. Il serait plus intéressant d'avoir un moyen général de fixer la valeur d'un argument, quelle que soit sa position dans la liste des arguments.

Bref tu affirmes que la curryfication n'est pas encore assez, bravotop
Allez, une ligne de code pour résoudre ce problème, dans le plus pur style ultraminimaliste que j'affectionne :
let arg2 f a b = f b a;;

Après ça, arg2 f a représente la fonction partielle f(*,a)

(Et, au passage : on se fout totalement du type de arg2, on voit bien comment ça marche. La compilateur trouve ( 'a -> 'b -> 'c ) -> 'b -> 'a -> 'c )

Mais un tel système de curryfication du deuxième argument n'a pas d'intérêt. Les fonctions courantes +, *, sont symétriques. Les fonctions plus avancées ont leur argument dans le bon ordre, en principe.
Tes 30 secondes sont une estimation très optimiste.

Mon frère (qui n'avait *jamais* fait de programmation d'aucune sorte jusqu'à maintenant) s'est mis à Caml cette année (programme de maths sup).
Et ça marche très bien pour lui. Caml est un excellent langage d'apprentissage, entre autres.
Tu n'es pas obligé de lui faire confiance. Tu peux explicitement déclarer register int variable1 asm("d3");.

C'est judicieux, sur un PC?triso
Les accolades montrent clairement où commence et où se termine le code.

La syntaxe du filtrage montre de manière infiniment plus claire les différents cas.
Mais qu'est-ce qu'elles t'ont fait, ces 2 lettres?

Rien rien, je les aime bien même.
Mais I + F + ESPACE + PARENTHESES autour de l'expression booléenne + ACCOLADES + INDENTATION = LOURD
Spécialement quand on en enfile une floppée à la suite.
Et donc le type est "Arbre" comme j'ai dit.

Ben oui, le type est Arbreconfus
Tu voulais que ce soit quoi?
Mais il a bien besoin de faire un test en temps d'exécution, et donc de mettre un identifiant! Ou alors d'utiliser l'astuce que j'ai proposée pour l'arbre, mais ça ne marche qu'en des cas particuliers.

Mais non mais non il ne calcule pas didentifiant.
Quand le motif est (a,_,([b::q] as w)) when a>0, il génère le code le plus efficace sans avoir besoin des mauvaises combines pour émuler ça en C.
C'est quoi cette manie de tout mettre dans des modules?

C'est une manie qui consiste à virer du langage tout ce qui est inutilesmile
Les droits inaliénables du troll :
1) le droit d'avoir raison
2) le droit d'être péremptoire
3) le droit de ne pas lire
4) le droit de ne pas répondre
5) le droit d'être de mauvaise foi
6) Autant pour moi / Faignant / Vivent Tintin et Milou

101

HIPPOPOTAME a écrit :
D'abord, tu surestime l'importance des GC. Dans un programme comme ackermann, par exemple, il n'y aura jamais de GC quelque soit la taille de l'argument.
Ensuite, si tu regardes les quantités de mémoire consommées dans les programmes qui réservent vraiment de la mémoire (Regular Expression Matching par exemple), tu verras qu'il y a nécessairement des GC.

Voilà exactement pourquoi je dis que Ackerman est un mauvais bench! Ce n'est pas une application réelle, et ça n'y ressemble même pas!
Un bench représentatif de la réalité, ça n'existe pas. A part ça, coder la même application en C et en Caml est délicat car les langages ont des performances très différentes selon les domaines.

Et donc je me repose sur des raisonnements théoriques.
Alors il est amusant de constater que c'est encore plus rapide en Camlsmile
Regarde le bench ackerman, c'est flagrant. Alors que :
- le programme C est écrit de manière optimisée, dans ce style illisible caractéristique.
- Caml, pour gérer ses entiers, doit rajouter les opérations qui selon toi pénalisent affreusement la vitesseroll

La différence est de 0,05 secondes. C'est en dessous de ce qui est mesurable de manière fiable (cf. prochaine réponse), et l'auteur le reconnaît bien, vu que GCC et ocaml ont tous les 2 eu le même nombre de points en la vitesse sur la fonction Ackerman (9). Et d'ailleurs, je signale aussi que le programme C (compilé avec GCC) a consommé 72 KO de mémoire en moins!
Tu veux dire que le type s'est planté en recopiant, gcc mettait 0.2 sec là où il a écrit 0.9 sec ? Bel argument.

Non! Je veux dire qu'il s'est planté en mesurant! Et c'est forcément le cas: Même si on utilise la RTC de l'ordinateur pour mesurer, il est toujours impossible d'avoir une mesure au cycle du processeur près! D'autant plus qu'il y a forcément des tâches de fond (les tâches système sont toujours actives!). Voilà pourquoi les raisonnements théoriques sont indispensables.
C'est faux. S'il existait des conclusions aussi catégoriques, il y aurait bien longtemps qu'on aurait abandonné les sytèmes garbage-collectés.

Pas du tout. Tu sous-estimes largement le facteur motivant qu'est la paresse.
Tout ce que tu racontes ne change rien au fait qu'un programme C, sauf exceptions très minoritaires, ne se transporte jamais tel quel d'un windows à un linux, à un mac, sur une Ti, un Unix ou autres,

Dans TIGCC, quand j'ai porté le tprbuilder de *nix à Windows, la seule chose que j'ai été obligé de changer (à part l'usage d'une fonction spécifique à glibc, mais elle n'avait de toute façon pas sa place dans un programme portable, et c'était très facile à changer) étaient les noms de répertoire.
sans parler des problèmes de librairies et de toute cette sorte de choses...

Il suffit d'utiliser des librairies portables.
>On ne s'en fout pas! Un langage disponible pour plus de plateformes est un langage meilleur! Evidemment non. Tout dépend des buts, des tenants et des aboutissants de ce langage.

Si! Il y a aussi autre chose au monde que les x86!
Et on s'en fout de ne pas pouvoir faire tourner caml dans un four micro ondes.

... sauf si on fabrique des fours à micro-ondes. smile
>Non. Un programmeur C sait déjà ce qu'il y a dedans. Ouaip, et au passage, ils sont chiants et inutiles et alourdissent encore le code source (comme si le C en avait besoin...)

Ils sont utiles, et ils n'alourdissent le code source que d'une seule ligne!
Tu vois, tu deviens raisonnable!
De même, quand tu écris function x -> x+1, ça ce voit que c'est un objet int -> int

Ben non, ça ne se voit pas d'un premier coup d'œil. D'autant plus qu'une fonction est normalement nettement plus longue que cet exemple trivial. Et si tu dis toujours que ça se voit, alors que dis tu de:
function x -> x
? Il n'y a pas de +1 qui indique le type ici.
Mais si mais si, ne sous estime pas l'intelligence du programmeur. Pour quelqu'un qui est capable de s'arracher les yeux à décortiquer de l'incompréhensible code C, le type d'un objet caml saute aux yeux.

Le code C n'est pas incompréhensible! Il saute aux yeux!
>Arrête de m'accuser de mauvaise foi!!! De quoi d'autre alors?

De rien du tout. smile
Oui, c'est bien ce que je dis, on déclare le type en petits morceaux. Un bout par ici, un bout par là...

Parce que c'est aussi comme ça qu'on appelle une fonction! Je trouve cette manière de déclarer le type tout à fait naturelle.
lol! On ne voit strictement rien de loin, parce qu'il y a trop de parenthèses (3 paires, c'est vraiment se foutre de la gueule du monde).

rotfl
Les parenthèses sont une bonne chose pour la lisibilité!
Doit on déduire des trois paires de parenthèses qu'il y a trois fonctions? visiblement pas...

Non, parce que la deuxième parenthèse ouvrante n'est pas précédée d'un nom de variable, mais d'un nom de type. Et tu remarqueras que j'ai mis un espace devant cette parenthèse et pas devant les autres (exactement comme le conseillent K&R), ce qui permet de les différencier sans lire même une lettre: s'il n'y a pas d'espace devant, c'est un appel de fonction.
il faut s'échiner à démonter ce truc qui ne va pas dans le sens du cerveau humain.

Sauf que mon cerveau démonte ce genre de déclarations en une fraction de seconde! Surtout grâce aux parenthèses.
Tu es tellement obnubilié par le mode de pensée du C que tu es incapable de juger autre chose sans faire un parrallèle qui n'a pas lieu d'être.
Le Caml ne mélange pas du tout les deux, il s'en fout et utilise ses propres méthodes.
L'adéquation entre les déclaration et l'utilisation est flagrante.

Désolé, mais je continue à trouver cette pratique de déclarer let f x y = x+y-1;; sans préciser aucun type absolument illisible.
Et même en Mathématiques, on précise toujours l'ensemble de définition et l'ensemble de valeurs (ou du moins on devrait toujours le faire).
Ces parenthèses sont inutiles. Totalement inutile.

Non, puisqu'elles améliorent la lisibilité!
Je rappelle que *même* dans le C (!), il y a des règles de priorité entre les opérateurs afin (sacrilège!) d'éliminer des parenthèses.

Mais tout le monde conseille de mettre plus de parenthèses que strictement nécessaire de manière à améliorer la lisibilité et éviter de mauvaises surprises avec les priorités.
Mais il est bien sûr d'une totale lisibilité.

Non, il manque des parenthèses.
Bref tu affirmes que la curryfication n'est pas encore assez, bravotop
Allez, une ligne de code pour résoudre ce problème, dans le plus pur style ultraminimaliste que j'affectionne :
let arg2 f a b = f b a;;

Ah tiens, c'est une bonne idée, ça. smile
Mon frère (qui n'avait *jamais* fait de programmation d'aucune sorte jusqu'à maintenant) s'est mis à Caml cette année (programme de maths sup). Et ça marche très bien pour lui. Caml est un excellent langage d'apprentissage, entre autres.

Mais le meilleur langage d'apprentissage est toujours le BASIC.
>Tu n'es pas obligé de lui faire confiance. Tu peux explicitement déclarer register int variable1 asm("d3");.
C'est judicieux, sur un PC?triso

Bon, déjà un PC n'a pas de registre d3. grin Et ensuite, je ne conseillerais pas ça sur PC x86 vu qu'il n'a pas assez de registres pour garder une variable dans un registre pendant une fonction entière.
La syntaxe du filtrage montre de manière infiniment plus claire les différents cas.

Pas du tout. Un if montre très bien les différent cas.
Rien rien, je les aime bien même.
Mais I + F + ESPACE + PARENTHESES autour de l'expression booléenne + ACCOLADES + INDENTATION = LOURD

Tu chipotes, là!
Mais non mais non il ne calcule pas didentifiant.
Quand le motif est (a,_,([b::q] as w)) when a>0, il génère le code le plus efficace sans avoir besoin des mauvaises combines pour émuler ça en C.

Ton when a>0 se traduit 1:1 en if (a>0). Et pour les autres champs, c'est à ça que sert une union. Et si tu y accèdes par un pointeur, l'union ne doit pas nécessairement être remplie jusqu'au bout, donc on ne gaspille pas du tout de place si les motifs n'ont pas la même longueur.
Et dans ton exemple avec l'arbre, tu n'as précisé aucun motif, donc le compilateur CAML est bien obligé de mettre un identifiant ou d'utiliser l'astuce que j'ai proposé pour le C.
C'est une manie qui consiste à virer du langage tout ce qui est inutilesmile

Ce n'est pas inutile, sinon ça n'existerait pas en module!
avatar
Mes news pour calculatrices TI: Ti-Gen
Mes projets PC pour calculatrices TI: TIGCC, CalcForge (CalcForgeLP, Emu-TIGCC)
Mes chans IRC: #tigcc et #inspired sur irc.freequest.net (UTF-8)

Liberté, Égalité, Fraternité

102

Voilà exactement pourquoi je dis que Ackerman est un mauvais bench! Ce n'est pas une application réelle, et ça n'y ressemble même pas!

Allons allons.
Le bench que je t'ai indiqué, ce n'est pas Ackerman. Ackerman n'en est qu'une petite partie (qui a d'ailleurs un coefficient minuscule).
Le bench regroupe un panel d'applications aussi diverses que possible, couvrant tout ce que peut faire une application réelle.
Voilà pourquoi c'est un bon bench.
La différence est de 0,05 secondes.

La différence est du simple au double tongue
Non! Je veux dire qu'il s'est planté en mesurant! Et c'est forcément le cas: Même si on utilise la RTC de l'ordinateur pour mesurer, il est toujours impossible d'avoir une mesure au cycle du processeur près! D'autant plus qu'il y a forcément des tâches de fond (les tâches système sont toujours actives!). Voilà pourquoi les raisonnements théoriques sont indispensables.

ça va au delà de la mauvaise foi, làroll.
Il n'y a pas de difficulté à mesurer au centième près, et les mesures ont été répétées trois fois avec les mêmes résultats.
Dans TIGCC, quand j'ai porté le tprbuilder de *nix à Windows, la seule chose que j'ai été obligé de changer (à part l'usage d'une fonction spécifique à glibc, mais elle n'avait de toute façon pas sa place dans un programme portable, et c'était très facile à changer) étaient les noms de répertoire.

Bref, tu as eu à changer une fonction et des noms. Tu as eu de la chance, c'était peu.
Il suffit d'utiliser des librairies portables.

« Il suffit. »
Sauf que tout le monde n'utilise pas de librairies portables. (euphémisme)
Si! Il y a aussi autre chose au monde que les x86!

Oui, il y a aussi les Alpha, les Sparc, les Mips, les PA-RISC, les PowerPC/Power, les ARM et les Itanium. smile
... sauf si on fabrique des fours à micro-ondes.

Si le fabricant de fours à micro-ondes est passionné de langages fonctionnels, il peut toujours utiliser camlot, le compilateur de caml en C. Celà dit, c'est une drôle d'idée.
Et si tu dis toujours que ça se voit, alors que dis tu de:
function x -> x ? Il n'y a pas de +1 qui indique le type ici.

Ca se voit de façon encore plus immédiatement évidente.
'a -> 'a, tout simplement.
Le code C n'est pas incompréhensible! Il saute aux yeux!

Mais oui et la marmotte...
Les parenthèses sont une bonne chose pour la lisibilité!

(((Les(parenthèses))sont(une(bonne(chose)))(pour(la(lisibilité))))!)
Non, parce que la deuxième parenthèse ouvrante n'est pas précédée d'un nom de variable, mais d'un nom de type. Et tu remarqueras que j'ai mis un espace devant cette parenthèse et pas devant les autres (exactement comme le conseillent K&R), ce qui permet de les différencier sans lire même une lettre: s'il n'y a pas d'espace devant, c'est un appel de fonction.

Pauvres programmeurs C, obligés de supporter un tel salmigondistsss
Alors qu'une bête notation -> est si simple.
Sauf que mon cerveau démonte ce genre de déclarations en une fraction de seconde! Surtout grâce aux parenthèses.

Parce que ton cerveau est très bon, et parce qu'il a été contaminé tout petit et en profondeur par les mauvaises habitudes du C.smile
Désolé, mais je continue à trouver cette pratique de déclarer let f x y = x+y-1;; sans préciser aucun type absolument illisible.

Et bien tant pistsss
Le fait est que c'est parfaitement lisible.
Non, puisqu'elles améliorent la lisibilité!

Non, puisqu'elles gênent la lisibilité!
Mais tout le monde conseille de mettre plus de parenthèses que strictement nécessaire de manière à améliorer la lisibilité et éviter de mauvaises surprises avec les priorités.

Bien sûr, moi aussi je préfère écrire (f a)+(f b) au lieu de f a + f b.
Non, il manque des parenthèses.

Il en a juste ce qu'il faut.
Mais le meilleur langage d'apprentissage est toujours le BASIC.

Bof bof.
Ca dépend bien sûr de quel basic tu parles, mais je trouve que c'est une fausse bonne idée d'apprendre d'abord ce langage.
Bon, déjà un PC n'a pas de registre d3. Et ensuite, je ne conseillerais pas ça sur PC x86 vu qu'il n'a pas assez de registres pour garder une variable dans un registre pendant une fonction entière.

Parfaitement.
Moi j'interdirais tout simplement les inclusions d'assembleur sur les plateformes assez récentes.
Pas du tout. Un if montre très bien les différent cas.

C'est pas fait pour faire du filtrage, c'est donc forcément moins clair. (Et dans la pratique, de beaucoup)
Tu chipotes, là!

Certes non.
(a,_,([b::q] as w)) when a>0
Ton when a>0 se traduit 1:1 en if (a>0).

Sûrement pas!
Parce qu'en C, il faut encore déclarer et donner sa valeur à la variable a, qui est nichée quelque part dans le motif...
Et pour les autres champs, c'est à ça que sert une union.

Il n'y a pas de type union dans ce motif.
Et dans ton exemple avec l'arbre, tu n'as précisé aucun motif

Ben si.
Feuille ou Noeud(a,b)
Ce n'est pas inutile, sinon ça n'existerait pas en module!

Bon alors c'est une manie consistant à virer du langage tout ce qui est inutile sauf pour les râleurs
Les droits inaliénables du troll :
1) le droit d'avoir raison
2) le droit d'être péremptoire
3) le droit de ne pas lire
4) le droit de ne pas répondre
5) le droit d'être de mauvaise foi
6) Autant pour moi / Faignant / Vivent Tintin et Milou

103

HIPPOPOTAME a écrit :
Allons allons.
Le bench que je t'ai indiqué, ce n'est pas Ackerman. Ackerman n'en est qu'une petite partie (qui a d'ailleurs un coefficient minuscule).
Le bench regroupe un panel d'applications aussi diverses que possible, couvrant tout ce que peut faire une application réelle. Voilà pourquoi c'est un bon bench.

Mais ce sont toutes des "applications" trop petites pour que des effets comme la "garbage collection" se produisent de manière mesurable. Voilà pourquoi c'est un mauvais bench.
La différence est du simple au double tongue

Tu ne peux pas dire ça de manière certaine. La différence est en plein dans la marge d'erreur.
ça va au delà de la mauvaise foi, làroll. Il n'y a pas de difficulté à mesurer au centième près, et les mesures ont été répétées trois fois avec les mêmes résultats.

Ce n'est quand-même pas une démonstration mathématique. Et les timers utilisés par les systèmes d'exploitation n'ont en général pas cette résolution. Par exemple, le timer de Windows s'incrémente par étapes d'un 18ème de seconde environ.
Bref, tu as eu à changer une fonction et des noms.

Si le code avait été conforme à la norme POSIX, je n'aurais même pas eu à changer cette fonction. C'était une fonction qui n'était non seulement pas ANSI, mais même pas POSIX, donc son utilisation était un bogue.
Tu as eu de la chance, c'était peu.

Ce cas n'est pas si rare que ça.

Et d'ailleurs, un autre exemple: le nouveau linker de TIGCC a écrit dès le départ pour être portable. Résultat: bien qu'il ait été développé sous Windows, il était compilable sans aucun changement sous Linux dès le départ.
« Il suffit. » Sauf que tout le monde n'utilise pas de librairies portables. (euphémisme)

Ben, alors c'est leur choix de ne pas développer de manière portable. Ce n'est pas la faute du C.
Oui, il y a aussi les Alpha, les Sparc, les Mips, les PA-RISC, les PowerPC/Power, les ARM et les Itanium. smile

Mais il y a aussi les 68k, les Z80, les AVR, les 68HC11, ... Le C tourne sur tous ces processeurs.
Si le fabricant de fours à micro-ondes est passionné de langages fonctionnels, il peut toujours utiliser camlot, le compilateur de caml en C.

Le code est certainement lourd par rapport à du C codé directement.
Celà dit, c'est une drôle d'idée.

En effet, le C est bien plus adapté pour ces machines. Donc c'est un langage plus universel, donc meilleur.
Ca se voit de façon encore plus immédiatement évidente.
'a -> 'a, tout simplement.

Ah, donc le type peut être n'importe quoi. Et pourtant, tu me disais que toutes les variables étaient typées en CAML... confus
(((Les(parenthèses))sont(une(bonne(chose)))(pour(la(lisibilité))))!)

((Ben(oui))(elles(sont(une(bonne(chose))(pour(la(lisibilité)))))))! (Si((tout(le(monde)))(écrivait(comme(ça))))(il((y)aurait((bien)(moins(de(malentendus))(au(monde)))))))! (On(saurait(toujours)((à(quoi))((se)rapporte(une(proposition(relative)))))(par(exemple)))).
Pauvres programmeurs C, obligés de supporter un tel salmigondistsss Alors qu'une bête notation -> est si simple.

Je trouve toujours que la notation C est meilleure.
>Non, puisqu'elles améliorent la lisibilité! Non, puisqu'elles gênent la lisibilité!

Pas si leur nombre reste petit. Et puis, il y a les IDEs qui colorient les paires de parenthèses, ce qui rend les parenthèses encore plus lisibles.
Bien sûr, moi aussi je préfère écrire (f a)+(f b) au lieu de f a + f b.

Moi, je préfère f(a)+f(b). Une bonne raison est que c'est la convention utilisée par pratiquement tous les mathématiciens du monde.
Bof bof. Ca dépend bien sûr de quel basic tu parles, mais je trouve que c'est une fausse bonne idée d'apprendre d'abord ce langage.

Personnellement, j'ai commencé par le BASIC, et maintenant, je suis un des meilleurs programmeurs sur ce forum.
Parfaitement. Moi j'interdirais tout simplement les inclusions d'assembleur sur les plateformes assez récentes.

C'est une idée stupide! L'assembleur inline est là pour rendre le code plus efficace, et il est utilisé très souvent!
C'est pas fait pour faire du filtrage,

Le if est fait pour prendre tous types de décisions, et le filtrage en fait partie.
c'est donc forcément moins clair. (Et dans la pratique, de beaucoup)

Dans ton exemple, ça ne changeait absolument rien à la clarté.
> Tu chipotes, là! Certes non.

Si!
Sûrement pas! Parce qu'en C, il faut encore déclarer et donner sa valeur à la variable a, qui est nichée quelque part dans le motif...

J'ai simplifié, évidemment. En pratique, on mettra: if (x->a>0), où x est le nom de la variable du type dont on parle. Ou peut-être if (x->motif1.a>0) si a peut avoir des types différents selon le motif choisi (auquel cas on le rentre dans l'union).
Il n'y a pas de type union dans ce motif.

Ça se traduirait quand-même par une union en C.
Ben si.
Feuille ou Noeud(a,b)

Mais il n'y a pas de condition de style when a>0, donc le compilateur doit mettre un ID lui-même.
Bon alors c'est une manie consistant à virer du langage tout ce qui est inutile sauf pour les râleurs

Je ne suis pas un râleur, je suis quelqu'un qui pense à la pratique et pas seulement à la théorie.
avatar
Mes news pour calculatrices TI: Ti-Gen
Mes projets PC pour calculatrices TI: TIGCC, CalcForge (CalcForgeLP, Emu-TIGCC)
Mes chans IRC: #tigcc et #inspired sur irc.freequest.net (UTF-8)

Liberté, Égalité, Fraternité

104

Mais ce sont toutes des "applications" trop petites pour que des effets comme la "garbage collection" se produisent de manière mesurable. Voilà pourquoi c'est un mauvais bench.

J'en ai déjà parlé dans un post précédent. Il n'y a pas de biais en ce qui concerne les GC : il suffit de voir les quantités de mémoire consommée pour s'en convaincre.
Tu ne peux pas dire ça de manière certaine. La différence est en plein dans la marge d'erreur.

Non non, elle n'est pas du tout dans la marge d'erreur.
Mais bon je veux bien corriger : « La différence est grosso modo du simple au double. » smile
Et les timers utilisés par les systèmes d'exploitation n'ont en général pas cette résolution. Par exemple, le timer de Windows s'incrémente par étapes d'un 18ème de seconde environ.

« My current shootout host is a dual 450Mhz Pentium-II server with 1GB of RAM and 4x9GB SCSI disks. »
Il me paraît très douteux qu'il s'agisse d'un windows.
Si le code avait été conforme à la norme POSIX,

Mais les codes ne sont en général (malheureusement) pas conformes à la norme posix. c'est comme ça.
Et d'ailleurs, un autre exemple: le nouveau linker de TIGCC a écrit dès le départ pour être portable. Résultat: bien qu'il ait été développé sous Windows, il était compilable sans aucun changement sous Linux dès le départ.

Il a été écrit dès le départ pour être portable.
Mais si on ne fait pas cet effort, il y a quand même du boulot (parfois beaucoup de boulot) pour porter un programme. Ce n'est pas le cas en Caml.
Ben, alors c'est leur choix de ne pas développer de manière portable. Ce n'est pas la faute du C.

Bien sûr que si.
C'est à cause du revolver que le bonhomme est mort => il faut interdire les revolver.
Mais il y a aussi les 68k, les Z80, les AVR, les 68HC11, ... Le C tourne sur tous ces processeurs.

Et bien je laisse sans complexe le C tourner tranquillement et invaincu sur ces processeurs qui n'intéressent pas Caml (trop vieux).
Le code est certainement lourd par rapport à du C codé directement.

C'est bien pour ça que je dis que c'est saugrenu. Celà dit, je n'ai jamais regardé le résultat et il n'est pas certain que le code soit si lourd.
En effet, le C est bien plus adapté pour ces machines. Donc c'est un langage plus universel, donc meilleur.

Non, puisqu'il est beaucoup moins adapté pour les machines plus modernes.
Le C est donc un langage vieux, tout simplement.
Ah, donc le type peut être n'importe quoi. Et pourtant, tu me disais que toutes les variables étaient typées en CAML...

Ben oui.
C'est ce qu'on appelle du typage polymorphe, et c'est une notion totalement inconnue du C.
Si une fonction ne "descend" pas jusqu'au bout de la structure d'un objet, le type reste générique ('a, 'b, ...)

Par exemple, la fonction function x -> x accepte n'importe quel argument.

Mais attention, ça ne veut pas dire du tout que le type est n'importe quoi. Par exemple, une fonction de type 'a -> 'a -> truc ne peut pas accepter un entier en premier argument et un flottant en second, il y aurait une erreur de type. En revanche, une fonction 'a -> 'b -> truc le peut.

De même, si f est une fonction 'a -> 'a -> truc, alors la fonction partielle f 1 sera typée int -> truc.
((Ben(oui))(elles(sont(une(bonne(chose))(pour(la(lisibilité)))))))! (Si((tout(le(monde)))(écrivait(comme(ça))))(il((y)aurait((bien)(moins(de(malentendus))(au(monde)))))))! (On(saurait(toujours)((à(quoi))((se)rapporte(une(proposition(relative)))))(par(exemple)))).

rotflsick
Pas si leur nombre reste petit.

oui
Une bonne raison est que c'est la convention utilisée par pratiquement tous les mathématiciens du monde.

Bah, tu sais bien que les notations mathématiques et informatiques sont vaguement incompatibles. En C tu peux écrire x=x+1 si ça te chante (oui, je sais, += )
Personnellement, j'ai commencé par le BASIC, et maintenant, je suis un des meilleurs programmeurs sur ce forum.

Si tu avais commencé par Caml, tu serais aussi un des meilleurs programmeurs, mais tu serais moins fanatique smile
C'est une idée stupide! L'assembleur inline est là pour rendre le code plus efficace, et il est utilisé très souvent!

C'était à moitié un troll, encore que, finalement, je suis effectivement plutôt pour l'interdiction.
C'est bien beau de parler de portabilité au début d'un post, et puis de l'abandonner au milieu.
Le if est fait pour prendre tous types de décisions, et le filtrage en fait partie.

Tant qu'à faire l'assembleur aussi, alorssick
Dans ton exemple, ça ne changeait absolument rien à la clarté.

Justement parce que ce n'était qu'un petit exemple en 2 lignes. Dans un vrai programme, je n'ose même pas imaginer l'horreur.
Si!

Non.
J'ai simplifié, évidemment. En pratique, on mettra: if (x->a>0), où x est le nom de la variable du type dont on parle. Ou peut-être if (x->motif1.a>0) si a peut avoir des types différents selon le motif choisi (auquel cas on le rentre dans l'union).

Mon dieu quelle horreur.
En particulier, le choc des ">" des deux opérateurs différents fait tragiquement mal aux yeux. sans compter la parenthèse qui ne sert strictement à RIEN pour la compréhension.

Beurk.
Mais il n'y a pas de condition de style when a>0, donc le compilateur doit mettre un ID lui-même.

what
Je crois qu'il y a des problèmes de longueur d'onde pour parler de la même chose.
Je ne suis pas un râleur, je suis quelqu'un qui pense à la pratique et pas seulement à la théorie.

Tu penses à tout alors.
Les droits inaliénables du troll :
1) le droit d'avoir raison
2) le droit d'être péremptoire
3) le droit de ne pas lire
4) le droit de ne pas répondre
5) le droit d'être de mauvaise foi
6) Autant pour moi / Faignant / Vivent Tintin et Milou

105

Kevin Kofler
a écrit : Personnellement, j'ai commencé par le BASIC, et maintenant, je suis un des meilleurs programmeurs sur ce forum.
Euh ça va, ne t'enflamme pas trop non plus...
C'est vrai que ce que tu dis n'est sûrement pas faux en plus, mais bon il faut avouer que ce n'est pas très dur te comparer à nous, on est tous des débutants en programmation ou presque (et ceux qui ne sont pas des débutants ne sont pas moins doués que toi, PpHd par exemple).

106

HIPPOPOTAME
a écrit : J'en ai déjà parlé dans un post précédent. Il n'y a pas de biais en ce qui concerne les GC : il suffit de voir les quantités de mémoire consommée pour s'en convaincre.

Il y a quand-même pas mal des programmes qui sont des mini-programmes dont la consommation de mémoire se mesure en KO au pire.
Mais les codes ne sont en général (malheureusement) pas conformes à la norme posix. c'est comme ça.

Ben, dans ce cas, on n'a pas à se plaindre qu'ils ne sont pas portables!
Il a été écrit dès le départ pour être portable. Mais si on ne fait pas cet effort, il y a quand même du boulot (parfois beaucoup de boulot) pour porter un programme. Ce n'est pas le cas en Caml.

Du code spécifique à une plateforme restera toujours du code spécifique à une plateforme. Du code portable restera toujours du code portable. Le langage employé n'y change rien, sauf s'il interdit complètement le code spécifique à une platefome, ce qui restreint les possibilités offertes par le langage.
Bien sûr que si. C'est à cause du revolver que le bonhomme est mort => il faut interdire les revolver.

Pas mal de gens sont morts à cause d'un couteau, donc il faut interdire les couteaux??? Pas mal de gens sont morts à cause d'une voiture, donc il faut interdire les voitures??? Il y a une différence entre un objet conçu exprès pour faire quelque chose de mauvais, et un objet qui peut accidentellement faire quelque chose de mauvais. Le C n'a pas été conçu exprès pour créer des programmes qui ne sont pas portables!
Et bien je laisse sans complexe le C tourner tranquillement et invaincu sur ces processeurs qui n'intéressent pas Caml (trop vieux).

Trop vieux??? Ces processeurs existent toujours et sont toujours produits (souvent sous forme de microcontrôleurs)! Certains microcontrôleurs avec des caractéristiques semblables à celles du Z80 par exemple sont même très récents!
Non, puisqu'il est beaucoup moins adapté pour les machines plus modernes. Le C est donc un langage vieux, tout simplement.

Comme dit dans le paragraphe précédent, il y a aussi des microcontrôleurs récents, et même de "vieux" processeurs comme le 68000 ou le Z80 sont encore produits!
>Pas si leur nombre reste petit.
oui

Sauf qu'on n'a pas l'air d'avoir la même idée de ce qu'est un nombre qui reste petit. grin
Bah, tu sais bien que les notations mathématiques et informatiques sont vaguement incompatibles. En C tu peux écrire x=x+1 si ça te chante (oui, je sais, += )

Ce n'est pas une raison de dévier exprès de la notation mathématique!
Si tu avais commencé par Caml, tu serais aussi un des meilleurs programmeurs, mais tu serais moins fanatique smile

rotfl
Je pense plutôt que je serais un fanatique du CAML comme tu l'es toi. grin
C'était à moitié un troll, encore que, finalement, je suis effectivement plutôt pour l'interdiction. C'est bien beau de parler de portabilité au début d'un post, et puis de l'abandonner au milieu.

Il y a un compromis à faire entre portabilité et efficacité.
>Le if est fait pour prendre tous types de décisions, et le filtrage en fait partie.
Tant qu'à faire l'assembleur aussi, alorssick

Le C est un langage proche de la machine, donc il est normal que des constructions comme if sont utilisés comme des passe-partout.
Justement parce que ce n'était qu'un petit exemple en 2 lignes. Dans un vrai programme, je n'ose même pas imaginer l'horreur.

Moi, je pense que ça passerait très bien, mais faute d'exemple concret, on ne peut pas vraiment argumenter là-dessus.
>>> Tu chipotes, là!
>> Certes non.
> Si Non.

Euh... On ne va pas aller loin sans arguments, donc laissons tomber. smile
Mon dieu quelle horreur. En particulier, le choc des ">" des deux opérateurs différents fait tragiquement mal aux yeux. sans compter la parenthèse qui ne sert strictement à RIEN pour la compréhension.

Bon, on va aider tes yeux:
if (x->a > 0)
C'est mieux là?

Quant aux parenthèses, voilà comment les virer:
#define IF if (
#define THEN ) {
#define ELSE } else {
#define ELSEIF } else if (
#define ENDIF }

Et voilà, maintenant, tu peux avoir des if avec la syntaxe BASIC:
IF x->a > 0 THEN
...
ENDIF
avatar
Mes news pour calculatrices TI: Ti-Gen
Mes projets PC pour calculatrices TI: TIGCC, CalcForge (CalcForgeLP, Emu-TIGCC)
Mes chans IRC: #tigcc et #inspired sur irc.freequest.net (UTF-8)

Liberté, Égalité, Fraternité

107

Il y a quand-même pas mal des programmes qui sont des mini-programmes dont la consommation de mémoire se mesure en KO au pire.

Ces programmes concernent des problèmes où il n'y a pas d'allocation de mémoire (tout sur la pile) donc pas de biais en ce qui concerne les GC.
Ben, dans ce cas, on n'a pas à se plaindre qu'ils ne sont pas portables!

Evidement, qu'on a le droit de s'en plaindre !!
Du code spécifique à une plateforme restera toujours du code spécifique à une plateforme. Du code portable restera toujours du code portable. Le langage employé n'y change rien, sauf s'il interdit complètement le code spécifique à une platefome, ce qui restreint les possibilités offertes par le langage.

Contrairement à ce que tu penses, le langage employé y change beaucoup.smile
Le C n'a pas été conçu exprès pour créer des programmes qui ne sont pas portables!

... hum ...
C'est vrai qu'on peut se poser la question!
Trop vieux??? Ces processeurs existent toujours et sont toujours produits (souvent sous forme de microcontrôleurs)! Certains microcontrôleurs avec des caractéristiques semblables à celles du Z80 par exemple sont même très récents!

Ben oui, et alors?!
Comme dit dans le paragraphe précédent, il y a aussi des microcontrôleurs récents, et même de "vieux" processeurs comme le 68000 ou le Z80 sont encore produits!

Ben oui, et alors?!
Sauf qu'on n'a pas l'air d'avoir la même idée de ce qu'est un nombre qui reste petit.

Ce qui est sûr, c'est que j'ai une notion d'un nombre petit plus petite que toi.
Donc meilleure.
Ce n'est pas une raison de dévier exprès de la notation mathématique!

Alors tu peux noter f(a)+f(b) si ça te dit!
Je pense plutôt que je serais un fanatique du CAML comme tu l'es toi.

Ca serait déjà plus intéressant !!
Il y a un compromis à faire entre portabilité et efficacité.

Mouais....
On dit ça pour se rattraper aux branches...
Le C est un langage proche de la machine,

Donc mauvais. ( (c) Un prof d'informatique )
Moi, je pense que ça passerait très bien, mais faute d'exemple concret, on ne peut pas vraiment argumenter là-dessus.

Non, je crois que c'est très clair : dans un exemple concret on n'utiliserait pas de filtrage. Emuler du filtrage en C donne un code très lourd et difficile à écrire.
Bon, on va aider tes yeux:
if (x->a > 0)
C'est mieux là?

Quant aux parenthèses, voilà comment les virer:
#define IF if (
#define THEN ) {
#define ELSE } else {
#define ELSEIF } else if (
#define ENDIF }
Et voilà, maintenant, tu peux avoir des if avec la syntaxe BASIC:
IF x->a > 0 THEN
... ENDIF

1) Les macros c'est dangereux
2) Les macros qui émulent des petits morceaux de structures c'est DANGEREUX !! (et hideux)
3) J'aime pas les majuscules, et encore moins le basic.
4) le "x->a>0" est toujours aussi moche
5) 5 lignes de déclarations qui ne servent à rien.

Beurk.
Les droits inaliénables du troll :
1) le droit d'avoir raison
2) le droit d'être péremptoire
3) le droit de ne pas lire
4) le droit de ne pas répondre
5) le droit d'être de mauvaise foi
6) Autant pour moi / Faignant / Vivent Tintin et Milou

108

Et ce système a un grand problème: tu peux fixer seulement la valeur du premier argument. Si tu veux fixer la valeur du deuxième argument, ça ne marchera pas. Il serait plus intéressant d'avoir un moyen général de fixer la valeur d'un argument, quelle que soit sa position dans la liste des arguments.

Il y a une solution pour ça : les fonctions à arguments nommés. On les déclare de cette façon :

#let divise ~dividende ~diviseur = dividende / diviseur;; [ça c'est ce que je tape]

val divise : dividende:int -> diviseur:int -> int = <fun> [ça c'est la réponse du "toplevel"]

Ensuite on peut appliquer les arguments dans n'importe quel ordre du moment qu'on précise le label. Ainsi si l'on veut définir f la fonction qui divise par 3 :

#let f = divise ~diviseur: 3;;

val f : dividende:int -> int = <fun>

Ensuite, f n'ayant qu'un argument, il est possible d'omettre le label. Il est d'ailleurs aussi possible d'omettre les labels dans le cas d'une application *complète* de divise avec les arguments dans l'ordre de la déclaration (mais pas dans le cas d'une application partielle bien sûr...)
C'est quoi cette manie de tout mettre dans des modules?

Ça correspond grosso modo aux headers du C... un identifiant ou un type déclaré dans un module n'est pas accessible directement tant qu'on n'a pas ouvert (#open) le module. N'avoir que le strict minimum dans le module ouvert par défaut permet d'éviter au maximum les conflits de noms...
Ben non, ça ne se voit pas d'un premier coup d'œil. D'autant plus qu'une fonction est normalement nettement plus longue que cet exemple trivial.

1) Si on a un doute sur le type d'une fonction (ou de n'importe quoi), de toute façon, on peut balancer la déclaration au "toplevel" qui la parse, l'évalue et renvoie le type du résultat (ainsi que sa valeur si elle est possible à écrire) (Ctrl-Alt-X sous Emacs fait ça).

2) Si la fonction en question est dans une bibliothèque ou dans le code de quelqu'un d'autre, il y a toujours un fichier interface (dont j'ai déjà parlé) où les types sont déclarés (si on ne crée pas soi-même de tel fichier, le compilo en génère un automatiquement). Et normalement ils le sont aussi dans la doc de la bibliothèque !
Ce n'est pas une raison de dévier exprès de la notation mathématique!

Euh, je te ferai remarquer que la notation fléchée après laquelle tu cries tant correspond justement (mis à part la curryfication) à la notation mathématique...
f: int -> float
f : Z -> |R

let g = function x -> x + 1
g : x |-> x + 1

Remarque que le gros problème d'écrire f (a) en caml est que ça a l'air de lever une ambiguïté alors que ça n'est pas le cas. Lorsque des parenthèses sont placées autour d'une expression, elles ont toujours le même sens, qui est que cette expression doit être considérée comme un unique "token" dans l'expression de niveau supérieur. Ainsi, a étant déjà un seul token dans notre cas, les parenthèses ne font strictement rien.

Supposons qu'on ait un doute sur la priorité entre addition et application d'argument par exemple, la bonne façon de lever l'ambiguïté est la suivante :
(f a) + b vs. f (a + b).
f (a) + b est quant à lui strictement équivalent à f a + b...
Il est vrai que du coup on n'utilise pas la notation mathématique habituelle, mais ça tient à la grammaire du langage...
Tout a commencé quand j'étais garde du cardinal...

109

Ah, dans ce cas, ça serait déjà plus clair sous la forme: ( 'a -> ( 'a -> bool ) ) -> ( 'a list -> 'a list )

Ça c'est vrai pour une fonction à 2 arguments.
Mais si elle en prend 15...
tu préfèrerais vraiment :
f : int -> (int -> (int -> (int -> (int -> (int -> (int -> ( int -> (int -> (int -> (int -> (int -> (int -> (int -> (int -> unit))))))))))))))
?
C'est pire que du LISP ! et encore, là les types des arguments sont atomiques, imagine si c'étaient des types fonctionnels...

Au fait, à propos de l'interversion d'arguments de même type, la bonne solution est ici encore les arguments nommés :
let set_cursor ~row ~column = ...
à l'appel de la fonction il suffit de préciser les labels ; ça passe même si les arguments ne sont pas dans l'ordre de la déclaration. Et si on met genre ~x: 3 ~y: 5, évidemment, c'est une erreur de compilation donc on la voit tout de suite...
Tout a commencé quand j'étais garde du cardinal...

110

Euh....... pour en revenir au lisp, g esssayer de porter les sources de l'interpreteur que j'avait trouver, mais j'y arrive pas sad
trop dure pour moi sad
Si qqu'un veut essayer, qu'il me le dise je lui enverrai plusieurs sources (s'il se sent le courage de les recompiler, moi toutes merde joyeusement)
http://membres.lycos.fr/pingooz/
Un cafe et deux sucres

111

HIPPOPOTAME
a écrit : Ces programmes concernent des problèmes où il n'y a pas d'allocation de mémoire (tout sur la pile) donc pas de biais en ce qui concerne les GC.

Justement, c'est ce que je leur reproche. Tu as déjà vu une application réelle qui n'alloue pas de mémoire, toi?
> Ben, dans ce cas, on n'a pas à se plaindre qu'ils ne sont pas portables! Evidement, qu'on a le droit de s'en plaindre !!

Ben non, puisque c'est fait exprès (par le programmeur, le langage n'y est pour rien)!
Contrairement à ce que tu penses, le langage employé y change beaucoup.smile

Ben non. Si tu utilises des fonctions de l'API de la plateforme X, ton programme ne va pas tourner sur la plateforme Y sans modifications quel que soit le langage. (Par exemple, si tu utilises des fonctions de l'API Win32, ton programme ne va pas tourner sous OS X sans modifications quel que soit le langage.) Si tu n'utilises que des fonctions de la librairie standard du langage, ton programme sera portable quel que soit le langage. (Par exemple, si tu n'utilises que des fonctions de la librairie standard C, ton programme C sera portable.)
>Le C n'a pas été conçu exprès pour créer des programmes qui ne sont pas portables!
... hum ... C'est vrai qu'on peut se poser la question!

Pfff...
>Trop vieux??? Ces processeurs existent toujours et sont toujours produits (souvent sous forme de microcontrôleurs)! Certains microcontrôleurs avec des caractéristiques semblables à celles du Z80 par exemple sont même très récents!
Ben oui, et alors?!

>Comme dit dans le paragraphe précédent, il y a aussi des microcontrôleurs récents, et même de "vieux" processeurs comme le 68000 ou le Z80 sont encore produits! Ben oui, et alors?!

Et alors, tu ne peux pas traîter ces processeurs de "trop vieux" et ainsi ignorer leur existence. Ces processeurs te dérangent (parce qu'ils montrent que rien ne remplace un langage de moyen niveau comme le C), donc tu veux t'en débarasser, et c'est pour ça que tu prétends qu'ils sont vieux et dépassés, alors que ce n'est pas du tout le cas.
>Sauf qu'on n'a pas l'air d'avoir la même idée de ce qu'est un nombre qui reste petit.
Ce qui est sûr, c'est que j'ai une notion d'un nombre petit plus petite que toi. Donc meilleure.

rotfl
La différence est que pour moi, le bon nombre est entre une borne inférieure m et une borne supérieure M, alors que pour toi, le bon nombre est le plus proche de 0 possible, et ta borne supérieure est bien en-dessous de ma borne inférieure. Je suis d'accord que le nombre de parenthèses ne doit pas être trop grand, mais je défends aussi la position qu'il ne doit pas être trop petit non plus, et je trouve que ce que toi, tu appelles "pas trop grand" est trop petit.
Alors tu peux noter f(a)+f(b) si ça te dit!

Sauf que le CAML ne traitera pas ça comme ce que ça veut dire (cf. la remarque de timoleon, ainsi que ma réponse plus bas).
>Je pense plutôt que je serais un fanatique du CAML comme tu l'es toi. grin Ca serait déjà plus intéressant !!

rotfl
>Le C est un langage proche de la machine, Donc mauvais. ( (c) Un prof d'informatique )

C'est ce genre de dogmes injustifiés qui m'énerve! Certains professeurs ont l'air de croire que les seuls processeurs au monde sont les processeurs 64 bits à plusieurs GHz. sad Et en plus, même sur un processeur à plusieurs GHz, un programme optimisé sera quand-même meilleur qu'un programme non optimisé!
Non, je crois que c'est très clair : dans un exemple concret on n'utiliserait pas de filtrage. Emuler du filtrage en C donne un code très lourd et difficile à écrire.

C'est une excuse pour ne pas donner un exemple, ça...
On peut très bien faire du filtrage par type en C, et ce n'est pas si lourd que ça. Pour certains trucs (par exemple pour les arbres), on n'a même pas d'autre choix que d'utiliser quelque chose du style.
1) Les macros c'est dangereux

Ces macros-là n'ont rien de dangereux.
2) Les macros qui émulent des petits morceaux de structures c'est DANGEREUX !! (et hideux)

Bon, donne-moi un exemple où une utilisation correcte de la macro donne une mauvaise expansion...
3) J'aime pas les majuscules, et encore moins le basic.

On peut résoudre ce problème très vite:
#define if if ( /* Oui, c'est parfaitement correct! */
#define then ) {
#define else } else { /* Oui, c'est parfaitement correct! */
#define endif }

(Plus de elseif, parce que ça ne marchera plus avec l'expansion de else. sad)
4) le "x->a>0" est toujours aussi moche

Tu peux mettre (*x).a>0 si tu préfères.
5) 5 lignes de déclarations qui ne servent à rien.

Mets-les dans un header commun.
timoleon
a écrit : Ça correspond grosso modo aux headers du C... un identifiant ou un type déclaré dans un module n'est pas accessible directement tant qu'on n'a pas ouvert (#open) le module. N'avoir que le strict minimum dans le module ouvert par défaut permet d'éviter au maximum les conflits de noms...

Moi, je préfère les trucs du style tigcclib.h (et: oui, je trouve que le standard C aurait dû prévoir un header du même style).
1) Si on a un doute sur le type d'une fonction (ou de n'importe quoi), de toute façon, on peut balancer la déclaration au "toplevel" qui la parse, l'évalue et renvoie le type du résultat (ainsi que sa valeur si elle est possible à écrire)

C'est quand-même lourd par rapport à un langage où il suffit de lire la source pour voir le type.
(Ctrl-Alt-X sous Emacs fait ça).

Tout le monde n'utilise pas Emacs! (Raison: C'est trop compliqué à utiliser.)
2) Si la fonction en question est dans une bibliothèque ou dans le code de quelqu'un d'autre, il y a toujours un fichier interface (dont j'ai déjà parlé) où les types sont déclarés (si on ne crée pas soi-même de tel fichier, le compilo en génère un automatiquement). Et normalement ils le sont aussi dans la doc de la bibliothèque !

N'empêche qu'il n'est pas apparent en lisant la source.
let g = function x -> x + 1 g : x |-> x + 1

Sauf qu'en Mathématiques, on précise toujours l'ensemble de départ et l'ensemble d'arrivée.
Remarque que le gros problème d'écrire f (a) en caml est que ça a l'air de lever une ambiguïté alors que ça n'est pas le cas. Lorsque des parenthèses sont placées autour d'une expression, elles ont toujours le même sens, qui est que cette expression doit être considérée comme un unique "token" dans l'expression de niveau supérieur. Ainsi, a étant déjà un seul token dans notre cas, les parenthèses ne font strictement rien.

Supposons qu'on ait un doute sur la priorité entre addition et application d'argument par exemple, la bonne façon de lever l'ambiguïté est la suivante :
(f a) + b vs. f (a + b).
f (a) + b est quant à lui strictement équivalent à f a + b... Il est vrai que du coup on n'utilise pas la notation mathématique habituelle, mais ça tient à la grammaire du langage...

Voilà pourquoi il est une mauvaise chose d'accepter f a. En C, les priorités sont claires: la parenthèse fait partie intégrante d'appel de fonction. La fonction est toujours appliqué à exactement ce qu'il y a entre les parenthèses. C'est beaucoup moins ambigü.
timoleon a écrit :
Ça c'est vrai pour une fonction à 2 arguments.
Mais si elle en prend 15...
tu préfèrerais vraiment :
f : int -> (int -> (int -> (int -> (int -> (int -> (int -> ( int -> (int -> (int -> (int -> (int -> (int -> (int -> (int -> unit))))))))))))))
? C'est pire que du LISP ! et encore, là les types des arguments sont atomiques, imagine si c'étaient des types fonctionnels...

Voilà le grand avantage de la notation prototypée:
unit f(int, int, int, int, int, int, int, int, int, int, int, int, int, int, int);
ou, mieux (grâce à la flexibilité de la notation prototypée qui permet de mettre des noms arbitraires dans le prototype):
unit f(int i1, int i2, int i3, int i4, int i5, int i6, int i7, int i8, int i9, int i10, int i11, int i12, int i13, int i14, int i15);
ce qui permet immédiatement de voir qu'il y a 15 arguments de type int.
avatar
Mes news pour calculatrices TI: Ti-Gen
Mes projets PC pour calculatrices TI: TIGCC, CalcForge (CalcForgeLP, Emu-TIGCC)
Mes chans IRC: #tigcc et #inspired sur irc.freequest.net (UTF-8)

Liberté, Égalité, Fraternité

112

Justement, c'est ce que je leur reproche. Tu as déjà vu une application réelle qui n'alloue pas de mémoire, toi?

Vraiment je ne vois pas ce qui te gênewhat
Que ces routines soient utilisées indépendamment dans un bench ou qu'elles fassent partie d'un programme plus gros, elles n'alloueront pas de mémoire, un point c'est tout. il y a dans le benchs d'autres routines qui elles allouent de la mémoire et pour lesquelles se produisent des GC. Que l'on mette ces routines ensemble ou qu'on les sépare est totalement équivalent, c'est évident.
Ben non, puisque c'est fait exprès (par le programmeur, le langage n'y est pour rien)!

Mais non ce n'est pas fait exprès.
c'est fait par facilité, parce que le langage y incite, voilà tout.
Si tu n'utilises que des fonctions de la librairie standard du langage, ton programme sera portable quel que soit le langage. (Par exemple, si tu n'utilises que des fonctions de la librairie standard C, ton programme C sera portable.)

Oui et non.
Il est impossible de porter tel quel un programme d'un PC sur une Ti.
Et alors, tu ne peux pas traîter ces processeurs de "trop vieux" et ainsi ignorer leur existence. Ces processeurs te dérangent (parce qu'ils montrent que rien ne remplace un langage de moyen niveau comme le C), donc tu veux t'en débarasser, et c'est pour ça que tu prétends qu'ils sont vieux et dépassés, alors que ce n'est pas du tout le cas.

Je ne veux ni m'en débarrasser, ni ne pas en tenir compte. Je veux un langage puissant pour les processeurs puissants. Pour les processeurs moins puissants, je laisse le C, qui est un langage plus vieillot mais qui restera toujours une référence pour les processeurs peu puissants.
La différence est que pour moi, le bon nombre est entre une borne inférieure m et une borne supérieure M, alors que pour toi, le bon nombre est le plus proche de 0 possible, et ta borne supérieure est bien en-dessous de ma borne inférieure. Je suis d'accord que le nombre de parenthèses ne doit pas être trop grand, mais je défends aussi la position qu'il ne doit pas être trop petit non plus, et je trouve que ce que toi, tu appelles "pas trop grand" est trop petit.

Ta position est de mettre un nombre minimum de parenthèses obligatoires.
Ma position est plus pragmatique : je mets le nombre minimum de parenthèses nécessaires pour que l'expression soit lisible.
Sauf que le CAML ne traitera pas ça comme ce que ça veut dire (cf. la remarque de timoleon, ainsi que ma réponse plus bas).

Si!
Pour caml, ce sera équivalent à f a + f b, et l'application de fonction a la priorité maximum. Tu peux donc noter f(a)+f(b), celà satisfera à tes critères esthétiques et ce sera parfaitement juste.

Mais évidemment, après un peu de pratique camélienne, la notation intuitive et naturelle pour bien marquer la priorité est (f a)+(f b).
>Le C est un langage proche de la machine,
Donc mauvais. ( (c) Un prof d'informatique )
C'est ce genre de dogmes injustifiés qui m'énerve!

Le but d'un langage est de rajouter une couche d'abstraction au dessus de la machine physique, pour enrichir le point de vue et faciliter le développement.
Un langage proche de la machine est donc un langage qui est faignant, qui n'atteint pas des buts très élevés de langage.
L'expression « langage de bas niveau » ou « langage de moyen niveau » est aussi à prendre au sens littéral.
Certains professeurs ont l'air de croire que les seuls processeurs au monde sont les processeurs 64 bits à plusieurs GHz.

32 bits, ça suffit pour avoir un Caml équivalent au C smile
Et tu fais un procès d'intention à mon pauvre professeur (que je salue au passage chapo) dont ce n'était pas du tout les opinions.
Et en plus, même sur un processeur à plusieurs GHz, un programme optimisé sera quand-même meilleur qu'un programme non optimisé!

Sur un proc à plusieurs GHz, Caml et C ont à la base des performances égales, et Caml est bien plus pratique pour développer l'algorithmie smile
On peut très bien faire du filtrage par type en C, et ce n'est pas si lourd que ça. Pour certains trucs (par exemple pour les arbres), on n'a même pas d'autre choix que d'utiliser quelque chose du style.

"Quelque chose du style" qui n'en est pas. Si le terme de filtrage existe en Caml et pas en C, il y a une bonne raison.
Ces macros-là n'ont rien de dangereux.

Les macros c'est dangereux.
Bon, donne-moi un exemple où une utilisation correcte de la macro donne une mauvaise expansion...

Je n'ai pas dit que c'était buggué, j'ai dit que c'était dangereux.
Les macros servent à maintenir le programmeur dans l'ignorance de ce qu'il écrit vraiment.
On peut résoudre ce problème très vite: #define if if ( /* Oui, c'est parfaitement correct! */

Beurk!
Ca me désole que ce soit correct!
#define else } else { /* Oui, c'est parfaitement correct! */

Oh my God!
De pire en pire...
#define endif }

J'aime pas les endif.
Mais c'est pas grave, vu ce qui précède.
Tu peux mettre (*x).a>0 si tu préfères.

Pourquoi passmile
La parenthèse est vraiment indispensable? sad
>>> 5) 5 lignes de déclarations qui ne servent à rien.
Mets-les dans un header commun.

Et voilà, encore du boulot en plus pour créer le header, pour l'inclure, et pour gérer le fichier supplémentaire.
Franchement, et en dehors de toute critique sur le langage lui même, la compilation du C, c'est vraiment *lourd*, tétracapillotomique, et il y a sans arrêt des problèmes.
Moi, je préfère les trucs du style tigcclib.h (et: oui, je trouve que le standard C aurait dû prévoir un header du même style).

Pas besoin de header....
C'est quand-même lourd par rapport à un langage où il suffit de lire la source pour voir le type.

Il suffit de lire la source pour voir le type.

Littéralement.

C'est à dire que quand on lit la source et qu'on simule ce que fait la fonction, le type est là. En Caml, connaître le type = comprendre la fonction. C'est une des choses qui rend le langage si simple.
Tout le monde n'utilise pas Emacs! (Raison: C'est trop compliqué à utiliser.)

Chouette!
Une flame Emacs/Vi ?grin
N'empêche qu'il n'est pas apparent en lisant la source.

Pfff t'es vraiment de mauvaise foi.
Bien sûr qu'il est apparentroll
Sauf qu'on mathématique, on précise toujours l'ensemble de départ et l'ensemble d'arrivée.

Justement, Caml est plus efficace que les mathématiques, il donne toujours les ensembles de départ et d'arrivée les plus grands possibles.smile
En C, les priorités sont claires

rotfl
rotfl
Là tu viens de franchir le mur du son!
la parenthèse fait partie intégrante d'appel de fonction.

En Caml la parenthèse est considérée comme inutile, tu peux la mettre si tu veux. dans la pratique, au début, ça fait un style un peu étrange, très léger et vaguement déroutant, puis une fois adopté, on ne s'en passe plus : ça rend les sources très claires, avec un grand autodafe de parenthèsesdevil.
La fonction est toujours appliqué à exactement ce qu'il y a entre les parenthèses. C'est beaucoup moins ambigü.

La fonction est appliquée exactement à l'objet qui suit. Il n' a aucune ambiguité.
Voilà le grand avantage de la notation prototypée:

Voyons donc le grand avantage de la notation prototypée grin
unit f(int i1, int i2, int i3, int i4, int i5, int i6, int i7, int i8, int i9, int i10, int i11, int i12, int i13, int i14, int i15);

=> 133 caractères.
Notation caml :
let f i1 i2 i3 i4 i5 i6 i7 i8 i9 i10 i11 i12 i13 i14 i15 = ...
=> 58 caractères.
Victoire par KO pour Camltop
Les droits inaliénables du troll :
1) le droit d'avoir raison
2) le droit d'être péremptoire
3) le droit de ne pas lire
4) le droit de ne pas répondre
5) le droit d'être de mauvaise foi
6) Autant pour moi / Faignant / Vivent Tintin et Milou

113

HIPPOPOTAME a écrit :
Vraiment je ne vois pas ce qui te gênewhat Que ces routines soient utilisées indépendamment dans un bench ou qu'elles fassent partie d'un programme plus gros, elles n'alloueront pas de mémoire, un point c'est tout. il y a dans le benchs d'autres routines qui elles allouent de la mémoire et pour lesquelles se produisent des GC. Que l'on mette ces routines ensemble ou qu'on les sépare est totalement équivalent, c'est évident.

Pour les routines qui n'allouent pas de mémoire du tout, oui, mais entre plusieurs petits programmes qui allouent chacun un peu de mémoire et un gros programme qui alloue beaucoup de mémoire, il y a une grosse différence en ce que concerne la GC!
>Ben non, puisque c'est fait exprès (par le programmeur, le langage n'y est pour rien)!
Mais non ce n'est pas fait exprès. c'est fait par facilité,

Donc exprès. La paresse d'un programmeur fait partie de sa volonté.
parce que le langage y incite, voilà tout.

Le langage n'y incite pas du tout. C'est la quantité d'APIs système différents qui y incite, et ça n'a aucun rapport avec le langage.
Oui et non. Il est impossible de porter tel quel un programme d'un PC sur une Ti.

C'est parce que TIGCCLIB n'est pas une librairie 100% standard. Il faudra qu'on travaille un peu sur la compatibilité ANSI (par exemple permettre l'utilisation d'un int main(int argc, char **argv)).
Je ne veux ni m'en débarrasser, ni ne pas en tenir compte. Je veux un langage puissant pour les processeurs puissants. Pour les processeurs moins puissants, je laisse le C, qui est un langage plus vieillot mais qui restera toujours une référence pour les processeurs peu puissants.

Le C reste une référence pour tous les processeurs. Voilà pourquoi c'est toujours le langage de référence.
Ta position est de mettre un nombre minimum de parenthèses obligatoires. Ma position est plus pragmatique : je mets le nombre minimum de parenthèses nécessaires pour que l'expression soit lisible.

Pour moi, tu n'utilises pas assez de parenthèses pour que ce soit lisible!
Si!
Pour caml, ce sera équivalent à f a + f b, et l'application de fonction a la priorité maximum.

Ah, heureusement.
Tu peux donc noter f(a)+f(b), celà satisfera à tes critères esthétiques et ce sera parfaitement juste.

N'empêche qu'il vaudrait mieux que le ( soit attaché directement au f de par la grammaire du langage. Ça serait plus logique.
Mais évidemment, après un peu de pratique camélienne, la notation intuitive et naturelle pour bien marquer la priorité est (f a)+(f b).

Et c'est exactement ce que je reproche.
Le but d'un langage est de rajouter une couche d'abstraction au dessus de la machine physique, pour enrichir le point de vue et faciliter le développement. Un langage proche de la machine est donc un langage qui est faignant, qui n'atteint pas des buts très élevés de langage.

Le but d'un langage de programmation est de permettre au programmeur de commander la machine en un langage plus lisible et plus naturel que le langage machine, et d'être portable au plus grand nombre de machines possible, et tout cela en perdant le moins possible en efficacité. La couche d'abstraction n'est pas un but, c'est juste un moyen de parvenir aux buts de lisibilité et de portabilité. Mais la couche d'abstraction doit être la plus mince possible pour perdre le moins possible en efficacité. Le C est donc le meilleur compromis: il y a juste l'abstraction nécessaire pour que le code soit lisible et portable, pas plus. Toute autre abstraction ne sert à rien d'autre qu'à la paresse du programmeur.
L'expression « langage de bas niveau » ou « langage de moyen niveau » est aussi à prendre au sens littéral.

rotfl
Et tu fais un procès d'intention à mon pauvre professeur (que je salue au passage chapo) dont ce n'était pas du tout les opinions.

Ah bon, c'est pourtant ce qu'on avait l'air de comprendre en te lisant... Désolé alors. smile
Mais toi, tu as bien l'air de penser que les seuls processeurs au monde sont les processeurs 64 bits à plusieurs GHz...
Sur un proc à plusieurs GHz, Caml et C ont à la base des performances égales,

NON! Le C a des performances meilleures! Et cela même d'après ton bench qui ne tient pas vraiment compte de la GC, vu la petite taille des programmes!
"Quelque chose du style" qui n'en est pas. Si le terme de filtrage existe en Caml et pas en C, il y a une bonne raison.

Le terme n'existe pas parce que ce n'est pas une fonctionnalité du langage C lui-même. Ça ne veut pas dire qu'un programme ne peut pas l'utiliser.
Les macros c'est dangereux.

C'est une généralisation injustifiée.
Je n'ai pas dit que c'était buggué, j'ai dit que c'était dangereux.

C'est la même chose.
Les macros servent à maintenir le programmeur dans l'ignorance de ce qu'il écrit vraiment.

Où est le problème? Tant que ça ne bogue pas, il n'y en a aucun!
Beurk!
Ca me désole que ce soit correct!

Oh my God! De pire en pire...

Règle simple: http://tigcc.ticalc.org/doc/cpp.html#SEC27.
J'aime pas les endif.

Tu veux quoi alors? Que le langage devine où finit ton bloc if??? Il faut bien mettre quelque chose: }, endif, ...
>Tu peux mettre (*x).a>0 si tu préfères.
Pourquoi passmile
La parenthèse est vraiment indispensable? sad

Oui, sinon ça sera interprété comme *(x.a) (probablement parce qu'il y a déjà l'autre notation pour désigner (*x).a).
Et voilà, encore du boulot en plus pour créer le header, pour l'inclure, et pour gérer le fichier supplémentaire.

Pour l'inclure, tu mets -include header.h dans la ligne de commande. Tu peux même définir toutes les macros dans la ligne de commande.
Franchement, et en dehors de toute critique sur le langage lui même, la compilation du C, c'est vraiment *lourd*, tétracapillotomique, et il y a sans arrêt des problèmes.

Exemple de problèmes?
Il suffit de lire la source pour voir le type.

Littéralement.
C'est à dire que quand on lit la source et qu'on simule ce que fait la fonction, le type est là.

Donc il ne suffit pas de lire la source, il faut en plus l'analyser! C'est très différent, et ça prend nettement plus de temps!
En Caml, connaître le type = comprendre la fonction. C'est une des choses qui rend le langage si simple.

Ça ne le rend pas simple, ça le rend illisible.
Chouette!
Une flame Emacs/Vi ?grin

Pas du tout! Vi n'est en rien mieux que Emacs! Il est lui aussi trop compliqué à utiliser.
>N'empêche qu'il n'est pas apparent en lisant la source.
Pfff t'es vraiment de mauvaise foi.
Bien sûr qu'il est apparentroll

Non, il n'est pas apparent. (Rappel: Définition: apparent = qui apparaît.) Le type n'apparaît nulle part dans la source vu qu'il est implicit.
Justement, Caml est plus efficace que les mathématiques, il donne toujours les ensembles de départ et d'arrivée les plus grands possibles.smile

rotfl
Comment oses-tu critiquer les Mathématiques!?!
>En C, les priorités sont claires
rotfl
rotfl Là tu viens de franchir le mur du son!

J'aurais dû préciser "... dans ce cas". grin Il est vrai que les priorités sont parfois inattendues. C'est pourquoi il faut toujours mettre des parenthèses pour plus de lisibilité. Mais il y a toujours des priorités qui peuvent surprendre dans un langage de programmation, ce n'est pas une spécificité du C.
En Caml la parenthèse est considérée comme inutile, tu peux la mettre si tu veux. dans la pratique, au début, ça fait un style un peu étrange, très léger et vaguement déroutant, puis une fois adopté, on ne s'en passe plus : ça rend les sources très claires, avec un grand autodafe de parenthèsesdevil.

Ça rend les sources très dépendantes de l'ordre des priorités, et donc on risque beaucoup d'avoir de mauvaises surprises si on ne s'attendait pas à la priorité choisie par le compilateur (c'est-à-dire par le standard du langage si on admet que le compilateur fait ce qu'il est censé faire).
La fonction est appliquée exactement à l'objet qui suit. Il n' a aucune ambiguité.

Oui, mais c'est quand-même moins logique. Cf. plus haut.
Voyons donc le grand avantage de la notation prototypée grin

=> 133 caractères.
Notation caml :
let f i1 i2 i3 i4 i5 i6 i7 i8 i9 i10 i11 i12 i13 i14 i15 = ...
=> 58 caractères.
Victoire par KO pour Camltop

NON! Ces 133-58=75 caractères donnent des informations indispensables pour comprendre la source dès le départ (sans passer son temps à l'analyser): les types des arguments et de la valeur de retour. Et ne me dis pas que le fait que les noms commencent par i indique le type: ça, ça marche pour des types comme int (et encore, rien ne dit que les variables ne sont pas d'un autre type qui commence par "i"), mais pour un type plus compliqué, ça ne tient plus debout (ça mène à la notation hongroise, qui est une des manières les plus rapides de créer des noms de variable illisibles).
avatar
Mes news pour calculatrices TI: Ti-Gen
Mes projets PC pour calculatrices TI: TIGCC, CalcForge (CalcForgeLP, Emu-TIGCC)
Mes chans IRC: #tigcc et #inspired sur irc.freequest.net (UTF-8)

Liberté, Égalité, Fraternité

114

Pour les routines qui n'allouent pas de mémoire du tout, oui, mais entre plusieurs petits programmes qui allouent chacun un peu de mémoire et un gros programme qui alloue beaucoup de mémoire, il y a une grosse différence en ce que concerne la GC!

Pas du tout.
Si tu réfléchis bien, le temps de GC est strictement proportionnel à la mémoire allouée.
C'est parce que TIGCCLIB n'est pas une librairie 100% standard. Il faudra qu'on travaille un peu sur la compatibilité ANSI (par exemple permettre l'utilisation d'un int main(int argc, char **argv)).

Voilà.
Rien n'est jamais 100% standard en C, d'où les problèmes de portabilité.
Le C reste une référence pour tous les processeurs. Voilà pourquoi c'est toujours le langage de référence.

C'était LE langage de référence à l'époque où aucun langage non impératif, fondé sur une abstraction, n'avait de performances honnêtes.
Aujourd'hui, avec l'arrivée des langages fonctionnels à la Caml, c'est UN langage de référence.
Pour moi, tu n'utilises pas assez de parenthèses pour que ce soit lisible!

Parce que tu as des problèmes de lecture.
N'empêche qu'il vaudrait mieux que le ( soit attaché directement au f de par la grammaire du langage. Ça serait plus logique.

Non, il ne « vaudrait mieux » pas.roll
Et c'est exactement ce que je reproche.

Parce que tu as l'esprit fermé.
Le but d'un langage de programmation est de permettre au programmeur de commander la machine en un langage plus lisible et plus naturel que le langage machine, et d'être portable au plus grand nombre de machines possible, et tout cela en perdant le moins possible en efficacité. La couche d'abstraction n'est pas un but, c'est juste un moyen de parvenir aux buts de lisibilité et de portabilité. Mais la couche d'abstraction doit être la plus mince possible pour perdre le moins possible en efficacité. Le C est donc le meilleur compromis: il y a juste l'abstraction nécessaire pour que le code soit lisible et portable, pas plus.

"Mais la couche d'abstraction doit être la plus mince possible pour perdre le moins possible en efficacité." => L'abstraction est plus forte en Caml qu'en C, et Caml a les mêmes performances que le C. A mon avis c'est ça qui te dérange : tu fais un blocage pour l'admettre.

"Le C est donc le meilleur compromis:" => Le Caml est donc le meilleur compromis!

"pour que le code soit lisible et portable" => Le code est plus lisible et plus portable en Caml.
Ah bon, c'est pourtant ce qu'on avait l'air de comprendre en te lisant... Désolé alors. Mais toi, tu as bien l'air de penser que les seuls processeurs au monde sont les processeurs 64 bits à plusieurs GHz...

Mais non.
Mais on est bien obligé de faire un tri parmi les microprocesseurs. On ne va pas programmer un 8086 de la même manière qu'un athlon. Le progrès en programmation nous pousse à inventer des choses spécifiques aux processeurs les plus puissants (sinon le multitache, les interfaces graphiques, etc... n'auraient jamais vu le jour).
Ici, en l'occurence, Caml est plus intéressant que le C sur un bon processeur, si on fait le compte des performances et de l'abstraction.
NON! Le C a des performances meilleures!

sick
Mais oui mais c'est bien sûr.
Le terme n'existe pas parce que ce n'est pas une fonctionnalité du langage C lui-même. Ça ne veut pas dire qu'un programme ne peut pas l'utiliser.

Et dans la pratique, les programmes ne l'utilisent pas, ils ne marchent pas comme ça.
Autant programmer objet en assembleur...
C'est une généralisation injustifiée.

C'est un fait.
>>> Je n'ai pas dit que c'était buggué, j'ai dit que c'était dangereux.
C'est la même chose.

what
Bien sûr que non, ce n'est pas la même chose!
Où est le problème? Tant que ça ne bogue pas, il n'y en a aucun!

Moi je suis un humaniste, je n'aime pas maintenir le programmeur dans l'ignorance.

Plus sérieusement c'est dangereux et tu le sais bien, même si tu ne voudras pas l'admettre. Il n'y a pas de différence syntaxique entre une macro et une fonction, par exemple, et c'est une source inépuisable de problèmes insolubles, dont les effets de bord sont les plus flagrants.
Règle simple: http://tigcc.ticalc.org/doc/cpp.html#SEC27.

Le fait qu'il existe une ou deux règles pour gérer ce bordel ne change rien : c'est terriblement porc, et c'est affligeant que le C accepte ça.
Tu veux quoi alors? Que le langage devine où finit ton bloc if??? Il faut bien mettre quelque chose: }, endif, ...

bah non, en Caml il n'y a besoin de rien...
Oui, sinon ça sera interprété comme *(x.a) (probablement parce qu'il y a déjà l'autre notation pour désigner (*x).a).

Pfouuuu.....
Mais alors, pourquoi tu écris l'autre avec des parenthèses?
Pour l'inclure, tu mets -include header.h dans la ligne de commande. Tu peux même définir toutes les macros dans la ligne de commande.

C'est aussi long dans la ligne de commande que dans le fichier.
Exemple de problèmes?

Le C est une usine à gaz ingérable...
Voilà ce qu'écrit Pingoo au post 109 :
Euh....... pour en revenir au lisp, g esssayer de porter les sources de l'interpreteur que j'avait trouver, mais j'y arrive pas
trop dure pour moi Si qqu'un veut essayer, qu'il me le dise je lui enverrai plusieurs sources (s'il se sent le courage de les recompiler, moi toutes merde joyeusement)

Donc il ne suffit pas de lire la source, il faut en plus l'analyser! C'est très différent, et ça prend nettement plus de temps!

triso !
« lire une source », ce n'est pas « passer l'oeil au dessus de la source » !!
C'est parser!

Et le type saute aux yeux de manière automatique.
Ça ne le rend pas simple, ça le rend illisible.

« Il est plus facile de briser un atome que de briser une conviction. »
Albert Einstein
tsss
Non, il n'est pas apparent. (Rappel: Définition: apparent = qui apparaît.)

Ben oui, justement!
Comment oses-tu critiquer les Mathématiques!?!

Je ne critique pas les mathématiques, au contraire. Caml est d'ailleurs bâti sur un paradigme mathématique ou logique plus puissant que le C.
Il est vrai que les priorités sont parfois inattendues. C'est pourquoi il faut toujours mettre des parenthèses pour plus de lisibilité.

Voilà.
C pousse à mettre des parenthèses qui ne devraient pas être utiles...
Mais il y a toujours des priorités qui peuvent surprendre dans un langage de programmation, ce n'est pas une spécificité du C.

...alors que les priorités de Caml sont plus cohérentes, et nécessitent moins de parenthèses.
Ça rend les sources très dépendantes de l'ordre des priorités,

Bof! Je ne crois pas.
et donc on risque beaucoup d'avoir de mauvaises surprises si on ne s'attendait pas à la priorité choisie par le compilateur

On n'a jamais de mauvaise surprise.
(c'est-à-dire par le standard du langage si on admet que le compilateur fait ce qu'il est censé faire).

Le compilateur est 200% conforme à la grammaire et aux standards du langage.
Ce qui n'est pas vraiment le cas du C...
Oui, mais c'est quand-même moins logique. Cf. plus haut.

Au contraire, c'est plus logique.
C'est la même notation qu'en lambda-calcul.
Les droits inaliénables du troll :
1) le droit d'avoir raison
2) le droit d'être péremptoire
3) le droit de ne pas lire
4) le droit de ne pas répondre
5) le droit d'être de mauvaise foi
6) Autant pour moi / Faignant / Vivent Tintin et Milou

115

[nosmile]
N'avoir que le strict minimum dans le module ouvert par défaut permet d'éviter au maximum les conflits de noms...

Moi, je préfère les trucs du style tigcclib.h (et: oui, je trouve que le standard C aurait dû prévoir un header du même style).

Moui... en fait mon analogie n'était pas très exacte, ça correspond plutôt aux "packages" du java qu'aux headers du C (sauf qu'il n'y a pas cette syntaxe débile avec 15 millions de préfixes : il n'y en a qu'un). C'est à dire que même si on n'a pas ouvert le module on peut accéder à son contenu avec la notation préfixée. Du coup il y a (volontairement) plein de fonctions qui ont le même nom dans des modules différents, par exemple Array.sort et List.sort. Si l'on ne manipule que des listes, on peut ouvrir le module List et utiliser simplement "sort" (si besoin, la fonction de tri sur les vecteurs reste accessible en tant que Array.sort, bien entendu).
Au fait, je me suis planté plus haut dans la syntaxe, ce n'est pas #open mais open tout court (j'ai confondu avec #load...)
Tout le monde n'utilise pas Emacs! (Raison: C'est trop compliqué à utiliser.)

Ça n'était bien sûr qu'un exemple...
Tu veux quoi alors? Que le langage devine où finit ton bloc if??? Il faut bien mettre quelque chose: }, endif, ...

Ben, non... y a pas plus de endif en Caml qu'en C. En C on a la syntaxe :
if (<expr>) <statement> [else <statement>]
en caml on a :
if <expr> then <expr> [else <expr>]
D'ailleurs une meilleure analogie du if de caml serait le <expr> ? <expr> : <expr> du C, qui n'a pas lui non plus de marqueur de fin de bloc...
Et ne me dis pas que le fait que les noms commencent par i indique le type

Ben, non, mais ce n'est pas un exemple très réaliste... dans du vrai code, on donne en principe des noms un peu plus explicites que ça aux paramètres ! surtout quand il y en a beaucoup. Et au nom de la fonction aussi. Et c'est BEAUCOUP plus important pour la lisibilité que de préciser les types...
effectivement, si l'on écrit let f a b c d e g h i j k l m n = ...
c'est un peu moins clair que void *f (char *a, int b, FILE *c ...
et encore pas tellement, parce que même avec les types va-t'en deviner ce que fait f si y a pas de commentaire !
mais imagine let ouvre_fichier nom_fichier nom_répertoire = ...
sans même la suite du code on se doute que ça prend comme arguments deux chaînes de caractères et que ça renvoie un fichier (et la suite le confirmera)
Tout a commencé quand j'étais garde du cardinal...

116

Bon, je ne suis pas spécialiste du C/C++, mais j'ai beaucoup pratiqué le Java (et je ne connais pas du tout le CALM).
Mon point de vue sur la question :
Le C/C++ est très souple... trop souple. La commande goto devrait être supprimée depuis longtemps, c'est une aberration. C'est paratique, mais contraire à du développement clair, stable etc.
La gestion des chaînes de caractères est désuette (pour ne pas dire chiatique)... je ne trouve pas normal qu'à la base on n'ai pas accès à ce type même s'il s'agit d'un type composé.
La gestion des pointeurs est puissante, certe, mais terriblement difficile à apprehender pour le débutant. J'ai moi même arreté de développer en C à cause de ça. KK, tu pourras très bien dire que je n'avais pas beaucoup de courage, c'est peut-être vrai, mais je ne trouve pas normal de complexifier les choses pour le plaisir (cette complexité en rajoute d'ailleurs encore plus lorsqu'on veut implémenter soit-même ses propres routines de gestion des chaînes de caractères).
Je ne parlerais pas du Calm que je ne connais pas, sauf que je suis quand même un adepte des parentheses... mais s'il les accepte aussi, alors...
Pour le Java, c'est un projet très interessant au départ, mais qui, par sa puissance, est devenu très lourd. Le fait de ne parler qu'en objets est très bien, mais bon, avoir à taper 30 lignes de codes pour un simple Hello world, c'est pas très cool. En plus ce langage, qui devait être portable pour toutes plateformes, commence à avoir les mêmes problèmes que le C : des librairies propriétaires mono-plateformes, des instances deprecated en trop grand nombre d'une version à l'autre... enfin, bon voilà, quoi.
Pour ma part, (par facilité aussi, j'avoue) je préfère travailler en Pascal (ou en Prolog, c'est très sympa comme langage, ça oblige à adopter une autre façon de développer qu'on peut ensuite réutiliser dans ses algos dans les autres langages). Le principal avantage du Pascal, c'est qu'il est vraiment proche de la prehension de l'algo. Enfin, après, tous les goûts sont dans la nature.
avatar

117

HIPPOPOTAME a écrit :
Pas du tout. Si tu réfléchis bien, le temps de GC est strictement proportionnel à la mémoire allouée.

Pas du tout. Plusieurs petits programmes qui allouent chacun très peu de mémoire = le treshold de GC sera rarement ou jamais dépassé = il y aura pas ou très peu de GC. Un gros programme qui alloue beaucoup de mémoire = le treshold sera dépassé à plusieurs reprises = il y aura beaucoup de GC. C'est l'existance du treshold (de la borne inférieure en dessous de laquelle il n'y a pas de GC) qui fait qu'il n'y a pas proportionnalité.
Voilà. Rien n'est jamais 100% standard en C, d'où les problèmes de portabilité.

TIGCC est un cas bien particulier. C'est ce qui s'appelle une implémentation "freestanding", mais on fait notre possible pour offrir une implémentation "hosted" la plus complète possible. Mais elle n'est pas compatible à 100% avec le standard ISO pour les implémentations "hosted". Ce n'est pas la faute du standard C. C'est avant tout la faute de TI qui n'offre pas une librairie C complète; nous, on fait notre possible pour être le plus compatible possible avec la librairie C standard.
C'était LE langage de référence à l'époque où aucun langage non impératif, fondé sur une abstraction, n'avait de performances honnêtes. Aujourd'hui, avec l'arrivée des langages fonctionnels à la Caml, c'est UN langage de référence.

Rien ne remplace le C! Et même si quelque chose remplaçait le C, ça serait le C++ ou peut-être le Java, mais certainement pas le CAML.
Parce que tu as des problèmes de lecture.

Sans commentaire. bang
Non, il ne « vaudrait mieux » pas.roll

Si, il vaudrait mieux, ça éviterait des considérations de type "la notation la plus naturelle est (f a)+(f b)". Quelle horreur! f(a)+f(b) est nettement plus naturel. En lisant (f a)+(f b), on dirait presque du LISP. (f a b c) est de la syntaxe LISP (notation polonaise préfixée et entourée de parenthèses)!
>Et c'est exactement ce que je reproche. Parce que tu as l'esprit fermé.

Sans commentaire. bang
"Mais la couche d'abstraction doit être la plus mince possible pour perdre le moins possible en efficacité." => L'abstraction est plus forte en Caml qu'en C, et Caml a les mêmes performances que le C.

Arrête de mentir! CAML n'a pas les mêmes performances que le C!!! Dans le bench, il est plus lent et il consomme nettement plus de mémoire. Et j'ai déjà montré pourquoi ça sera encore pire pour des programmes réels.
A mon avis c'est ça qui te dérange : tu fais un blocage pour l'admettre.

Non, c'est toi qui es d'extrêmement mauvaise foi à continuer de renier le fait que GCC bat Ocaml en vitesse et en consommation de mémoire (en temps d'exécution), alors que le bench que toi, tu m'as indiqué, montre le contraire!

Et d'ailleurs, je trouve que le bench que tu m'as indiqué néglige un critère important: la taille de l'exécutable. Je suis presque sûr que le C bat nettement le CAML sur ce point. Il y a beaucoup moins d'overhead.
"Le C est donc le meilleur compromis:" => Le Caml est donc le meilleur compromis!

Non. Un langage trop abstrait dégrade les performances.
"pour que le code soit lisible et portable" => Le code est plus lisible et plus portable en Caml.

Non, il est tout aussi portable, et je trouve que le C est plus lisible.
Mais non.
Mais on est bien obligé de faire un tri parmi les microprocesseurs. On ne va pas programmer un 8086 de la même manière qu'un athlon. Le progrès en programmation nous pousse à inventer des choses spécifiques aux processeurs les plus puissants (sinon le multitache, les interfaces graphiques, etc... n'auraient jamais vu le jour). Ici, en l'occurence, Caml est plus intéressant que le C sur un bon processeur, si on fait le compte des performances et de l'abstraction.

L'erreur est justement de faire le compte de l'abstraction. L'abstraction n'est pas un but, c'est juste un moyen d'obtenir de la lisibilité et de la portabilité. Le C est déjà très lisible et très portable, donc ce n'est pas la peine d'aller plus loin en abstraction. Et je ne vois pas du tout pourquoi on ne programmerait pas un Athlon de la même manière qu'un 8086. Ça donnerait des programmes bien plus efficaces que le bloatware qu'on voit de nos jours.
>NON! Le C a des performances meilleures!
sick Mais oui mais c'est bien sûr.

Arrête de nier les faits!
>C'est une généralisation injustifiée. C'est un fait.

Le fait que tu ne saches pas distinguer entre une généralisation injustifiée et un fait est très inquiétant!
what Bien sûr que non, ce n'est pas la même chose!

Si. Si ça marche correctement, ce n'est pas dangereux.
Moi je suis un humaniste, je n'aime pas maintenir le programmeur dans l'ignorance.

grin
Plus sérieusement c'est dangereux et tu le sais bien, même si tu ne voudras pas l'admettre. Il n'y a pas de différence syntaxique entre une macro et une fonction, par exemple, et c'est une source inépuisable de problèmes insolubles, dont les effets de bord sont les plus flagrants.

Ce ne sont pas du tout des problèmes insolubles! Pour le problème d'effets de bord, il suffit d'écrire des macros protégés contre les effets de bord:
http://tigcc.ticalc.org/doc/gnuexts.html#SEC63
Le fait qu'il existe une ou deux règles pour gérer ce bordel ne change rien : c'est terriblement porc, et c'est affligeant que le C accepte ça.

Ce n'est pas "terriblement porc", c'est souvent très pratique, et de toute façon, toute autre définition n'aurait pas de sens, donc ce n'est pas ambigü, et il n'y a donc aucune raison pratique de ne pas l'accepter.
bah non, en Caml il n'y a besoin de rien...

Et il fait comment pour repérer la fin d'un bloc if...then...else? Magie noire? grin
>Oui, sinon ça sera interprété comme *(x.a) (probablement parce qu'il y a déjà l'autre notation pour désigner (*x).a).
Pfouuuu..... Mais alors, pourquoi tu écris l'autre avec des parenthèses?

confus
Je signale que le "oui" veut dire: "oui, les parenthèses sont nécessaires"! Il faut mettre (*x).a. *x.a veut dire *(x.a). Mais je mets toujours les parenthèses pour que ce soit clair.
C'est aussi long dans la ligne de commande que dans le fichier.

Non, il y a 2 caractères en moins ("" ou <>). grin
Le C est une usine à gaz ingérable...
Voilà ce qu'écrit Pingoo au post 109 :
>Euh....... pour en revenir au lisp, g esssayer de porter les sources de l'interpreteur que j'avait trouver, mais j'y arrive pas
>trop dure pour moi >Si qqu'un veut essayer, qu'il me le dise je lui enverrai plusieurs sources (s'il se sent le courage de les recompiler, moi toutes merde joyeusement)

1. C'est parce que'il essaye de porter ça vers les TI-89/92+/V200, pas vers une plateforme avec une librairie C complète et de la mémoire suffisante pour faire tourner un gros programme.
2. Il dit bien que c'est lui qui n'y arrive pas, pas que c'est trop dur dans l'absolu.
triso ! « lire une source », ce n'est pas « passer l'oeil au dessus de la source » !!

Si. Lire, c'est lire. Analyser, c'est analyser.
C'est parser!

Ben non.
Et le type saute aux yeux de manière automatique.

Carrément pas. Il faut commencer à lire la fonction en entier pour pouvoir (avec pas mal de travail et un peu de chance) déchiffrer les types. En C, il suffit de lire la première ligne de la fonction pour avoir tous les types, sans avoir à analyser quoi que ce soit.
>Non, il n'est pas apparent. (Rappel: Définition: apparent = qui apparaît.) Ben oui, justement!

Ben non. Il n'apparaît pas. Un type qui apparaît, c'est un type qui est marqué explicitement. Sinon, il n'apparaît pas, il est implicit.
Je ne critique pas les mathématiques, au contraire.

Si, parce que tu dis que "Caml est plus efficace que les mathématiques".
Caml est d'ailleurs bâti sur un paradigme mathématique ou logique plus puissant que le C.

Thèse de Church-Turing: le lambda-calcul (de Church) est strictement équivalent à la machine de Turing. En d'autres mots, les langages fonctionnels sont strictement équivalents en expressivité aux langages impératifs. Aucun contre-exemple connu. Donc ce n'est pas un "paradigme mathématique ou logique plus puissant".
Voilà. C pousse à mettre des parenthèses qui ne devraient pas être utiles...

Non, c'est le souci de clarté et de non-ambigüité qui y pousse.
...alors que les priorités de Caml sont plus cohérentes, et nécessitent moins de parenthèses.

Il y a forcément des priorités qui peuvent surprendre.
On n'a jamais de mauvaise surprise.

Désolé, mais je ne te crois pas, là. Rien que par le fait qu'on vient d'un autre langage de programmation où les priorités sont différentes de manière subtile, on peut être surpris par les priorités d'un langage (même si ce dernier n'y est pour rien).
Le compilateur est 200% conforme à la grammaire et aux standards du langage.

rotfl 200% conforme rotfl
Ce qui n'est pas vraiment le cas du C...

As-tu déjà essayé gcc -ansi -pedantic?
Au contraire, c'est plus logique. C'est la même notation qu'en lambda-calcul.

Mais la notation utilisée dans pratiquement tout le reste des Mathématiques est plus courante, donc son emploi serait nettement plus logique.
avatar
Mes news pour calculatrices TI: Ti-Gen
Mes projets PC pour calculatrices TI: TIGCC, CalcForge (CalcForgeLP, Emu-TIGCC)
Mes chans IRC: #tigcc et #inspired sur irc.freequest.net (UTF-8)

Liberté, Égalité, Fraternité

118

timoleon
a écrit : Au fait, je me suis planté plus haut dans la syntaxe, ce n'est pas #open mais open tout court (j'ai confondu avec #load...)

Vive la cohérence. grin

[cite]Ben, non... y a pas plus de endif en Caml qu'en C. En C on a la syntaxe :
if (<expr>) <statement> [else <statement>]
en caml on a :
if <expr> then <expr> [else <expr>]
D'ailleurs une meilleure analogie du if de caml serait le <expr> ? <expr> : <expr> du C, qui n'a pas lui non plus de marqueur de fin de bloc...[/cie]
Et si on veut mettre plusieurs instructions, on fait quoi? On ne peut pas? Parce que sinon, il faudra bien marquer le début et la fin des "expressions".
mais imagine let ouvre_fichier nom_fichier nom_répertoire = ... sans même la suite du code on se doute que ça prend comme arguments deux chaînes de caractères et que ça renvoie un fichier (et la suite le confirmera)

Alors là, carrément, rien ne me dit que la fonction renvoie un fichier, voire-même qu'elle renvoie quelque chose. Elle pourrait stocker le fichier dans une variable globale, et ne rien renvoyer ou renvoyer un booléen (succès/échec). Et les noms de variable commençant par "nom_" suggèrent que ce sont des chaînes de caractères, mais ça ne sera pas toujours aussi simple. FILE *ouvre_fichier(const char *nom_fichier, const char *nom_repertoire) est nettement plus clair.
avatar
Mes news pour calculatrices TI: Ti-Gen
Mes projets PC pour calculatrices TI: TIGCC, CalcForge (CalcForgeLP, Emu-TIGCC)
Mes chans IRC: #tigcc et #inspired sur irc.freequest.net (UTF-8)

Liberté, Égalité, Fraternité

119

Nil
a écrit : Le C/C++ est très souple... trop souple.

En quoi être souple est-ce une mauvaise chose??? Plus un langage est souple, mieux c'est!
La commande goto devrait être supprimée depuis longtemps, c'est une aberration. C'est paratique, mais contraire à du développement clair, stable etc.

1. Tu avoues toi-même que c'est pratique, ce qui est une excellente raison de le garder (et de l'utiliser).
2. S'il est utilisé correctement, goto peut mèner à du code plus clair qu'une boucle. Les boucles mises juste pour émuler un goto sont tout sauf du code clair. Et le pire, ce sont les "variables de contrôle" qui sont souvent nécessaires si on ne veut pas utiliser de goto. Du code clair sélectionne la prochaine instruction à exécuter en y sautant explicitement, pas en mettant des variables à 1 ou à 0 et en les testant la ligne d'après.
3. Je ne vois pas du tout, mais alors vraiment pas du tout, le rapport entre l'utilisation ou pas de goto et la stabilité ou l'instabilité.
La gestion des chaînes de caractères est désuette (pour ne pas dire chiatique)... je ne trouve pas normal qu'à la base on n'ai pas accès à ce type même s'il s'agit d'un type composé.

La gestion des chaînes de caractères se base sur ce qu'elles sont vraiment: des chaînes (tableaux) de caractères.
La gestion des pointeurs est puissante, certe, mais terriblement difficile à apprehender pour le débutant. J'ai moi même arreté de développer en C à cause de ça.

Bon, évidemment, si tu n'as pas compris les pointeurs, c'est normal que tu as des problèmes avec les chaînes de caractères. roll Les pointeurs font partie des bases du C. Si tu n'arrive pas à comprendre les pointeurs en restant en C seul (même si tu es un des rares qui n'y arrivent pas - ce n'est pas si dur que ça), apprends un minimum d'assembleur. Tu verras:
* qu'un pointeur correspond exactement à une adresse
* que x=*y; correspond exactement à move (ay),dx
* que *x=y; correspond exactement à move dy,(ax)
* que x=*(y++); correspond exactement à move (ay)+,dx
etc.
KK, tu pourras très bien dire que je n'avais pas beaucoup de courage, c'est peut-être vrai, mais je ne trouve pas normal de complexifier les choses pour le plaisir (cette complexité en rajoute d'ailleurs encore plus lorsqu'on veut implémenter soit-même ses propres routines de gestion des chaînes de caractères).

Le C ne complexifie pas du tout les choses. C'est ton ignorance de la structure de la machine et du langage assembleur qui te fait croire ça. C'est plus complexe que le BASIC, mais ça, c'est parce que le BASIC simplifie les choses pour toi (ce qui mène à des programmes leeeeents).
avatar
Mes news pour calculatrices TI: Ti-Gen
Mes projets PC pour calculatrices TI: TIGCC, CalcForge (CalcForgeLP, Emu-TIGCC)
Mes chans IRC: #tigcc et #inspired sur irc.freequest.net (UTF-8)

Liberté, Égalité, Fraternité

120

Un Goto peut casser une boucle + "correcte" et ainsi te foutre une merde pas possible dans tes variables.
Quand je dis que les gotos sont pratiques, je ne parle pas pour moi, je n'en utilise jamais (absolument, je n'ai pas un seul programme Pascal ou C avec un goto).
Je sais ce qu'est un pointeur... je sais ce qu'est un pointeur en C, mais je trouve que la représentation des pointeurs en pascal est plus facile à apprehender. Un code C devient très vite illisible (c'est marrant comme les codeurs C ont la fâcheuse habitude de ne pas commenter, ou de commenter en Franglais ou en Français des banlieues). Un code Pascal peut aussi devenir illisible, mais (à mon sens) beaucoup moins (bon, c'est vrai, un programma Prolog devient illisible en moins de 5 secondes).
Ah, et puis petite note... Je n'ai plus touché plus au basic depuis loooooongtemps, donc bon, le fait que le C soit plus complexe que le basic n'y est pas pour grand chose.
Il est vrai que je n'ai pas une connaissance approfondie du HW PC, mais j'ai fait du 8086 (je ne suis pas un spécialiste, c'est vrai) et du 6809.
De toutes façons, le C étant un langage quasi "universel" - plus que le C++ -(compilos disponibles sur la majorité des plateformes, programmation des PICS en C...), je ne pense pas qu'il disparaisse avant longtemps.
avatar