2011-09-29 7 views
10

Qualcuno può fornirmi un esempio che possa aiutarmi a capire i modelli di programmazione procedurali, funzionali, logici e orientati agli oggetti fianco a fianco usando quasi lo stesso problema di esempio.Puoi rappresentare lo stesso esempio usando le lingue di programmazione procedurali, funzionali, logiche e OO?

Fornire esempi di frammenti di codice dello stesso problema utilizzando linguaggi di programmazione procedurali, funzionali, logici e OO.

+1

Hmm. Hai accettato la mia risposta, poi non l'hai accettata e hai offerto una taglia. Cosa ti ha fatto cambiare idea? (Solo curioso, non trolling per rappresentante.) –

+1

La maggior parte dei codici è intesa a dimostrare le caratteristiche del linguaggio piuttosto che il Paradigma/Metodologia della lingua. – anonymous

risposta

8

Proviamo più semplice esempio: basta calcolare il n-esimo numero di Fibonacci.

In primo luogo, procedurale (in 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. 

Questo esempio mostra caratteristiche di linguaggi procedurali:

  • Ci sono alcune subroutine (funzione in questo caso)
  • variabili vengono assegnati valore probabilmente più volte (: = operatore)
  • Ci sono cicli (per operatore in questo caso)
  • lingua è indispensabile, cioè stiamo dicendo computer cosa fare in quale ordine

In secondo luogo, orientata agli oggetti (in 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) 

In realtà la problema non vale la pena creare una classe, quindi ho aggiunto il caching dei risultati già calcolati.

Questo esempio mostra:

  • classe e della relativa istanziazione (esempio creando)
  • classe ha propria sezione di memoria, proprio stato ( ed i suoi membri)
  • linguaggio è imperativo, cioè stiamo dicendo al computer cosa fare in quale ordine

Non mostrato ma possiamo ad es. discendi questa classe dalla classe astratta che restituisce l'n-esimo membro di qualche sequenza. Con subslassing otteniamo classe che definisce la sequenza di Fibonacci, la sequenza 1,2,3 ..., sequenza 1,4,9,16, ... ecc

In terzo luogo, in stile funzionale (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) 

Le seguenti caratteristiche di un paradigma di programmazione funzionale sono dimostrate:

  • non c'è stato, nessuna variabile - solo funzioni definite
  • ci sono cicli - solo ricorsione
  • corrispondenza del modello: abbiamo definito separatamente "fib 0", "fib 1" e "fib n" per il resto dei numeri, nessun costrutto come se fosse necessario
  • stile dichiarativo - non definiamo l'ordine dei passaggi per calcolare valore di funzione principale: il compilatore/interprete/runtime lo rileva da solo, date le definizioni di funzione. Diciamo al computer cosa vogliamo ottenere, non cosa fare.
  • Valutazione pigra. Se main chiamava solo "fib 2", allora "fib n" non veniva chiamato perché le funzioni sono valutate solo quando il loro risultato è necessario per essere passato come parametro ad altre funzioni.

Ma la caratteristica principale dei linguaggi funzionali è che le funzioni sono oggetti di prima classe. Questo può essere dimostrato con altre applicazioni di fib:

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

Qui stiamo passando fibs funzione del parametro di zipWith funzione. Questo esempio dimostra anche una valutazione lazy: la lista "infinita" viene calcolata solo per estenderne l'uso per altre funzioni.

A proposito, funzionale non necessario significa non orientato agli oggetti. Un esempio di linguaggio di programmazione che sia funzionale e orientato agli oggetti è 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. 

seguenti funzionalità di stile di programmazione logica può essere visto:

  • lingua è dichiarativa. Come nello stile funzionale, definiamo le cose e non diciamo in quale ordine eseguirle.
  • Ma la differenza con lo stile funzionale è che definiamo i predicati, non le funzioni. In questo caso, il predicato fib (X, Y) significa "X-esimo numero di Fibonacci è Y".Dati alcuni predicati noti (fib (1, 1) e fib (2, 1) - ovvero il primo numero di Fibonacci è 1 e il secondo numero di Fibonacci è 1) e regole per inferire altri predicati (Y è X-th Il numero di Fibonacci è Y è un somma del numero X-1 ° di Fibonacci e del numero X-2 ° di Fibonacci), il Prolog fornisce i predicati in questione. In realtà ci potrebbe essere più di 1 risposta!
  • Non ci sono valori di input e valori di ritorno - al posto di questo definiamo una relazione tra "input" e "output".

Questo programma potrebbe anche essere utilizzato per scoprire che Fibonacci numero 8 è al 6 ° posizione nella sequenza:

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

La caratteristica principale dei linguaggi funzionali è che le funzioni sono oggetti di prima classe, cioè possono essere associati a "variabili", passate come parametri, restituite da altre funzioni. Il mio esempio in Haskell non lo stava dimostrando. Lo sto sostituendo con l'implementazione usando la lista infinita e 'zipWith'. –

6

Project Euler Problema numero 2: http://projecteuler.net/problem=2

Haskell (funzionali/logica):

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 (procedurale/imperativo):

#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); 
} 

E qui è una versione molto inefficiente scritta nello Schema 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

Non conosco alcun prologo, ma sarà molto simile alla versione Haskell, e puoi facilmente trovare dei prolog nei forum di Project Euler che risolvono questo problema (penso che tu debba inserire la risposta corretta per accedervi) – Wes

+0

So che questa è l'errore della domanda nel chiedere i frammenti, ma sembra che nessuno di questi frammenti mostri davvero qualcosa di idiomatico su questi linguaggi. – Gian

1

Beh è molto semplice

  1. procedurale, logica funzionale lascia dì che vuoi calcolare qualcosa (questo è ciò che fanno i computer)
    1. interrompe il problema in funzioni dire f1, f2, f3 .... ora se si guarda al problema, lo si vede diviso in funzioni .. ma ci deve essere un punto di partenza (da dove si inizia il calcolo) e il punto finale (dove si termina il calcolo) e tra di loro ci sono le funzioni (f1, f2, f3). Quindi quello che hai veramente fatto è invece di scrivere una grande funzione (F) che fa ogni cosa ed è molto lunga che tu l'abbia suddivisa in parti più piccole (questo è noto come refactoring). Comprendere una singola funzione lunga 150 righe è noiosa .. quando arrivi alla fine della linea ti dimenticherai da dove hai iniziato, quindi spezzeremo le cose. ora come facciamo il calcolo ---> Creiamo una singola funzione diciamo compute() (nota come facciata) che chiamerà le restanti funzioni (f1, f2, f3 ...) nell'ordine desiderato e restituirà il risultato. Ora capisco questo: Se avessimo scritto una singola funzione che sarebbe stata di circa 150 linee (aumento di complessità) .. supponiamo di averlo suddiviso in 3 funzioni e di dire che ogni funzione è di 50 righe (gestibile) .. come riduciamo la complessità poiché la somma delle righe di 3 funzioni è ancora 150: D. la complessità è ridotta dal nome della funzione .. che indica chiaramente cosa fa la funzione .. significa che guardando il nome si può avere un'idea di cosa funzioni la funzione.

OO logica di programmazione:
Ora funzioni sono sparsi nella logica funzionale .. quando portiamo tutte le relative funzioni (comportamento) all'interno di un unico ombrello (Class) che hanno ulteriormente ridotto la complessità. .. come .. per "Nome della classe". Ora puoi dire che invece di chiamare f1, f2, f3 .. chiamiamo c1.f1(), c2.f2, c3.f3() dove "c" denota una classe (design basato sul dominio).

imp .. non importa se usi oops o logica funzionale c'è sempre un punto di inizio e di fine del computo ... ricorda il calcolo() di cui ho parlato .. e la domanda è chi lo chiama ... e il risposta sei tu .. Tutto la logica o logica procedurale di OOP è nascosta dietro di essa (Service Face)

Problemi correlati