Salut,
C# n'autorise pas la surcharge des opérateurs [] et (), ce qui est très
embêtant quand on vient du C++, comme moi.
J'aimerais avoir la possibilité de créer des foncteurs (ou
classes-fonctions), ainsi que des opérateurs du genre [,].
Comment peut-on contourner le problème ?
Toute piste est bienvenue.
Merci.
Salut,
C# n'autorise pas la surcharge des opérateurs [] et (), ce qui est très
embêtant quand on vient du C++, comme moi.
J'aimerais avoir la possibilité de créer des foncteurs (ou
classes-fonctions), ainsi que des opérateurs du genre [,].
Comment peut-on contourner le problème ?
Toute piste est bienvenue.
Merci.
Salut,
C# n'autorise pas la surcharge des opérateurs [] et (), ce qui est très
embêtant quand on vient du C++, comme moi.
J'aimerais avoir la possibilité de créer des foncteurs (ou
classes-fonctions), ainsi que des opérateurs du genre [,].
Comment peut-on contourner le problème ?
Toute piste est bienvenue.
Merci.
Salut Boris
class BorisList
{
double this[string key,string key2] { get {...} set {...}}
}
par contre, pour le () implicite, oublie ça. le C++ est un dépotoire à
embrouilles en grande partie à cause des casts implicites, c'est pas po ur en
ramener en C#.
ademettons encore qu'ils soient explicit,
pourquoi ne pas écrire simplement une méthode. regarde dans String, tu
trouves ToCharArray...
pour les foncteurs, si tu entends pointeurs de fonction,
Salut Boris
class BorisList
{
double this[string key,string key2] { get {...} set {...}}
}
par contre, pour le () implicite, oublie ça. le C++ est un dépotoire à
embrouilles en grande partie à cause des casts implicites, c'est pas po ur en
ramener en C#.
ademettons encore qu'ils soient explicit,
pourquoi ne pas écrire simplement une méthode. regarde dans String, tu
trouves ToCharArray...
pour les foncteurs, si tu entends pointeurs de fonction,
Salut Boris
class BorisList
{
double this[string key,string key2] { get {...} set {...}}
}
par contre, pour le () implicite, oublie ça. le C++ est un dépotoire à
embrouilles en grande partie à cause des casts implicites, c'est pas po ur en
ramener en C#.
ademettons encore qu'ils soient explicit,
pourquoi ne pas écrire simplement une méthode. regarde dans String, tu
trouves ToCharArray...
pour les foncteurs, si tu entends pointeurs de fonction,
> Cette approche a très nettement ces limites quand tu fait de la
programmation générique à coup de templates ou, de manière plus
limitée, de génériques : Si tu veux manipuler un type "T" inconnu,
c'est beaucoup plus simple et plus naturel d'imposer comme contrainte
que T doit définir un operateur (), où être convertible
(implicitement ou explicitement) dans tel type, plutôt que d'imposer
qu'il ait une méthode "To_TrucChose" ou "Do_CeciOuCela".
chercher une opération
de cast dans un code existant à coup de "Rechercher", c'est infaisable
avec la syntaxe ().
encore trop si ca va ête bénéfique ou pas... De toute façon, comme
les génériques ne permettent pas la spécialisation partielle ou
totale, ce qu'on peut faire avec en manière de programmation
générique est très limité.
Et non! Un foncteur c'est un objet qui se comporte coimme une fonction,
donc qui surcharge (une ou plusieurs fois) l'operateur (). (en plus on
considère souvent que un foncteur doit être copiable, mais c'est unc
concept purement C++ là).
> Cette approche a très nettement ces limites quand tu fait de la
programmation générique à coup de templates ou, de manière plus
limitée, de génériques : Si tu veux manipuler un type "T" inconnu,
c'est beaucoup plus simple et plus naturel d'imposer comme contrainte
que T doit définir un operateur (), où être convertible
(implicitement ou explicitement) dans tel type, plutôt que d'imposer
qu'il ait une méthode "To_TrucChose" ou "Do_CeciOuCela".
chercher une opération
de cast dans un code existant à coup de "Rechercher", c'est infaisable
avec la syntaxe ().
encore trop si ca va ête bénéfique ou pas... De toute façon, comme
les génériques ne permettent pas la spécialisation partielle ou
totale, ce qu'on peut faire avec en manière de programmation
générique est très limité.
Et non! Un foncteur c'est un objet qui se comporte coimme une fonction,
donc qui surcharge (une ou plusieurs fois) l'operateur (). (en plus on
considère souvent que un foncteur doit être copiable, mais c'est unc
concept purement C++ là).
> Cette approche a très nettement ces limites quand tu fait de la
programmation générique à coup de templates ou, de manière plus
limitée, de génériques : Si tu veux manipuler un type "T" inconnu,
c'est beaucoup plus simple et plus naturel d'imposer comme contrainte
que T doit définir un operateur (), où être convertible
(implicitement ou explicitement) dans tel type, plutôt que d'imposer
qu'il ait une méthode "To_TrucChose" ou "Do_CeciOuCela".
chercher une opération
de cast dans un code existant à coup de "Rechercher", c'est infaisable
avec la syntaxe ().
encore trop si ca va ête bénéfique ou pas... De toute façon, comme
les génériques ne permettent pas la spécialisation partielle ou
totale, ce qu'on peut faire avec en manière de programmation
générique est très limité.
Et non! Un foncteur c'est un objet qui se comporte coimme une fonction,
donc qui surcharge (une ou plusieurs fois) l'operateur (). (en plus on
considère souvent que un foncteur doit être copiable, mais c'est unc
concept purement C++ là).
> Cette approche a très nettement ces limites quand tu fait de la
> programmation générique à coup de templates ou, de manière plus
> limitée, de génériques : Si tu veux manipuler un type "T" inconnu,
> c'est beaucoup plus simple et plus naturel d'imposer comme contrainte
> que T doit définir un operateur (), où être convertible
> (implicitement ou explicitement) dans tel type, plutôt que d'imposer
> qu'il ait une méthode "To_TrucChose" ou "Do_CeciOuCela".
hmmm. c'est typique STL ça.
maintenant si on mets un parametre supplémentaire (type ou valeur) qui fait
le boulot, ça revient au même... je crois meme que ça enrichi le tr uc.
bon faut voir...
> encore trop si ca va ête bénéfique ou pas... De toute façon, co mme
> les génériques ne permettent pas la spécialisation partielle ou
> totale, ce qu'on peut faire avec en manière de programmation
> générique est très limité.
disons que la façon d'exprimer les choses est différente.
si on reprend l'eternel exemple de la classe Complex<T>, les operations de
base sur les composantes Re et Im peuvent etre faites par un objet, disons
Algebra.
point de vue type, on découpe un concept autours de ces opérations +- */, et
ça permet de les "séparer" du type manipulé. moi, j'aime bien , c'e st une
bonne propriété...
point de vue efficacité, c'est sur que c'est pas le grand reve ultime p our
l'instant... meme si on gagne du temps sur les algorithmes qui utilisent nos
classes, on aime pas trop avoir ce genre de frein à main levé dans les
briques de base.
> Cette approche a très nettement ces limites quand tu fait de la
> programmation générique à coup de templates ou, de manière plus
> limitée, de génériques : Si tu veux manipuler un type "T" inconnu,
> c'est beaucoup plus simple et plus naturel d'imposer comme contrainte
> que T doit définir un operateur (), où être convertible
> (implicitement ou explicitement) dans tel type, plutôt que d'imposer
> qu'il ait une méthode "To_TrucChose" ou "Do_CeciOuCela".
hmmm. c'est typique STL ça.
maintenant si on mets un parametre supplémentaire (type ou valeur) qui fait
le boulot, ça revient au même... je crois meme que ça enrichi le tr uc.
bon faut voir...
> encore trop si ca va ête bénéfique ou pas... De toute façon, co mme
> les génériques ne permettent pas la spécialisation partielle ou
> totale, ce qu'on peut faire avec en manière de programmation
> générique est très limité.
disons que la façon d'exprimer les choses est différente.
si on reprend l'eternel exemple de la classe Complex<T>, les operations de
base sur les composantes Re et Im peuvent etre faites par un objet, disons
Algebra.
point de vue type, on découpe un concept autours de ces opérations +- */, et
ça permet de les "séparer" du type manipulé. moi, j'aime bien , c'e st une
bonne propriété...
point de vue efficacité, c'est sur que c'est pas le grand reve ultime p our
l'instant... meme si on gagne du temps sur les algorithmes qui utilisent nos
classes, on aime pas trop avoir ce genre de frein à main levé dans les
briques de base.
> Cette approche a très nettement ces limites quand tu fait de la
> programmation générique à coup de templates ou, de manière plus
> limitée, de génériques : Si tu veux manipuler un type "T" inconnu,
> c'est beaucoup plus simple et plus naturel d'imposer comme contrainte
> que T doit définir un operateur (), où être convertible
> (implicitement ou explicitement) dans tel type, plutôt que d'imposer
> qu'il ait une méthode "To_TrucChose" ou "Do_CeciOuCela".
hmmm. c'est typique STL ça.
maintenant si on mets un parametre supplémentaire (type ou valeur) qui fait
le boulot, ça revient au même... je crois meme que ça enrichi le tr uc.
bon faut voir...
> encore trop si ca va ête bénéfique ou pas... De toute façon, co mme
> les génériques ne permettent pas la spécialisation partielle ou
> totale, ce qu'on peut faire avec en manière de programmation
> générique est très limité.
disons que la façon d'exprimer les choses est différente.
si on reprend l'eternel exemple de la classe Complex<T>, les operations de
base sur les composantes Re et Im peuvent etre faites par un objet, disons
Algebra.
point de vue type, on découpe un concept autours de ces opérations +- */, et
ça permet de les "séparer" du type manipulé. moi, j'aime bien , c'e st une
bonne propriété...
point de vue efficacité, c'est sur que c'est pas le grand reve ultime p our
l'instant... meme si on gagne du temps sur les algorithmes qui utilisent nos
classes, on aime pas trop avoir ce genre de frein à main levé dans les
briques de base.
> Euhh... moi pas comprendre là... Tu peux donner un exemple de ce à
L'alternative que tu proposes, c'est quoi?
C'est vrai, c'est propre sur le papier, c'est orienté objet, c'est
proprement typé, et tout et tout.... Maintenant comment tu fais pour
faire un Complex<int> ? Tu modifies int pour qu'il satisfasse le
concept "Algebra"? (pour moi Algebra est un concept, pas un type à
proprement parler).
Il y a certainement des tas de choses à faire avec cette notion de
"concept", mais je n'ai pas encore vu de proposition de syntaxe et
veux supporter "export" c'est-à-dire fournir un template sous forme de
binaire).
> Euhh... moi pas comprendre là... Tu peux donner un exemple de ce à
L'alternative que tu proposes, c'est quoi?
C'est vrai, c'est propre sur le papier, c'est orienté objet, c'est
proprement typé, et tout et tout.... Maintenant comment tu fais pour
faire un Complex<int> ? Tu modifies int pour qu'il satisfasse le
concept "Algebra"? (pour moi Algebra est un concept, pas un type à
proprement parler).
Il y a certainement des tas de choses à faire avec cette notion de
"concept", mais je n'ai pas encore vu de proposition de syntaxe et
veux supporter "export" c'est-à-dire fournir un template sous forme de
binaire).
> Euhh... moi pas comprendre là... Tu peux donner un exemple de ce à
L'alternative que tu proposes, c'est quoi?
C'est vrai, c'est propre sur le papier, c'est orienté objet, c'est
proprement typé, et tout et tout.... Maintenant comment tu fais pour
faire un Complex<int> ? Tu modifies int pour qu'il satisfasse le
concept "Algebra"? (pour moi Algebra est un concept, pas un type à
proprement parler).
Il y a certainement des tas de choses à faire avec cette notion de
"concept", mais je n'ai pas encore vu de proposition de syntaxe et
veux supporter "export" c'est-à-dire fournir un template sous forme de
binaire).
> Euhh... moi pas comprendre là... Tu peux donner un exemple de ce à
quoi tu penses? Typiquement, avec la STL, tu peux avoir:
std::for_each(iterateur_de_debut, itrateur_de_fin, foncteur);
avec foncteur *n'importe quoi* qui définit operator(). Ce n'importe
quoi peut être un pointeur de fonction, un foncteur, etc...
L'alternative que tu proposes, c'est quoi?
> Euhh... moi pas comprendre là... Tu peux donner un exemple de ce à
quoi tu penses? Typiquement, avec la STL, tu peux avoir:
std::for_each(iterateur_de_debut, itrateur_de_fin, foncteur);
avec foncteur *n'importe quoi* qui définit operator(). Ce n'importe
quoi peut être un pointeur de fonction, un foncteur, etc...
L'alternative que tu proposes, c'est quoi?
> Euhh... moi pas comprendre là... Tu peux donner un exemple de ce à
quoi tu penses? Typiquement, avec la STL, tu peux avoir:
std::for_each(iterateur_de_debut, itrateur_de_fin, foncteur);
avec foncteur *n'importe quoi* qui définit operator(). Ce n'importe
quoi peut être un pointeur de fonction, un foncteur, etc...
L'alternative que tu proposes, c'est quoi?
> Euhh... moi pas comprendre là... Tu peux donner un exemple de ce à
[...]
> L'alternative que tu proposes, c'est quoi?
j'ai pas compris ce que tu as dis, alors...
> C'est vrai, c'est propre sur le papier, c'est orienté objet, c'est
> proprement typé, et tout et tout.... Maintenant comment tu fais pour
> faire un Complex<int> ? Tu modifies int pour qu'il satisfasse le
> concept "Algebra"? (pour moi Algebra est un concept, pas un type à
> proprement parler).
pour l'instant, ça devient un type.
> Euhh... moi pas comprendre là... Tu peux donner un exemple de ce à
[...]
> L'alternative que tu proposes, c'est quoi?
j'ai pas compris ce que tu as dis, alors...
> C'est vrai, c'est propre sur le papier, c'est orienté objet, c'est
> proprement typé, et tout et tout.... Maintenant comment tu fais pour
> faire un Complex<int> ? Tu modifies int pour qu'il satisfasse le
> concept "Algebra"? (pour moi Algebra est un concept, pas un type à
> proprement parler).
pour l'instant, ça devient un type.
> Euhh... moi pas comprendre là... Tu peux donner un exemple de ce à
[...]
> L'alternative que tu proposes, c'est quoi?
j'ai pas compris ce que tu as dis, alors...
> C'est vrai, c'est propre sur le papier, c'est orienté objet, c'est
> proprement typé, et tout et tout.... Maintenant comment tu fais pour
> faire un Complex<int> ? Tu modifies int pour qu'il satisfasse le
> concept "Algebra"? (pour moi Algebra est un concept, pas un type à
> proprement parler).
pour l'instant, ça devient un type.
> beaucoup plus naturel dans le code template d'écrire
T& mon_truc_que_je_peux_appeler = ... //initialisé correctment
//....
mon_truc_que_je_peux_appeler();
plutôt que d'écrire
mon_truc_que_je_peux_appeler.DoIt(); //ou un autre nom de fonction.
Entre autres choses, la 1ere version permet que T soit un pointeur de
fonction brut, pas forcément un objet.
Si tu veux une analogie C#, c'est un peu le même principe que pour
rappeler un delegate : on utilise la forme operator() pour appeler le
delegate, quoi que cet "appel" fasse réellement derrière.
pour l'instant, ça devient un type.
<snip tout un tas d'essais tordus>
D'où l'idée de concept, c'est à dire de contrainte que l'on impose
sur un type (genre "il supporte les opérations + et -", "il est
assignable", "il est convertible en bool") mais sans que ces
contraintes soient exprimées sous forme d'héritage.
Au passage, exprimer ces contraintes sous forme d'héritage, c'est
plutôt limite par rapport au principe de substitution de Liskov : dire
qu'un int EST un Algebra, c'est plutot bizarre...
Ne restes donc plus qu'à trouver une syntaxe qui va bien pour exprimer
ces concepts de manière formelle et à la faire implémenter ;-)
> beaucoup plus naturel dans le code template d'écrire
T& mon_truc_que_je_peux_appeler = ... //initialisé correctment
//....
mon_truc_que_je_peux_appeler();
plutôt que d'écrire
mon_truc_que_je_peux_appeler.DoIt(); //ou un autre nom de fonction.
Entre autres choses, la 1ere version permet que T soit un pointeur de
fonction brut, pas forcément un objet.
Si tu veux une analogie C#, c'est un peu le même principe que pour
rappeler un delegate : on utilise la forme operator() pour appeler le
delegate, quoi que cet "appel" fasse réellement derrière.
pour l'instant, ça devient un type.
<snip tout un tas d'essais tordus>
D'où l'idée de concept, c'est à dire de contrainte que l'on impose
sur un type (genre "il supporte les opérations + et -", "il est
assignable", "il est convertible en bool") mais sans que ces
contraintes soient exprimées sous forme d'héritage.
Au passage, exprimer ces contraintes sous forme d'héritage, c'est
plutôt limite par rapport au principe de substitution de Liskov : dire
qu'un int EST un Algebra, c'est plutot bizarre...
Ne restes donc plus qu'à trouver une syntaxe qui va bien pour exprimer
ces concepts de manière formelle et à la faire implémenter ;-)
> beaucoup plus naturel dans le code template d'écrire
T& mon_truc_que_je_peux_appeler = ... //initialisé correctment
//....
mon_truc_que_je_peux_appeler();
plutôt que d'écrire
mon_truc_que_je_peux_appeler.DoIt(); //ou un autre nom de fonction.
Entre autres choses, la 1ere version permet que T soit un pointeur de
fonction brut, pas forcément un objet.
Si tu veux une analogie C#, c'est un peu le même principe que pour
rappeler un delegate : on utilise la forme operator() pour appeler le
delegate, quoi que cet "appel" fasse réellement derrière.
pour l'instant, ça devient un type.
<snip tout un tas d'essais tordus>
D'où l'idée de concept, c'est à dire de contrainte que l'on impose
sur un type (genre "il supporte les opérations + et -", "il est
assignable", "il est convertible en bool") mais sans que ces
contraintes soient exprimées sous forme d'héritage.
Au passage, exprimer ces contraintes sous forme d'héritage, c'est
plutôt limite par rapport au principe de substitution de Liskov : dire
qu'un int EST un Algebra, c'est plutot bizarre...
Ne restes donc plus qu'à trouver une syntaxe qui va bien pour exprimer
ces concepts de manière formelle et à la faire implémenter ;-)