* N'importe quelle * tâche de programme peut-elle être exprimée sans état?

13

C'est une question théorique, mais après de nombreuses années de programmation dans ce que je réalise maintenant comme une technique impérative "normale", utilisant principalement le C ++, j'ai découvert cet autre monde de programmation fonctionnelle, sur lequel je suis tombé par hasard tout en apprenant avec désinvolture JavaScript.

Cela m'a amené à me demander si vous pouviez techniquement remplacer un programme complet orienté état par une implémentation différente purement fonctionnelle et sans état?

C'est une idée intrigante et je dois admettre qu'il y a une clarté et une élégance dans la programmation fonctionnelle qui m'a vraiment époustouflé.

johnbakers
la source
1
Une réponse StackOverflow pertinente: stackoverflow.com/questions/3722084/…
jfriend00
Qu'il y ait ou non un état qui persiste d'un point dans le temps ne dépend pas du paradigme de programmation que vous utilisez, mais du problème ou de la tâche que vous codez. Si vous comptez le nombre de fois où un bouton est cliqué, alors il y a clairement un état pour enregistrer ce compteur et peu importe la technique de codage que vous utilisez, il devra y avoir un état pour garder une trace du comptage pendant le processus. Ainsi, cette tâche particulière ne peut pas être effectuée sans état en cours de route, peu importe comment vous la codez.
jfriend00
6
Si vous voulez discuter de l'état; un état clair est requis, ne serait-ce que pour le programme lui-même. Il semble que vous pensiez à un état mutable ou immuable - vous souhaiterez peut-être indiquer ce que vous voulez dire dans la question.
Billy ONeal
1
C'est comme demander si tous les programmes peuvent être convertis en véritables machines Turing. Techniquement oui, même les programmes qui enregistrent et chargent à partir d'une base de données, mais il devient plus difficile de simuler ce comportement dans une machine Turing. De même, vous pourriez avoir un programme dont le côté contrôleur dans l'architecture MVC est supprimé et vous effectuez tous les appels, mais là encore, cela devient plus difficile à gérer (vous devenez essentiellement le contrôleur afin de rendre le programme sans état).
Neil

Réponses:

17

Réponse courte: oui. Selon Wikipedia, l'équivalence du calcul lambda aux machines de Turing en tant que modèle universel de calcul a été montrée en 1937 par Alan Turing. Le modèle de calcul d'une machine de Turing est ce que vous avez généralement à l'esprit lorsque vous parlez de programmation impérative ou avec état, et le calcul lambda est une formalisation mathématique de la «programmation fonctionnelle pure».

On suppose que tout modèle de calcul efficace est capable d'effectuer les mêmes calculs qu'une machine de Turing et vice versa. C'est ce qu'on appelle la thèse de Church-Turing . Cette conjection, cependant, ne peut pas être prouvée, en raison du terme plus ou moins intuitif de "modèle efficace de calcul" (peut-être que quelqu'un inventera un nouveau modèle à l'avenir?)

Doc Brown
la source
2
Votre même argument peut être inversé en disant qu'étant un calcul lamba équivalent à une machine de tournée, chaque calcul doit avoir un état (plus ou moins caché). Qu'il soit représenté comme externe au code (au moyen de variables) ou interne au flux (au moyen d'un appel de fonction basé sur la pile) est toujours "état".
Emilio Garavaglia
3
Le calcul lambda a un état; sa contrainte est que l'État est immuable. L'état immuable est toujours un état. Les paramètres des fonctions, y compris les lambdas, sont toujours en état; on peut supposer que vous voulez qu'une fonction ait un comportement différent pour différents paramètres.
Billy ONeal
@emilio Déclarer qu'il existe une solution basée sur un état équivalent à un problème (comme vous le décrivez) n'est pas la preuve qu'aucune version sans état de cette solution n'existe.
Billy ONeal
2
@EmilioGaravaglia vous vous référez alors à l'état d'un interprète lambda-calcul. Lors du raisonnement dans le calcul lambda, il n'est pas nécessaire de raisonner sur l'état. L'aspect de la "mutabilité" est également différent.
wirrbel
1
@EmilioGaravglia: L'état dans la programmation impérative est la configuration de la mémoire à la fois, ici l'espace des paramètres est donné par toutes les valeurs de mémoire possibles et l'état est une configuration à la fois (bande de la machine de Turing). Lors de l'écriture d'un programme dans le lambda calcul, il n'y a pas d'entité directe telle qu'un champ mémoire. L'exécution du programme est l'application de transformations lambda. Les étapes intermédiaires peuvent ressembler à "état", mais ce ne sont que des expressions équivalentes de la même valeur. Rien ne change pendant l'évaluation, les expressions sont juste réécrites et traitées sous une forme "plus simple".
wirrbel
14

Quel que soit le système dynamique, «l'état» est ce qui fait que votre présent est influencé par votre passé ou votre futur (la flèche du temps n'est pas un problème mathématique, juste une contrainte physique).

Que vous ayez quelque chose à retenir ou que cela dépende de ce que vous avez fait, vous avez un état.

Un système sans état n'est pas "dynamique": c'est juste une fonction combinatoire. Cela peut ne pas avoir d'état, mais pour produire des résultats différents, il faut que l'état soit fourni d'une manière ou d'une autre.

Maintenant, selon le modèle de calcul auquel vous vous référez, un état peut être représenté explicitement (sous forme de variable) ou implicitement (sous forme d '"adresses de retour").

quand vous le faites, fna(fnb(x))vous donnez un état à fnb qui à son tour produira un état pour fna. Cela est dû au fait qu'il xexiste avant que fnb soit appelé (donc, il vient de son propre "passé").

Ce n'est pas une question d '«état exisit» ou «état n'existe pas». C'est une question de «je m'en soucie» ou de «je m'en fiche».

Emilio Garavaglia
la source
0

État signifie la capacité de répondre à un stimulus présent d'une manière qui dépend des stimuli passés, et pas seulement basée sur le stimulus actuel.

Les programmes purement fonctionnels ne sont que des fonctions. Ainsi, pour des applications pratiques, le programme purement fonctionnel entre une paire (old_state * present_stimulus) et sort une paire (new_state * present_response). Un "looper" externe et dynamique est nécessaire pour attendre le prochain stimulus et propager l'état.

Un programme purement fonctionnel n'a pas intrinsèquement d'état et ne peut pas être utilisé directement pour des applications pratiques.

Ainsi, aucun programme orienté état ne peut être remplacé par une implémentation différente purement fonctionnelle et sans état.

Atsby
la source
0

Vous pouvez éviter un état mutable explicite tant que vous n'avez pas à interagir avec le monde extérieur.

En JavaScript, pour que votre programme ait réellement un effet au-delà de la prise de cycles de processeur, vous devez modifier le Dom ou l'objet Window, et ces API sont avec état. Mais je suppose que vous pouvez créer un wrapper qui transmet les objets Dom et Window en tant que paramètres au code JavaScript, puis reçoit un nouveau Dom / Window en sortie. Cela isolerait le code JavaScript de l'état mutable.

Bien sûr , vous êtes toujours basez sur l' état, depuis la fenêtre du navigateur et DOM est stateful par nature. Toute application interactive est intrinsèquement avec état, mais vous pouvez toujours structurer votre code de manière à minimiser l'état explicite.

Une autre question est de savoir si c'est une bonne idée. Même Haskell, qui est un langage fonctionnel pur par conception, comprend la monade «état», qui vous permet de simuler un état mutable. Cela montre que l'état mutable explicite est parfois vraiment un modèle souhaitable.

JacquesB
la source
0

Pensez à la façon dont vous implémenteriez une "machine d'état" dans un langage de programmation sans état.

Vous pourriez probablement le faire, mais vous finiriez par utiliser des noms de fonction comme stockage. Se retrouver avec un gobblyday comme:

if (sm.atBegining()) sm.start() else if (sm.done()) sm.stop() ) else sm.progress()
James Anderson
la source