2011-09-29 1 views
10

Quelqu'un peut-il me fournir un exemple qui peut m'aider à comprendre les modèles de programmation procéduraux, fonctionnels, logiques et orientés objet côte à côte en utilisant presque le même exemple-problème.Pouvez-vous représenter le même exemple en utilisant les langages de programmation procédural, fonctionnel, logique et OO?

Veuillez me donner des exemples d'extraits de code du même problème en utilisant les langages de programmation Procedural, Functional, Logic et OO.

+1

Hmm. Vous avez accepté ma réponse, puis l'avez refusée et offert une prime. Qu'est-ce qui a changé votre esprit? (Juste curieux, pas trolling pour rep.) –

+1

La plupart des codes sont destinés à démontrer les caractéristiques linguistiques plutôt que le paradigme/méthodologie de la langue. – anonymous

Répondre

8

Essayons plus simple exemple - juste en calculant le n-ème numéro de Fibonacci.

En premier lieu, la procédure (en Pascal):

program Fibonacci; 

function fib(n: Integer): Integer; 
var a: Integer = 1; 
    b: Integer = 1; 
    f: Integer; 
    i: Integer; 
begin 
    if (n = 1) or (n = 2) then 
    fib := 1 
    else 
    begin 
     for i := 3 to n do 
     begin 
     f := a + b; 
     b := a; 
     a := f; 
     end; 
     fib := f; 
    end; 
end; 

begin 
    WriteLn(fib(6)); 
end. 

Cet exemple montre les caractéristiques des langages de procédure:

  • Il y a quelques sous-routines (fonction dans ce cas)
  • Les variables sont de valeur attribuée probablement plusieurs fois (: = opérateur)
  • Il y a des cycles (pour opérateur dans ce cas)
  • La langue est impératif, à savoir que nous disons ordinateur ce qu'il faut faire dans quel ordre

En second lieu, orienté objet (en Python):

class Fibonacci: 
    def __init__(self): 
     self.cache = {} 
    def fib(self, n): 
     if self.cache.has_key(n): 
      return self.cache[n] 
     if n == 1 or n == 2: 
      return 1 
     else: 
      a = 1 
      b = 1 
      for i in range(2, n): 
       f = a + b; 
       b = a; 
       a = f; 
      self.cache[n] = f; 
      return f; 


fibonaccyCounter = Fibonacci() 
print fibonaccyCounter.fib(6) 

En fait, la le problème ne vaut pas la peine de créer une classe, j'ai donc ajouté la mise en cache des résultats déjà calculés.

Cet exemple montre:

    classe
  • et son instanciation (par exemple la création)
  • classe a sa propre section de mémoire, propre état (auto et ses membres)
  • La langue est impératif, à savoir nous disons ordinateur quoi faire dans quel ordre

Non montré mais nous pouvons par exemple Descendez cette classe de la classe abstraite en retournant le nième membre d'une séquence. En subslassing nous obtenons la classe de définition séquence de Fibonacci, séquence 1,2,3 ..., séquence 1,4,9,16, ... etc.

Troisièmement, dans le style fonctionnel (Haskell):

import Text.Printf 

fib :: Int -> Int 
fib 0 = 0 
fib 1 = 1 
fib n = fib (n-1) + fib (n-2) 

main = printf "%d\n" (fib 6) 

caractéristiques suivantes d'un paradigme de programmation fonctionnelle sont mises en évidence:

  • il n'y a pas d'état, pas de variables - seulement des fonctions définies
  • il n'y a pas de cycles - ne récursion
  • correspondance de modèle: nous avons défini séparément "fib 0", "fib 1" et "fib n" pour le reste des nombres, pas de construction comme si étaient nécessaires
  • style déclaratif - nous ne définissons pas l'ordre des étapes à calculer principal valeur de la fonction: le compilateur/interpréteur/runtime le trouve lui-même, compte tenu des définitions de fonctions. Nous disons à l'ordinateur ce que nous voulons obtenir, pas ce qu'il faut faire.
  • Évaluation paresseuse. Si main n'appelait que "fib 2" alors "fib n" n'était pas appelé car les fonctions sont évaluées seulement quand leur résultat est nécessaire pour être passé en paramètre à d'autres fonctions.

Mais la principale caractéristique des langages fonctionnels est que les fonctions sont des objets de première classe. Cela peut être démontré par une autre mise en œuvre de fib:

fib n = fibs!!n 
fibs = 0 : 1 : zipWith (+) fibs (tail fibs) 

nous passons ici la fonction fibs en tant que paramètre à zipWith fonction. Cet exemple montre également une évaluation paresseuse: la liste "infini" est calculée uniquement dans la mesure où elle est nécessaire pour d'autres fonctions. Par ailleurs, fonctionnel ne signifie pas nécessairement pas d'objet orienté. Un exemple de langage de programmation à la fois fonctionnel et orienté objet est Scala.

Prolog:

fib(1, 1). 
fib(2, 1). 


fib(X, Y):- 
     X > 1, 
     X1 is X - 1, 
     X2 is X - 2, 
     fib(X1, Z), 
     fib(X2, W), 
     Y is W + Z. 


main :- 
    fib(6,X), write(X), nl. 

Les fonctionnalités suivantes du style de programmation logique peut être vu:

  • La langue est déclarative. Comme dans le style fonctionnel, nous définissons les choses et ne disons pas dans quel ordre les faire.
  • Mais la différence avec le style fonctionnel est que nous définissons des prédicats, pas des fonctions. Dans ce cas, le fib de prédicat (X, Y) signifie "X-ème nombre de Fibonacci est Y".Étant donné certains prédicats connus (fib (1, 1) et fib (2, 1) - soit le premier nombre de Fibonacci est 1 et le deuxième nombre de Fibonacci est 1) et les règles pour déduire d'autres prédicats (Y est le nombre de Fibonacci est Y est un somme du nombre X-1th Fibonacci et du nombre X-2th Fibonacci), Prolog déduit les prédicats en question. En fait, il pourrait y avoir plus d'une réponse!
  • Il n'y a pas de valeurs d'entrée et de valeur de retour - au lieu de cela, nous définissons une relation entre "entrée" et "sortie".

Ce programme pourrait également être utilisé pour savoir ce nombre Fibonacci 8 est à la 6ème place dans la séquence:

?- between(0,inf,X), fib(X,8). 
X = 6 . 
+1

La principale caractéristique des langages fonctionnels est que les fonctions sont des objets de première classe, c'est-à-dire qu'elles peuvent être liées à des "variables", passées en tant que paramètres, renvoyées par d'autres fonctions. Mon exemple chez Haskell ne le démontrait pas. Je le remplace par une implémentation utilisant la liste infinie et 'zipWith'. –

6

Projet Euler Problème numéro 2: http://projecteuler.net/problem=2

Haskell (fonctionnelle/logique):

p2 = sum [x | x <- fibs, (x `mod` 2) == 0] where 
    fibs = unfoldr acc (0,1) where 
      acc (prev, cur) | (prev+cur) > 4000000 = Nothing 
          | otherwise   = Just (prev+cur, (cur, prev+cur)) 

Python (OO):

class FibSum(object): 
    def __init__(self, end): 
     self.end = end 
     self.next_two = (1,0) 
     self.sum = 0 

    def __iter__(self): 
     return self 

    def next(self): 
     current, previous = self.next_two 
     self.next_two = (previous+current, current) 
     new = current+previous 

     if current >= self.end: 
      raise StopIteration 
     elif (new % 2) == 0: 
      self.sum += new 
     else: 
      pass 


fibcount = FibSum(4000000) 
[i for i in fibcount] 
print fibcount.sum 

C (procédure/impératif):

#include <stdio.h> 

int main(void) 
{ 
    long int sum, newnum, previous = 0; 
    long int current = 1; 

    while(current <= 4000000) 
    { 
     newnum = previous+current; 
     if ((newnum % 2) == 0) 
     { 
      sum = sum + newnum; 
     } 
     previous = current; 
     current = newnum; 

    } 
    printf("%d\n", sum); 
} 

Et voici une version très inefficace écrit dans le schéma MIT

(define (unfold func seed) 
    (let* ((result (func seed))) 
    (cond ((null? result)()) 
    (else (cons (car result) (unfold func (second result))))))) 

(define (test x) 
    (cond ((> (sum x) 4000000)()) 
    (else (list (sum x) (list (second x) (sum x)))))) 

(define (sum xs) 
    (cond ((null? (cdr xs)) (first xs)) 
    (else (+ (car xs) (sum (cdr xs)))))) 

(sum (filter (lambda (x) (eq? (modulo x 2) 0)) (unfold test (list 0 1)))) 

Prolog: Take from this here, posted by 13tazer31

fibonacci(_,Current,End,0) :- 
     Current > End. 
fibonacci(Previous, Current, End, Total) :- 
     divisible(Current, 2), 
     Next is Current + Previous, 
     fibonacci(Current, Next, End, Sum), 
     Total is Sum + Current, !. 
fibonacci(Previous, Current, End, Total) :- 
     Next is Current + Previous, 
     fibonacci(Current, Next, End, Total). 

divisible(Number, 0) :- 
     write(‘Error: division by 0′).   
divisible(Number, Divisor) :- 
     Number mod Divisor =:= 0. 
+0

Je ne connais aucun prologue, mais il sera très similaire à la version Haskell, et vous pouvez probablement trouver facilement des prolog sur les forums de Project Euler qui résout cela (je pense que vous devez entrer la bonne réponse pour y accéder) – Wes

+0

Je sais que c'est la faute de la question en demandant des snippets, mais il semble qu'aucun de ces snippets ne démontre vraiment quelque chose d'idiomatique sur ces langages. – Gian

1

Eh bien sa très simple

  1. procédure, la logique fonctionnelle permet disons que vous voulez calculer quelque chose (c'est ce que font les ordinateurs)
    1. divisez le problème en fonctions dites f1, f2, f3 .... maintenant si vous regardez le problème, vous le voyez divisé en fonctions .. mais il doit y avoir un point de départ (d'où vous commencez le calcul) et un point final (où vous terminez le calcul) et entre eux sont les fonctions (f1, f2, f3). Ainsi, ce que vous avez réellement fait est d'écrire une grande fonction (F) qui fait tout et qui est très longue, vous devez la décomposer en parties plus petites (c'est ce qu'on appelle le refactoring). Comprendre une seule fonction longue de 150 lignes est ennuyeux. Quand vous arrivez à la fin de la ligne, vous oubliez où vous avez commencé et nous décomposons les choses. maintenant comment on fait le calcul ---> On crée une fonction unique dit calcul() (c'est ce qu'on appelle la façade) qui appellera les fonctions restantes (f1, f2, f3 ...) dans l'ordre désiré et retournera le résultat. Maintenant, comprenez ceci: Si nous avions écrit une seule fonction qui aurait été d'environ 150 lignes (la complexité augmente) .. supposons que nous l'avons décomposé en 3 fonctions et disons que chaque fonction est de 50 lignes (gérable) .. comment on réduit la complexité puisque la somme des lignes de 3 fonctions est toujours de 150: D. la complexité est réduite par le nom de la fonction .. ce qui indique clairement ce que la fonction fait .. cela signifie que, en regardant le nom, vous pouvez avoir une idée de ce que fait la fonction.

OO logique de programmation:
Maintenant, les fonctions sont dispersées dans la logique fonctionnelle .. lorsque nous apportons toutes les fonctions connexes (comportement) à l'intérieur d'un seul parapluie (classe), nous avons encore réduit la complexité. comment .. par "Nom de la classe". Maintenant, vous pouvez dire qu'au lieu d'appeler f1, f2, f3 .. nous appelons c1.f1(), c2.f2, c3.f3() où "c" indique une classe (design piloté par domaine).

imp .. peu importe si vous utilisez oops ou la logique fonctionnelle, il y a toujours un point de départ et de fin de calcul ... rappelez-vous le calcul() dont j'ai parlé .. et la question est de savoir qui .. La réponse est vous .. Toute la logique logique ou procédurale de la POO est cachée derrière elle (Service Façade)

Questions connexes