web-dev-qa-db-fra.com

Quel est le fondement mathématique des valeurs de première / deuxième / troisième classe dans les langages de programmation?

Ajoutée

Je viens de trouver deux questions connexes

https://math.stackexchange.com/q/1759680/1281

https://stackoverflow.com/a/2582804/156458


Dans les langages de programmation, de Michael Scott's Programming Language Pragmatics

En général, une valeur dans un langage de programmation est considérée comme ayant un état de première classe si elle peut être transmise en tant que paramètre, renvoyée par un sous-programme, ou assigné dans une variable. Les types simples tels que les entiers et les caractères sont des valeurs de première classe dans la plupart des langages de programmation. En revanche, une valeur de "seconde classe" peut être transmise en tant que paramètre, mais pas renvoyée par un sous-programme ou affectée à une variable, et une valeur de "troisième classe" ne peut même pas être passée en paramètre.

Les étiquettes sont des valeurs de troisième classe dans la plupart des langages de programmation, mais des valeurs de deuxième classe dans ALGOL. Les sous-programmes affichent le plus de variations. Ce sont des valeurs de première classe dans tous les langages de programmation fonctionnels et la plupart des langages de script. Ce sont également des valeurs de première classe en C # et, avec quelques restrictions, dans plusieurs autres langages impératifs, dont Fortran, Modula-2 et -3, Ada 95, C et C++. 11 Ce sont des valeurs de deuxième classe dans la plupart des autres langages impératifs, et des valeurs de troisième classe dans Ada 83.

  1. Quel est le fondement mathématique des valeurs de première/deuxième/troisième classe dans les langages de programmation?

    La terminologie me rappelle la logique du premier/deuxième ordre, mais sont-elles liées?

  2. Il me semble que la différence entre eux est de savoir dans quel cas spécifique une valeur peut être utilisée

    • passé en paramètre,
    • rentré d'un sous-programme, ou
    • assigné dans une variable.

    Pourquoi les cas spécifiques sont-ils importants, alors que les autres cas ne sont pas mentionnés?

Merci.

19
Tim

Il n'y en a pas, et c'est assez arbitraire.

La seule distinction utile est entre la première classe et toutes les autres. Chaque cas qui se trouve dans la fourchette "autre" a son propre ensemble de règles distinct dans chaque cas et les regrouper tous ensemble n'est tout simplement pas très utile. "Première classe" signifie "Vous n'avez pas à chercher les règles", et "autre" est "Vous devez apprendre les règles".

Par exemple, en C++, les fonctions individuelles sont des valeurs de première classe, tant qu'elles sont sans état. Les ensembles de surcharge ne le sont pas mais les lambdas le sont. En C #, les fonctions sont généralement des valeurs de première classe, mais il y a des cas gênants qui surviennent lors de l'inférence de type qui les empêchent d'être dans tous les cas.

45
DeadMG

Je suis d'accord avec DeadMG, la distinction importante est entre la première classe et "tout le reste". Cependant, il existe une manière plus familière de classer la différence.

Les valeurs de première classe sont des données, les autres sont du code. (grosso modo: je suis sûr qu'il y a des exceptions. Mais c'est une très bonne approximation qui vaut pour les langues du monde réel.)

Dans certaines langues, vous pouvez traiter le code comme des données. Les langages fonctionnels sont connus pour cela: certains d'entre eux vous permettent de changer le code du programme pendant son exécution (la base de programmation génétique ).

Les langages tels que C et C++ vous permettent de prendre l'adresse des fonctions: bien que vous ne puissiez pas les modifier, vous pouvez passer des fonctions comme paramètres à d'autres fonctions. C++ a également le sucre syntaxique de foncteurs . L'idée est de créer un objet entier qui, en surface, semble se comporter comme une fonction et peut être transmis comme s'il s'agissait de données. Ce qui est autrement une classe de valeur inférieure peut être traité comme une valeur de première classe.

Mathématiquement, je pense que la meilleure façon est de penser à AST d'un programme. En règle générale, chaque jeton a un type spécifique qui peut être compatible ou non avec d'autres types. Pensez l-value, r-value, et tout le reste des types de valeurs en C++ . Ajoutez ensuite les mots-clés, les symboles qui sont des fonctions, etc. Certains d'entre eux peuvent être des valeurs de première, deuxième ou troisième classe selon la langue.

Je ne suis pas sûr de savoir que la "classe" de valeur est si importante, sauf peut-être dans un environnement académique. Dans le monde réel, la chose importante à savoir est de savoir comment transmettre du code, en le traitant comme des données: foncteurs, lambdas/fermetures, pointeurs de fonction, etc.

11
user22815

Denotational Semantics fournit une base mathématique pour décrire le fonctionnement des valeurs et des variables dans un langage de programmation. Cela a été si bien expliqué dans mon diplôme en informatique que j'ai obtenu une note élevée à l'examen de sémantique dénotationnelle, puis j'ai oublié la plupart et je n'ai jamais eu besoin de l'utiliser dans une vie de 20 ans en tant que programmeur.

Vous pouvez choisir d'utiliser une base mathématique bien définie, ou vous pouvez utiliser une terminologie informelle comme "statut de première classe". J'aurais appris beaucoup plus si le cours était basé sur la pragmatique du langage de programmation de Scott, mais les mathématiques formelles sont nécessaires pour quelqu'un qui va faire un doctorat en conception de langage de programmation.

Si vous lisez les spécifications de la plupart des langages de programmation, vous remarquerez un manque dissident de sémantique dénotationnelle, mais la plupart des langages bien conçus avaient quelqu'un dans l'équipe qui est un expert en conception de langage de programmation, donc comprend bien la sémantique dénotationnelle.

Michearl Scott utilise donc une terminologie informelle qui a une certaine relation avec les mathématiques formelles, tout en présentant le sujet d'une manière dont la plupart des programmeurs peuvent bénéficier. Sa terminologie n'est pas utilisé par d'autres personnes, il n'est donc pas utile pour communiquer, mais il vous donne une bonne base sur les questions que vous devez poser lorsque vous voyez un nouveau langage de programmation pour la première fois.

Notez que Michael L. Scott est un chercheur de premier plan en informatique, donc comprendra et sera très heureux d'utiliser les mathématiques formelles, mais comme les meilleurs chercheurs, il est habile à expliquer l'application de la recherche au reste d'entre nous .

8
Ian

Non, le mot "premier" dans "première classe" et dans "premier ordre" signifie des choses différentes.

Mais oui, les concepts de "première classe" et de "premier ordre" sont liés. Ils visent tous deux à classer les concepts sur lesquels une langue peut décrire la langue.

Un concept est de première classe si les mécanismes d'abstraction habituels d'un langage peuvent faire abstraction de ce concept.

Par exemple, le langage de programmation Java Java peut décrire des nombres entiers, et tous les mécanismes habituels pour abstraire des nombres entiers (les accepter comme paramètres de méthode, les renvoyer comme résultats de fonction, les stocker dans des structures de données, .. .) fonctionne pour les entiers.

Un concept est de premier ordre s'il ne peut pas être utilisé pour s'abstraire sur lui-même.

Par exemple, encore une fois en Java, nous pouvons utiliser des méthodes pour résumer certaines choses. Mais nous ne pouvons pas utiliser de méthodes pour abstraire des méthodes, car un nom de méthode ne peut pas être passé comme paramètre de méthode. Ceci est différent en JavaScript, où vous pouvez utiliser la notation entre crochets pour accéder à une propriété d'un objet par son nom sous forme de chaîne, et vous pouvez résumer sur des chaînes.

Un concept est de second ordre s'il peut être utilisé pour faire abstraction des utilisations de premier ordre de lui-même, mais pas des utilisations de second ordre.

Par exemple, en Java, vous pouvez utiliser des génériques pour abstraire des types (comme dans class Foo<T> { public List<T> content; }). Cependant, vous ne pouvez pas utiliser de génériques pour abstraire des génériques (comme dans class Bar<T> { public T<Int> content; }). C'est différent à Scala.

Un concept est troisième ordre s'il peut être utilisé pour faire abstraction des utilisations de premier ordre et de deuxième ordre de lui-même, mais pas des utilisations de deuxième ordre.

Etc.

Enfin, un concept est d'ordre supérieur s'il peut être utilisé pour abstraire des utilisations arbitraires de lui-même.

Résumé: Si une fonction d'abstraction est de première classe, elle est également d'ordre supérieur. Et si une fonction d'abstraction est de premier ordre, elle ne peut pas être de première classe.

3
Toxaris

Quel est le fondement mathématique des valeurs de première/deuxième/troisième classe dans les langages de programmation?

Aucun que je sache.

La terminologie me rappelle la logique du premier/deuxième ordre, mais sont-elles liées?

Pas vraiment.

La "classe" d'un élément de langage de programmation n'est qu'une manière abrégée de réfléchir à la question quelles choses l'utilisateur de mon langage souhaite-t-il manipuler par programmation? Par exemple, C # vous donne un ensemble riche d'opérations à manipuler valeurs, un ensemble moins riche de façons de manipuler types, et aucune opération qui manipule étiquettes.

Cependant, votre intuition selon laquelle il existe un lien ici n'est pas entièrement déplacée. Il y a une analogie à faire entre la logique du premier ordre et la programmation procédurale, et de la logique d'ordre supérieur à la programmation fonctionnelle. La logique du premier ordre concerne la manipulation logique des valeurs; la programmation procédurale concerne la manipulation programmatique des valeurs. La logique d'ordre supérieur concerne la manipulation logique de déclarations de logique, la programmation fonctionnelle concerne la manipulation programmatique de fonctions.

Pourquoi les cas spécifiques sont-ils importants, alors que les autres cas ne sont pas mentionnés?

Il faudrait demander à l'auteur une réponse définitive.

Je ne serais pas trop accroché à cette notion de "classe". Ce n'est pas une chose formellement définie. C'est un raccourci que les concepteurs de langage utilisent pour parler de ce qui peut être manipulé par programme.

2
Eric Lippert

La "valeur de première classe", dans ce contexte, est une terminologie standard dans la théorie du langage de programmation. Une valeur de première classe est quelque chose qui peut être manipulé comme des valeurs normales dans le langage, quelque chose qui peut être calculé au moment de l'exécution. Bien sûr, c'est une définition tautologique jusqu'à ce que vous ayez défini une sémantique pour le langage, puis une valeur est ce que la sémantique définit comme étant une valeur. Le but du concept est d'identifier ce qui peut être manipulé directement, par opposition à seulement accessible indirectement.

Par exemple, dans presque tous les langages de programmation, les entiers machine d'une taille limitée (par exemple, les entiers 8 bits, ou les entiers 32 bits, ou les entiers 64 bits, etc.) sont des valeurs de première classe. Vous pouvez les stocker dans des variables, les passer et les retourner aux fonctions, etc. Dans la plupart des langages mais pas dans les langages de bas niveau tels que Assembly et C, les chaînes sont des valeurs de première classe - mais en C, elles ne le sont pas, vous seulement obtenir des pointeurs sur les chaînes. En C, les chaînes et les tableaux ne sont pas des valeurs de première classe: par exemple, vous ne pouvez pas passer un tableau à une fonction, vous ne pouvez pas affecter un tableau à une variable de tableau, etc. En C, les fonctions ne sont pas des valeurs de première classe soit: vous ne pouvez pas stocker une fonction dans une variable, seulement un pointeur vers une fonction. En revanche, les chaînes et les fonctions sont des valeurs de première classe dans la plupart des langages de programmation de haut niveau: vous pouvez les stocker dans une chaîne, etc.

Les types sont un exemple d'un concept qui n'est pas de première classe dans de nombreux langages de programmation conçus pour être compilés. Dans un langage comme C ou Java, les types vivent au moment de la compilation, vous ne pouvez pas les manipuler à l'aide de constructions de langage. (Java a également un système de type dynamique basé sur les classes; les classes sont des valeurs de première classe par réflexion.) En revanche, un langage comme Python a une fonction type qui renvoie un valeur qui représente le type de son argument.

La négation de la "valeur de première classe" dans la terminologie standard n'est "pas une valeur de première classe". L'expression "valeur de deuxième classe" n'est pas couramment utilisée et "valeur de troisième classe" encore moins. Ne vous attendez pas à les voir en dehors de ce livre. Il n'y a absolument aucune base pour définir "deuxième" comme "peut être passé en tant que paramètre" et "troisième" comme "ne peut pas être passé en tant que paramètre", il n'y a pas d'échelle de choses qui pourraient être sérieusement numérotées. Très peu de langues font la différence entre les valeurs qui peuvent être transmises en tant que paramètre aux fonctions et les valeurs qui peuvent être affectées aux variables, il n'est donc pas utile de définir un nom pour ce concept.