|
Publicité ' | ||||||||||||||||||||||||
|
|
#1 |
|
Membre éprouvé
![]() |
Est-ce que l'existance des pointeurs de fonction en C en fait un language fonctionnel ?
Si non, je serai curieux de savoir pourquoi. |
|
|
00
|
|
|
#2 |
|
Membre Expert
![]() Inscription : avril 2007 Messages : 829 ![]() |
Il n'y pas de définition stricte et formelle de ce qu'est un "langage fonctionnel". Il y a des outils utiles pour faire de la programmation fonctionnelle, mais souvent c'est aussi une convention "sociale", les langages dans lequel le style fonctionnel est encouragé.
Un critère objectif est le fait d'avoir ce qu'on appelle des "fonctions d'ordre supérieur". Un langage a les fonctions d'ordre supérieur quand les fonctions sont des valeurs à part entière du langage, c'est-à-dire qu'elles peuvent être reçues en arguments, renvoyées comme valeur de retour, et construites à tout moment de l'évaluation. Les pointeurs de fonctions en C, à ma connaissance, ne remplissent pas tout à fait ce cahier des charges : on peut passer et renvoyer des adresses de fonctions existantes, mais ces fonctions sont créées "statiquement" dans le programme et ne peuvent pas être générées dynamiquement pendant l'exécution. Peut-être que les extensions pour les fonctions imbriquées et les fermetures/closures répondent à ce besoin, je ne sais pas. On peut se passer de la nécessité de créer des fonctions dynamiquement en appliquant des transformations globales aux programmes qui "rendent statiques" toutes les fonctions (closure conversion, défonctionalisation...). C'est ce que font souvent les compilateurs de langages fonctionnels. Si tu as un programme utilisant des fonctions d'ordre-supérieur en tête, tu peux donc en écrire une forme transformée en C. Mais ce n'est pas satisfaisant car cette transformation globale rend le code moins maintenable et modulaire (une transformation qui était seulement locale dans le langage fonctionnel imaginaire peut te demander des modifications à de nombreux endroits dans un code C traduit). |
|
|
10
|
|
|
#3 |
|
Membre éprouvé
![]() |
Mais d'aprés wikipédia, une fonction d'ordre supérieur c'est plus simple que ça :
Il suffit qu'une fonction soit capable de prendre comme paramétre une autre fonction ou bien d'en retourner une. Et ça grace au pointeur de fonction le C en est capable. Mais effectivement on peut pas générer dynamiquement une fonction en C.* *J'ai pour le moment pratiquement rien écrit dans un language fonctionnel, et j'arrive pas du tout à concevoir comment on peut générer dynamiquement une fonction ^^ Vivement que j'en connaisse un peu plus. |
|
|
00
|
|
|
#4 | ||
|
Membre Expert
![]() Inscription : avril 2007 Messages : 829 ![]() |
Tu as raison, j'ai fait une légère confusion de langage : prendre et retourner c'est "ordre supérieur" et "manipuler comme toute autre valeur" (donc ça comprend aussi la création) c'est "fonctions de première classe" (plus généralement "X de première classe" quand X est une valeur comme les autres; on peut par exemple considérer les références OCaml comme des "lvalues de première classe").
Au sujet de la création dynamique de fonctions : quand on fait de la programmation fonctionnelle on passe son temps à construire des fonctions. Par exemple, comment traduirais-tu en C le programme OCaml suivant ? L'important n'est pas ici ce qu'il fait (il calcule 1 + 2 + 3, facile), mais comment il le fait, en utilisant des fonctions. Code :
|
||
|
|
00
|
|
|
#5 | |||
|
Membre éprouvé
![]() |
Citation:
J'essaye de comprendre exactement comment il le fait pour essayer de refaire la même chose en C mais je vois pas |
|||
|
|
00
|
|
|
#6 | |
|
Expert Confirmé Sénior
![]() Développeur informatique Inscription : novembre 2006 Messages : 4 445 ![]() |
Citation:
Cela n'est pas possible le langage C est un langage compilé qui donne au final du code machine |
|
|
|
00
|
|
|
#7 |
|
Membre Expert
![]() Inscription : avril 2007 Messages : 829 ![]() |
Le langage OCaml, dans lequel j'ai donné cet exemple, est aussi compilé vers du code machine. Le compilateur ne fait pas du JIT pour les déclarations de fonction (compiler le code de la fonction pendant l'exécution), ce serait bien trop coûteux: il utilise des techniques de traduction pour éliminer les fonctions "dynamiques" (les fonctions, anonymes ou non, qui ne sont pas au toplevel).
Ubiquité : tu ne comprends pas le sens du code ((fun x -> foo) est une fonction anonyme qui renvoie (foo) quand on lui donne la valeur de (x)), ou tu ne comprends pas comment il est exécuté ? Syntaxiquement le code a le comportement suivant : let f = compose (ajoute 1) (ajoute 2) in f 3 => let f = compose (fun b -> 1 + b) (fun c -> 2 + c) in f 3 => let f = fun x -> (fun b -> 1 + b) ((fun c -> 2 + c) x) in f 3 => (fun x -> (fun b -> 1 + b) ((fun c -> 2 + c) x)) 3 => (fun b -> 1 + b) ((fun c -> 2 + c) 3) => (fun b -> 1 + b) (2 + 3) => (fun b -> 1 + b) 5 => 1 + 5 => 6 |
|
|
00
|
|
|
#8 | |
|
Membre éprouvé
![]() |
Citation:
in f 3 ca veut dire quoi ? |
|
|
|
00
|
|
|
#9 | ||
|
Membre Expert
![]() Inscription : avril 2007 Messages : 829 ![]() |
"let x = a in b" c'est la forme des déclarations locale en Caml, ça veut dire "déclare la variable x comme ayant la valeur de a, et évalue b (qui peut utiliser x)".
Tu connais un autre langage fonctionnel (ou un autre langage qui a au moins des fonctions de première classe) dans lequel je pourrais fournir l'exemple ? En Javascript: Code :
|
||
|
|
00
|
|
|
#10 | ||
|
Membre éprouvé
![]() |
Je galere pour faire ca en C mais en C++ avec les foncteurs ca doit être bien plus faisable.
Déjà la fonction addition pen C++ peut être un foncteur comme celui là : Code :
|
||
|
|
00
|
|
|
#11 | ||||||||||
|
Membre chevronné
![]() Inscription : mars 2010 Messages : 281 ![]() |
C et C++ dans leur version actuelle ne sont pas du tout des "langages fonctionnels" parce qu'ils ne permettent pas de capture de variable lors de la définition des fonctions (c'est ça qui permet de "créer dynamiquement" des fonctions, appelées aussi "fermetures").
Prenons un exemple de ce que permettrait la capture en C (en fait, de ce qu'elle permet, grace à l'extension "block" d'apple) Code :
Code :
En développant un peu cet exemple (et sans avoir testé), supposons que la fonction main deviennent Code :
Code :
Et attention, ici tous les paramètres sont connus, mais il n'y a pas deux fonctions créées lors de la compilation. On pourrait très bien imaginer un tableau de fonctions Code :
Tout ça est impossible à faire en C standard (on peut "tricher" en créant une structure contenant le pointeur de fonction et le tableau de ses variables capturées, puis avoir une macro d'application qui rajoute le tableau comme premier argument, ce que fait sans doute l'implémentation, mais ce n'est pas la même chose !). Ce sera possible en C++0x avec les "lambdas" J'espère que ça aide avec une syntaxe moins "caml" |
||||||||||
|
|
00
|
|
|
#12 |
|
Membre éprouvé
![]() |
Donc finalement avoir des fonctions d'ordre supérieur ne suffit pas ? Les fonctions d'un langage doivent être un objet de première classe pour que le langage implement le paradigme fonctionnel ?
Et t'es sur que les foncteurs du c++ ne permettent pas la capture ? |
|
|
00
|
|
|
#13 |
![]() ![]() Inscription : juin 2002 Messages : 2 034 ![]() |
|
|
|
00
|
|
|
#14 | |
|
Membre Expert
![]() Inscription : avril 2007 Messages : 829 ![]() |
Citation:
Si tu n'arrives pas à implémenter mon exemple dans un langage de programmation (en utilisant des fonctions), il peut difficilement se prétendre un langage fonctionnel. |
|
|
|
00
|
|
|
#15 |
|
Membre éprouvé
![]() |
Oki,
Merci pour toutes les précisions. Quand je reviendrai je serai surement entrain de lire Real World Haskell. |
|
|
00
|
|
|
#16 |
|
Membre Expert
![]() Inscription : mars 2002 Messages : 962 ![]() |
Pour info, les fonctions anonymes arrivent avec C++0x (et on choisit à chaque fois si la capture se fait par copie ou par référence).
|
|
|
00
|
|
|
#17 |
|
Membre régulier
![]() Inscription : septembre 2007 Messages : 99 ![]() |
Tous les langages savent manier les fonctions (sauf JAVA qui a décider de suivre la voie 100% objet)
Ce qui fait réellement un langage fonctionnel, c'est l'application partielle. Dès que l'on a cette fonctionnalité on peut coder en fonctionnel, quand on ne l'a pas on ne peut pas coder en fonctionnel. Et dans ce domaine le C est un incapable. Ce n'est donc pas un langage fonctionnel. |
|
|
01
|
|
|
#18 |
|
Membre Expert
![]() Inscription : avril 2007 Messages : 829 ![]() |
NokyDaOne > pardon ? L'assembleur "gère les fonctions" ? Comment ? Mais il ne "gère" pas l'application partielle ? Qu'est-ce que c'est ?
Ça ne veut pas dire grand chose ce que tu dis... |
|
|
00
|
|
|
#19 | |
|
Membre régulier
![]() Inscription : septembre 2007 Messages : 99 ![]() |
Citation:
Si, ce que je dis veut dire quelque-chose |
|
|
|
00
|
|
|
#20 | |
![]() ![]() ![]() Nicolas ValléeIngénieur d'études Inscription : décembre 2005 Messages : 9 963 ![]() |
Citation:
euh c'est extrêmement réducteur... tu en arrives presque à dire que C = assembleur en terme de fonctionnalités ![]() je sais bien que les aficionados français des langages fonctionnels sont plus proches de la famille ML, mais il ne faudrait tout de même pas dire que la famille Algol (et son représentant le plus représenté aujourd'hui : C) est limitée à l'assembleur... |
|
|
|
00
|
Copyright © 2000-2013 - www.developpez.com