Wat is verschil tussen functionele en imperatieve programmeertalen?

Meeste van de mainstream-talen, waaronder objectgeoriënteerde programmering (OOP), zoals C #, Visual Basic, C++, en Java zijn ontworpen om in de eerste plaats noodzakelijke (procedurele) programmering te ondersteunen, terwijl Haskell / GoFer zoals talen puur functioneel zijn. Kan iemand uitgebreid zijn over wat het verschil is tussen deze twee manieren van programmeren?

Ik weet dat het afhangt van gebruikersvereisten om de manier van programmeren te kiezen, maar waarom wordt het aanbevolen om functionele programmeertalen te leren?


1, Autoriteit 100%

definitie:
Een imperatieve taal gebruikt een reeks verklaringen om te bepalen hoe een bepaald doel te bereiken. Van deze verklaringen wordt gezegd dat de toestand van het programma op hun beurt wordt geëxecuteerd.

voorbeelden:
Java is een dwingende taal. Een programma kan bijvoorbeeld worden gemaakt om een ​​reeks nummers toe te voegen:

int total = 0;
 int number1 = 5;
 int number2 = 10;
 int number3 = 15;
 total = number1 + number2 + number3; 

Elke instructie verandert de status van het programma, van het toewijzen van waarden aan elke variabele tot de uiteindelijke toevoeging van die waarden. Met behulp van een reeks van vijf uitspraken wordt het programma expliciet verteld hoe u de nummers 5, 10 en 15 bij elkaar wilt toevoegen.

functionele talen:
Het functionele programmeerparadigma werd uitdrukkelijk gemaakt om een ​​pure functionele benadering van het oplossen van problemen te ondersteunen. Functionele programmering is een vorm van declaratieve programmering.

Voordelen van pure functies:
De primaire reden om functionele transformaties ten uitvoer te leggen als pure functies is dat pure functies componabel zijn: dat is, op zichzelf staand en staatloos. Deze kenmerken brengen een aantal voordelen, inclusief het volgende:
Verhoogde leesbaarheid en onderhoudbaarheid. Dit komt omdat elke functie is ontworpen om een specifieke taak te volbrengen, gegeven zijn argumenten. De functie is niet afhankelijk van een externe status.

Eenvoudigere herhaalde ontwikkeling. Omdat de code gemakkelijker te refactoren is, zijn wijzigingen in het ontwerp vaak gemakkelijker te implementeren. Stel dat u bijvoorbeeld een gecompliceerde transformatie schrijft, en u realiseert zich dan dat sommige code meerdere keren wordt herhaald in de transformatie. Als u refactoreert via een pure methode, kunt u uw pure methode naar believen gebruiken zonder u zorgen te maken over bijwerkingen.

Gemakkelijker testen en debuggen. Omdat pure functies gemakkelijker afzonderlijk kunnen worden getest, kunt u testcode schrijven die de pure functie aanroept met typische waarden, geldige randgevallen en ongeldige randgevallen.

Voor OOP-mensen of
Dwingende talen:

Objectgeoriënteerde talen zijn goed als je een vaste reeks bewerkingen op dingen hebt en naarmate je code evolueert, voeg je voornamelijk nieuwe dingen toe. Dit kan worden bereikt door nieuwe klassen toe te voegen die bestaande methoden implementeren en de bestaande klassen worden met rust gelaten.

Functionele talen zijn goed als je een vaste set dingen hebt en naarmate je code evolueert, voeg je voornamelijk nieuwe bewerkingen toe aan bestaande dingen. Dit kan worden bereikt door nieuwe functies toe te voegen die met bestaande gegevenstypen rekenen en de bestaande functies met rust te laten.

Nadelen:

Het hangt af van de gebruikersvereisten om de manier van programmeren te kiezen, dus er is alleen schade als gebruikers niet de juiste manier kiezen.

Als de evolutie de verkeerde kant opgaat, heb je problemen:

  • Het toevoegen van een nieuwe bewerking aan een objectgeoriënteerd programma vereist mogelijk het bewerken van veel klassedefinities om een nieuwe methode toe te voegen
  • Het toevoegen van een nieuw soort ding aan een functioneel programma vereist mogelijk het bewerken van veel functiedefinities om een nieuw geval toe te voegen.

2, Autoriteit 143%

Hier is het verschil:

Bergelijk:

  • Start
  • Schakel uw schoenen af ​​van 9 1/2.
  • Maak ruimte in uw zak om een ​​array [7] van de sleutels te houden.
  • Plaats de sleutels in de ruimte voor de sleutels in de zak.
  • Voer de garage in.
  • open garage.
  • Voer de auto in.

… enzovoort en op …

  • Doe de melk in de koelkast.
  • stoppen.

declareermiddel, waarvan functioneel een subcategorie is:

  • Melk is een gezond drankje, tenzij je problemen hebt met het verteren van lactose.
  • Meestal slaat men een melk in een koelkast op.
  • Een koelkast is een doos die de dingen in het koel houdt.
  • Een winkel is een plaats waar items worden verkocht.
  • door “verkopen”, bedoelen we de uitwisseling van dingen voor geld.
  • ook, de uitwisseling van geld voor dingen wordt “kopen” genoemd.

… enzovoort en op …

  • Zorg ervoor dat we melk in de koelkast hebben (wanneer we het nodig hebben – voor luie functionele talen).

Samenvatting: in imperatieve talen vertel je de computer hoe je bits, bytes en woorden in zijn geheugen en in welke volgorde kunt veranderen. In functionele, vertellen we de computer welke dingen, acties etc. zijn. We zeggen bijvoorbeeld dat de faculteit van 0 1 is en de faculteit van elk ander natuurig nummer is het product van dat aantal en het faculteit van zijn voorganger. We zeggen niet: om de faculteit van N te berekenen, een geheugenregio te reserveren en er 1 op te slaan, vermenigvuldig het nummer in die geheugenregio met de nummers 2 tot n en opslaan het resultaat op dezelfde plaats, en aan het einde, De geheugenregio bevat het factoriaal.


3, Autoriteit 10%

De meeste moderne talen zijn in verschillende mate zowel imperatief als functioneel, maar om functioneel programmeren beter te begrijpen, is het het beste om een voorbeeld te nemen van pure functionele taal zoals Haskell in tegenstelling tot imperatieve code in niet zo functionele taal zoals java/C#. Ik geloof dat het altijd gemakkelijk uit te leggen is met een voorbeeld, dus hieronder is er een.

Functioneel programmeren: bereken faculteit van n i.e n! d.w.z. n x (n-1) x (n-2) x …x 2 X 1

-- | Haskell comment goes like
-- | below 2 lines is code to calculate factorial and 3rd is it's execution  
factorial 0 = 1
factorial n = n * factorial (n - 1)
factorial 3
-- | for brevity let's call factorial as f; And x => y shows order execution left to right
-- | above executes as := f(3) as 3 x f(2) => f(2) as 2 x f(1) => f(1) as 1 x f(0) => f(0) as 1  
-- | 3 x (2 x (1 x (1)) = 6

Merk op dat Haskel overbelasting van functies toestaat tot het niveau van de argumentwaarde. Hieronder staat een voorbeeld van een imperatieve code in toenemende mate van imperatief:

//somewhat functional way
function factorial(n) {
  if(n < 1) {
     return 1;
  }
  return n * factorial(n-1);   
}
factorial(3);
//somewhat more imperative way
function imperativeFactor(n) {
  int f = 1;
  for(int i = 1; i <= n; i++) {
     f = f * i;
  }
  return f;
}

Deze lezenkan een goede referentie zijn om te begrijpen hoe imperatieve code zich meer richt op hoe onderdeel, toestand van de machine (i in voor lus), volgorde van uitvoering, stroomregeling.

Het latere voorbeeld kan grofweg worden gezien als java/C# langcode en het eerste deel als beperking van de taal zelf in tegenstelling tot Haskell om de functie te overbelasten met waarde (nul) en daarom kan worden gezegd dat het geen puristische functionele taal is, aan de andere kant kun je zeggen dat het functionele prog ondersteunt. tot op zekere hoogte.

Disclosure:geen van de bovenstaande code is getest/uitgevoerd, maar zou hopelijk goed genoeg moeten zijn om het concept over te brengen; ook zou ik opmerkingen voor een dergelijke correctie op prijs stellen 🙂


Antwoord 4, autoriteit 6%

Functioneel programmerenis een vorm van declaratief programmeren, die de logica van de berekening beschrijft en de volgorde van uitvoering volledig wordt benadrukt.

Probleem: ik wil dit wezen veranderen van een paard in een giraf.

  • Nek langer maken
  • Benen langer maken
  • Spots toepassen
  • Geef het wezen een zwarte tong
  • Verwijder paardenstaart

Elk item kan in willekeurige volgorde worden uitgevoerd om hetzelfde resultaat te produceren.

Dwingend programmerenis procedureel. Staat en volgorde is belangrijk.

Probleem: ik wil mijn auto parkeren.

  1. Let op de oorspronkelijke staat van de garagedeur
  2. Stop de auto op de oprit
  3. Als de garagedeur gesloten is, open dan de garagedeur, onthoud de nieuwe staat; ga anders verder
  4. Auto naar garage trekken
  5. Sluit garagedeur

Elke stap moet worden gedaan om tot het gewenste resultaat te komen. Als u de garage binnenrijdt terwijl de garagedeur gesloten is, zou dit resulteren in een kapotte garagedeur.


Antwoord 5, autoriteit 3%

Functionele programmering is “programmeren met functies”, waar een functie enkele verwachte wiskundige eigenschappen heeft, inclusief referentiële transparantie. Uit deze eigenschappen stroomden verdere eigenschappen, met name vertrouwde redeneerstappen ingeschakeld door substitueerbaarheid die leiden tot wiskundige bewijzen (d.w.z. rechtvaardiging in een resultaat).

Hieruit volgt dat een functioneel programma slechts een uitdrukking is.

U kunt eenvoudig het contrast tussen de twee stijlen zien door de plaatsen in een imperatief programma te noteren waar een uitdrukking niet langer reagentieel transparant is (en daarom niet gebouwd is met functies en waarden, en niet zelf deel uitmaakt van een functie). De twee meest voor de hand liggende plaatsen zijn:
mutatie (b.v. variabelen)
andere bijwerkingen
niet-lokale controlestroom (bijvoorbeeld uitzonderingen)

Op dit kader van programma’s-as-expressies die zijn samengesteld uit functies en waarden, is het opgebouwd een heel praktisch paradigma van talen, concepten, “functionele patronen”, combinators en verschillende soorten systemen en evaluatie-algoritmen.

Door de meest extreme definitie, kan bijna elke taal-zelfs C of Java-functioneel worden genoemd, maar meestal behouden mensen de term voor talen met specifiek relevante abstracties (zoals sluitingen, onveranderlijke waarden en syntactische hulpmiddelen zoals patroonvergelijking) .
Wat het gebruik van functionele programmering betreft, betreft het gebruik van functines en bouwt de code zonder bijwerkingen op.
gebruikt om bewijzen te schrijven


6, Autoriteit 2%

Bergelijkende programmeerstijl werd van 2005 geoefend in Web-ontwikkeling helemaal tot 2013.

Met een imperatieve programmering schreef we de code die vermeldde precies wat onze aanvraag moest doen, stap voor stap.

De functionele programmeerstijl produceert abstractie via slimme manieren om functies te combineren.

Er wordt melding gemaakt van declaratief programmeren in de antwoorden en wat dat betreft zal ik zeggen dat declaratief programmeren een aantal regels opsomt die we moeten volgen. Vervolgens geven we wat we een initiële status noemen aan onze applicatie en we laten die regels een beetje bepalen hoe de applicatie zich gedraagt.

Deze snelle beschrijvingen zijn waarschijnlijk niet erg logisch, dus laten we de verschillen tussen imperatief en declaratief programmeren door een analogie lopen.

Stel je voor dat we geen software bouwen, maar in plaats daarvan taarten bakken voor de kost. Misschien zijn we slechte bakkers en weten we niet hoe we een heerlijke taart moeten bakken zoals we zouden moeten.

Dus onze baas geeft ons een lijst met aanwijzingen, wat we kennen als een recept.

Het recept vertelt ons hoe je een taart maakt. Eén recept is geschreven in een imperatieve stijl, zoals:

  1. Meng 1 kopje bloem
  2. Voeg 1 ei toe
  3. Voeg 1 kopje suiker toe
  4. Giet het mengsel in een pan
  5. Zet de pan in de oven gedurende 30 minuten en 350 graden F.

Het declaratieve recept zou het volgende doen:

1 kopje bloem, 1 ei, 1 kopje suiker – begintoestand

Regels

  1. Als alles gemengd is, in de pan doen.
  2. Als alles ongemengd is, doe het dan in een kom.
  3. Als alles in de pan zit, plaats het dan in de oven.

Dus imperatieve benaderingen worden gekenmerkt door stapsgewijze benaderingen. Je begint met stap één en gaat naar stap 2 enzovoort.

Je krijgt uiteindelijk een eindproduct. Dus bij het maken van deze taart nemen we deze ingrediënten, mengen ze, doen het in een pan en in de oven en je hebt je eindproduct.

In een declaratieve wereld is dat anders. In het declaratieve recept zouden we ons recept in twee afzonderlijke delen splitsen, te beginnen met één deel dat de beginstatus van het recept weergeeft, zoals de variabelen. Dus onze variabelen hier zijn de hoeveelheden van onze ingrediënten en hun type.

We nemen de oorspronkelijke staat of oorspronkelijke ingrediënten en passen er enkele regels op toe.

Dus we nemen de begintoestand en doorlopen deze regels keer op keer totdat we een kant-en-klare rabarber-aardbeientaart of wat dan ook hebben.

Dus in een declaratieve benadering moeten we weten hoe we deze regels goed kunnen structureren.

Dus de regels die we misschien willen om onze ingrediënten te onderzoeken of te vermelden, als ze gemengd zijn, doe ze dan in een pan.

Met onze oorspronkelijke staat komt dat niet overeen omdat we onze ingrediënten nog niet hebben gemengd.

Dus regel 2 zegt, als ze niet gemengd zijn, meng ze dan in een kom. Oké, ja, deze regel is van toepassing.

Nu hebben we een kom met gemengde ingrediënten zoals onze staat.

Nu passen we die nieuwe staat weer toe op onze regels.

Dus regel 1 zegt dat als ingrediënten worden gemengd, ze in een pan moeten, oké, ja, nu is regel 1 van toepassing, laten we het doen.

Nu hebben we deze nieuwe staat waarin de ingrediënten worden gemengd en in een pan. Regel 1 is niet langer relevant, regel 2 is niet van toepassing.

Regel 3 zegt dat als de ingrediënten in een pan zitten, ze in de oven moeten worden geplaatst, geweldig die regel is wat van toepassing is op deze nieuwe staat, laten we het doen.

En we eindigen met een heerlijke warme appeltaart of wat dan ook.

Als je op mij lijkt, denk je misschien: waarom doen we niet nog steeds imperatief programmeren. Dit is logisch.

Nou, voor eenvoudige stromen ja, maar de meeste webapplicaties hebben complexere stromen die niet goed kunnen worden vastgelegd door een imperatief programmeerontwerp.

In een declaratieve benadering kunnen we enkele initiële ingrediënten of initiële status hebben, zoals textInput=“”, een enkele variabele.

Misschien begint tekstinvoer als een lege tekenreeks.

We nemen deze beginstatus en passen deze toe op een reeks regels die in uw toepassing zijn gedefinieerd.

  1. Als een gebruiker tekst invoert, moet de tekstinvoer worden bijgewerkt. Nou, op dit moment is dat niet van toepassing.

  2. Als de sjabloon wordt weergegeven, berekent u de widget.

  3. Als textInput is bijgewerkt, moet u de sjabloon opnieuw renderen.

Nou, dit is allemaal niet van toepassing, dus het programma wacht gewoon tot er een evenement plaatsvindt.

Dus op een gegeven moment werkt een gebruiker de tekstinvoer bij en dan kunnen we regel nummer 1 toepassen.

We kunnen dat bijwerken naar “abcd”

Dus we hebben zojuist onze tekst- en textInput-updates geüpdatet, regel nummer 2 is niet van toepassing, regel nummer 3 zegt dat als tekstinvoer is geüpdatet, wat zojuist heeft plaatsgevonden, de sjabloon opnieuw wordt gerenderd en dan gaan we terug naar regel 2, dat wil zeggen als sjabloon is weergegeven, bereken de widget, oké, laten we de widget berekenen.

Over het algemeen willen we als programmeurs streven naar meer declaratieve programmeerontwerpen.

Dwingend lijkt meer duidelijk en voor de hand liggend, maar een declaratieve benadering schaalt heel goed voor grotere toepassingen.


Antwoord 7, autoriteit 2%

• Dwingende talen:

  • Efficiënte uitvoering

  • Complexe semantiek

  • Complexe syntaxis

  • Concurrency is door de programmeur ontworpen

  • Complexe testen, heeft geen referentiële transparantie, heeft bijwerkingen

  • Heeft staat

• Functionele talen:

  • Eenvoudige semantiek

  • Eenvoudige syntaxis

  • Minder efficiënte uitvoering

  • Programma’s kunnen automatisch gelijktijdig worden gemaakt

  • Eenvoudige testen heeft referentiële transparantie, heeft geen bijwerkingen

  • heeft geen staat

8

Ik denk dat het mogelijk is om functionele programmering op een imperatieve mode uit te drukken:

  • Met behulp van een heleboel staatscontrole van objecten en if... else/ switchverklaringen
  • Enkele time-out / wachtmechanisme om voor asynchornous te zorgen

Er zijn enorme problemen met een dergelijke aanpak:

  • Regels / procedures worden herhaald
  • Bevestigte verlaat de kansen voor bijwerkingen / fouten

Functionele programmering, het behandelen van functies / methoden zoals objecten en omarmende stateless, werd geboren om die problemen op te lossen die ik geloof.

Voorbeeld van usages: Frontend-toepassingen zoals Android, iOS of Web Apps ‘Logica incl. communicatie met backend.

Andere uitdagingen bij het simuleren van functionele programmering met imperatief / procedurele code:

  • RACE CONDITE
  • complexe combinatie en volgorde van gebeurtenissen. Gebruiker probeert bijvoorbeeld geld te verzenden in een bank-app. Stap 1) Doe al het volgende parallel, ga gewoon door als alles goed is) Controleer of de gebruiker nog steeds goed is (fraude, AML) b) Controleer of de gebruiker voldoende balans heeft C) Controleer of de ontvanger geldig en goed is (fraude, AML) enz. Stap 2) Voer de overdrachtsbewerking uit Stap 3) Toon update over het saldo van de gebruiker en / of een soort tracking. Met bijvoorbeeld RXJAVA is de code beknopt en verstandig. Zonder het kan ik me voorstellen dat er veel code, rommelig en foutgevoelige code
  • is

Ik ben ook van mening dat functionele code aan het einde van de dag wordt vertaald in de montage- of machinecode die imperatief / procedureel is door de compilers. Tenzij u echter een montage schrijft, als mensen die code schrijven met een hoog niveau / menselijke leesbare taal, is functionele programmering de meer geschikte manier van expressie voor de vermelde scenario’s


Antwoord 9

//The IMPERATIVE way
int a = ...
int b = ...    
int c = 0; //1. there is mutable data
c = a+b;   //2. statements (our +, our =) are used to update existing data (variable c)

Een imperatief programma = reeks uitspraken die bestaande gegevens wijzigen.

Focus op WAT = onze muterende gegevens (aanpasbare waarden oftewel variabelen).

Aaneenschakeling van imperatieve uitspraken = gebruik procedures (en/of oeps).


//The FUNCTIONAL way
const int a = ... //data is always immutable
const int b = ... //data is always immutable
//1. declare pure functions; we use statements to create "new" data (the result of our +), but nothing is ever "changed"
int add(x, y) 
{
   return x+y;
} 
//2. usage = call functions to get new data
const int c = add(a,b); //c can only be assigned (=) once (const)

Een functioneel programma = een lijst met functies die “uitleggen” hoe nieuwe gegevens kunnen worden verkregen.

Focus op HOE = onze functie add.

Om functionele “statements” te koppelen = gebruik functiecompositie.


Deze fundamentele verschillen hebben ingrijpende gevolgen.

Serieuze software heeft veel data en veel code.

Dus dezelfde gegevens (variabele) worden in meerdere delen van de code gebruikt.

A. In een imperatief programma veroorzaakt de veranderlijkheid van deze (gedeelde) gegevens problemen

  • code is moeilijk te begrijpen/onderhouden (aangezien gegevens op verschillende locaties/manieren/momenten kunnen worden aangepast)
  • parallelle code is moeilijk (slechts één thread kan tegelijkertijd een geheugenlocatie muteren), wat betekent dat het muteren van toegang tot dezelfde variabele geserialiseerd moet zijn = ontwikkelaar moet extra code schrijven om deze geserialiseerde toegang tot gedeelde bronnen af te dwingen, meestal via sloten/ semaforen

Voordeel: gegevens worden ter plekke echt aangepast, er hoeft minder te worden gekopieerd. (enkele prestatieverbeteringen)

B. Aan de andere kant gebruikt functionele code onveranderlijke gegevens die dergelijke problemen niet hebben. Gegevens zijn alleen-lezen, dus er zijn geen racevoorwaarden. Code kan eenvoudig worden geparallelliseerd. Resultaten kunnen in de cache worden opgeslagen. Veel gemakkelijker te begrijpen.

Als nadeel: gegevens worden veel gekopieerd om “aanpassingen” te krijgen.

Zie ook: https://en.wikipedia.org/wiki/Referential_transparency


Antwoord 10

Ik weet dat deze vraag ouder is en dat anderen het al goed hebben uitgelegd, ik zou graag een voorbeeldprobleem willen geven dat hetzelfde in eenvoudige bewoordingen uitlegt.

Probleem: de tafel van 1 schrijven.

Oplossing: –

Op imperatieve stijl: =>

   1*1=1
    1*2=2
    1*3=3
    .
    .
    .
    1*n=n 

Op functionele stijl: =>

   1
    2
    3
    .
    .
    .
    n

Uitleg in imperatieve stijl we schrijven de instructies explicieter en die kunnen op een meer vereenvoudigde manier worden aangeroepen.

Waar, zoals in Functionele stijl, dingen die voor zichzelf spreken worden genegeerd.

Other episodes