1)

Voici une fonction python summation, qui peut effectuer la somme des cubes / carrés / .., opérations similaires .

def identity(k): return k def cube(k): return pow(k, 3) def square(k): return pow(k,2) def summation(n, term): if n == 0: return 0 else: return term(n) + summation(n-1, term) def sum_cubes(n): return summation(n, cube) if __name__ == "__main__": sum = sum_cubes(4) print(sum) """ In C, We can implement the same using function pointers. Goal is, to perform similar operations(Sum of ..) using single function summation()""" 

2)

Considérez, ci-dessous, le tri des API à partir de C,

void qsort(void *base, size_t nmemb, size_t size, int (*compar)(const void *, const void *)); 

Ici, qsort peut trier les données de tout type , tableau de floats / noms de fichiers dans un répertoire / strings / …


Question:

Comment définir une fonction générique?

summation est-il une fonction générique?

ou

qsort est-il une fonction générique?

ou

À partir de deux exemples, la fonction générique est-elle une terminologie invalide?

div id = « 4ce7c96277 »>

ou toute fonction de tri que je conçois

Commentaires

  • Quelle définition de  » fonction générique  » avez-vous lu que vous ne comprenez pas ‘? Cela vous aiderait si vous publiez cela au lieu décrire un tas de code.
  • Le terme de la théorie des types pour le type de générique où une fonction fonctionne pour tout type sans contrainte et sans connaissance du type spécifique est polymorphisme paramétrique . La fonction didentité est générique de cette manière.
  • Dans certains langages (comme Java)  » fonction générique  » a une définition technique spécifique. Mais ce nest pas le cas en Python, donc la  » fonction générique  » na pas de signification bien définie. Cela ne signifie pas quil sagit dune  » terminologie non valide « , mais simplement que vous devez être conscient du contexte lorsque vous utilisez le terme.
  • @AndresF. Javascrpt utilise également beaucoup cette terminologie de fonction générique . Parce que vous pouvez avoir une fonction qui prend nimporte quel élément html à traiter (exemple – supprimer tous les enfants dun élément html donné)

Answer

Il y a plusieurs significations à » générique « .

Définition informelle

« générique » dans le langage courant quelque chose qui partage des propriétés communes mais qui est moins spécifique à certains égards.

Dans cette perspective, vous pourriez considérer qsort() comme générique: le code de cette fonction est capable de trier toute structure de données de taille fixe pour laquelle vous pouvez définir une fonction de comparaison à laide de lalgorithme QSORT.

La même chose sapplique à votre fonction summation(), qui résume les termes obtenus en utilisant nimporte quelle fonction avec un paramètre.

Définition formelle

Les langages de programmation comme C ++ ou Java permettent une programmation générique avec lutilisation de modèles ou de génériques:

Définition du standard C ++ 14 : Un modèle définit une famille de classes ou de fonctions ou un alias pour une famille de types.

Le principe est que limplémentation dune classe ou dune fonction peut être paramétrée par types.

Selon ce point de vue plus formel, qsort() nest pas une fonction générique. Son implémentation na pas besoin de déterminer de type à la compilation, et son comportement est indépendant du type. La seule chose dont il a besoin est la taille des éléments triés, et cette taille est un argument ordinaire qui est traité au moment de lexécution.

Pour un langage qui nest pas typé statiquement tel que Python , je « ne sais pas quoi répondre pour summation(). Je pense quelle nest pas générique car sa mise en œuvre et son comportement ne dépendent pas du type: cette fonction est juste une fonction dordre supérieur, largument term étant une fonction. Elle nutilise aucune fonctionnalité qui modifierait le comportement de cette fonction en fonction des types.

Pour illustrer une fonction générique, vous pouvez jeter un œil à la fonction standard C ++ std::sort() : son implémentation dépend du type de ses arguments (et éventuellement dune fonction de comparaison avec des arguments dun type déterminé). En utilisant les fonctionnalités des modèles C ++, il peut trier nimporte quel conteneur de nimporte quel type, à condition quil dispose des opérateurs / fonctions membres / traits / itérateurs requis par limplémentation de la fonction générique.

Un langage à typage dynamique peut-il avoir des fonctions génériques

Un langage à typage dynamique nécessite code moins générique que les langages à typage statique.

Par exemple, si vous avez un conteneur dobjets de type dynamique, une fonction qsort pourrait trier le conteneur de manière générique, tant que nimporte quelle combinaison de deux éléments dans le conteneur peut être comparée.

Mais même dans un environnement aussi flexible, une programmation générique – dépendante du type – pourrait être utile. Le cas dutilisation typique est multi-méthodes, où le comportement ou le code dépend du type des arguments ou même de la combinaison de types (comme pour déterminer lintersection entre deux formes différentes). Pour plus dinformations, voir:

Commentaires

  • Je ne sais pas, pourquoi comparons-nous des génériques (principalement utilisé pour éviter la conversion de type en Java & aide à effectuer le polymorphisme) avec définition de fonction générique?
  • @overexchange Je pense que java propose également une programmation générique, y compris des méthodes génériques (voir spécification ou tutoriel ). Néanmoins, jai ‘ légèrement modifié la partie définition pour répondre à votre remarque.
  • Le paquet générique de Python na rien à voir avec les fonctions génériques. Sauf quils partagent le même adjectif.
  • @Killian if programmation générique , concerne lidée dabstraire des algorithmes concrets et efficaces pour obtenir des algorithmes génériques qui peuvent être combinés avec différentes représentations de données , je pense que les multiméthodes de ce package devraient être dans, don ‘ t vous le pensez?

Réponse

Les fonctions génériques prennent le type dau moins un argument de fonction de manière générique au moment de la compilation. Autrement dit, le compilateur découvre quel type est utilisé à un certain endroit et applique exactement ce type là où il est utilisé dans la fonction. Par exemple. si vous avez un argument générique dans votre fonction qui est utilisé avec un opérateur +, le type doit avoir les méthodes appropriées. Pour les chaînes / tableaux, ce serait dans de nombreux cas une concaténation et pour et entier / flottant une addition. Le compilateur peut détecter et appliquer lopération correcte. Votre routine C nest pas générique dans ce sens, car cest le programmeur qui applique certaines informations de taille et non le compilateur détectant le type et utilisant la taille correcte.

Par exemple, dans un langage fictif

func add(p1,p2) { return p1+p2 } print add("a", "b") // yields "ab" print add(1, 2) // yields 3 

Ici, le compilateur détecte dans le premier cas que deux chaînes sont appliquées et développeront en interne quelque chose comme

func add(p1:string, p2:string) 

et traiter le + comme une concaténation tandis que dans le second cas, il se développerait

func add(p1:int, p2:int) 

comme indiqué paramètres entiers. Générique signifie que le compilateur génère du code individuel pendant la compilation. Python, par exemple, nest pas typé et ferait ce genre de substitution pendant lexécution. Signifie: Python na pas de fonctions génériques car tout est en quelque sorte générique.

Commentaires

  • Vous navez pas compris votre idée. Vous voulez dire + est une fonction générique, la syntaxe en C ++?
  • Les arguments de fonction prenant les fonctions sont dordre supérieur fonction s dans le monde Python / JavaScript. En C, nous avons besoin de pointeurs de fonction, pour la même chose.
  • Voir ma modification ci-dessus.
  • Alors, quel type de fonction est summation, Fonction dordre supérieur? et rien de plus?
  • Il y a beaucoup de définitions de ce quest le générique. Stroustrup, par exemple, le définit comme une  » programmation utilisant des types comme paramètres « . Pour la référence wikipedia, je ‘ plutôt aller à: en.wikipedia.org/wiki/Generic_programming

Réponse

Je vais commencer cela du point de vue du C ++, puis progresser vers C.

Dans les langages statiquement typés comme C, C ++, Java, etc., une fonction « générique » vous permet de spécifier les opérations de fonction une fois , en utilisant des espaces réservés pour tous les types qui peuvent varier entre différents appels (ce qui signifie que des fonctions comme qsort et bsearch sont très certainement pas fonctions génériques). Idéalement, vous aimeriez aussi que le compilateur détecte automatiquement tout appel à cette fonction générique et génère le code réel si nécessaire.

C ++ facilite cette opération 1 en offrant des modèles :

template <typename T> T summation( T *values, size_t numValues ) { T result = 0; for ( size_t i = 0; i < numValues; i++ ) result += values[i]; return result; } 

T est un espace réservé pour tout type 2 , vous pouvez donc lappeler comme

int ivals[] = {1,2,3,4,5,6,7,8,9}; double dvals[] = {1,2,3,4,5,6,7,8,9}; int sumi = summation( ivals, 10 ); double sumd = summation( dvals, 10 ); 

Lorsque le code est compilé, le compilateur voit les deux appels à summation et en déduit les types des arguments. Pour chaque type différent, il génère une nouvelle instance de la fonction, lui donnant un nom unique:

int summation_i( int *values, size_t numValues ) // actual compilers will generate { // more complex "mangled" names int result = 0; // than this ... } double summation_d( double *values, size_t numValues ) { double result = 0; ... } 

Il génère ensuite du code de telle sorte que le résultat de summation_i soit attribué à sumi et summation_d est affecté à sumd.

C noffre rien de similaire à la fonctionnalité de modèle. Traditionnellement, nous avons attaqué la programmation générique de deux manières – soit en utilisant des macros, soit en utilisant void * partout et en déléguant des opérations sensibles au type à dautres fonctions.

Voici « un mauvais exemple de solution macro-basée:

#include <stdio.h> #define SUMMATION_DEF(t) \ t summation_##t( t *values, size_t numValues ) \ { \ t result = 0; \ for ( size_t i = 0; i < numValues; i++ ) \ result += values[i]; \ return result; \ } #define SUMMATION(t,x,s) summation_##t(x, s) SUMMATION_DEF(int) SUMMATION_DEF(double) int main( void ) { int ivals[] = {1, 2, 3, 4, 5}; double dvals[] = {1, 2, 3, 4, 5}; int sumi = SUMMATION(int, ivals, 5); double sumd = SUMMATION(double, dvals, 5); printf( "sumi = %d\n", sumi ); printf( "sumd = %f\n", sumd ); return 0; } 

Le SUMMATION_DEF est à peu près similaire à un modèle en ce quil spécifie les opérations de fonction, en utilisant le paramètre de macro t comme espace réservé de type. Nous utilisons également t dans le cadre du nom de la fonction – ## est lopérateur de collage de jetons et le préprocesseur développera t et ajoutez cette valeur au nom de la fonction 3 .

Là où elle diffère du C ++, cest le fait quune macro est juste une substitution de texte stupide. Elle ne déclenche pas toute opération spéciale de la part du compilateur. Les instances de fonction réelles ne sont pas automatiquement générées en fonction des appels de la macro SUMMATION – nous devons générer explicitement les fonctions que nous voulons (doù SUMMATION_DEF(int) et SUMMATION_DEF(double) avant main). Cela signifie également que lorsque nous appelons summation_xxx via la macro SUMMATION, nous devons passer le type dans la liste des arguments de la macro, de sorte que la bonne fonction soit appelée. Quelle douleur.

Le La norme C 2011 a ajouté le mot clé _Generic, ce qui peut rendre la vie un peu plus facile à cet égard:

#include <stdio.h> #define SUMMATION_DEF(t) \ t summation_##t( t *values, size_t numValues ) \ { \ t result = 0; \ for ( size_t i = 0; i < numValues; i++ ) \ result += values[i]; \ return result; \ } #define SUMMATION(x,s) _Generic((x), \ int * : summation_int, \ double * : summation_double \ )(x, s) SUMMATION_DEF(int) SUMMATION_DEF(double) int main( void ) { int ivals[] = {1, 2, 3, 4, 5}; double dvals[] = {1, 2, 3, 4, 5}; int sumi = SUMMATION(ivals, 5); double sumd = SUMMATION(dvals, 5); printf( "sumi = %d\n", sumi ); printf( "sumd = %f\n", sumd ); return 0; } 

Le _Generic le mot-clé vous permet dévaluer des expressions en fonction de types ; ainsi, si le type du premier argument à SUMMATION est int *, nous appelons summation_int; cest « s it » s double *, nous appelons summation_double. De cette façon, nous navons pas à spécifier le nom du type dans les arguments de la macro.

Lautre approche, comme vous « avez vu, est dutiliser void * et de déléguer des opérations de type à dautres fonctions. Comme je lai dit plus haut, » La programmation nest pas vraiment « générique », car vous devez implémenter manuellement chaque fonction de comparaison pour chaque type. Vous ne pouvez pas le coder une seule fois et en finir avec. Et en utilisant void *, vous jetez essentiellement la sécurité de type par la fenêtre et dans le trafic venant en sens inverse.

Et avant que quiconque se plaint – non, aucune de ces fonctions de sommation ne vérifie ou ne traite le débordement arithmétique. Cest un sujet pour un autre jour.


  1. Pour des définitions suffisamment vagues de «facile». Le langage de métaprogrammation utilisé pour prendre en charge les modèles est Turing-complet, vous pouvez donc faire * vraiment incroyable * et impossible de comprendre les choses avec.
  2. Pour des définitions suffisamment vagues de « tout type ». Notez que quel que soit le type que vous utilisez, il doit prendre en charge lopérateur +=, sinon le compilateur vous hurlera dessus.
  3. Ce code sera interrompu pour les types tels que unsigned int ou long double car ils ont des espaces dans le nom. Je ne connais pas immédiatement la solution à ce problème, et jai passé suffisamment de temps sur cette réponse telle quelle est.

Laisser un commentaire

Votre adresse e-mail ne sera pas publiée. Les champs obligatoires sont indiqués avec *