Forskellen mellem en compiler og en fortolker
On december 31, 2021 by adminSom det fremgår af deres definitioner, synes forskellen mellem en compiler og en fortolker at være klar nok:
- Fortolker er et program, der direkte udfører instruktioner skrevet i et programmeringssprog
- Compiler er et program, der omdanner kildekode i et lav(er)-niveau sprog
Hvis man graver dybere, finder man dog en vis udviskning mellem de to.
En fortolker kunne faktisk oversætte kildesproget i en mellemform, for at fremskynde udførelsen. Det er det, der normalt sker med et sprog, der er afhængig af en virtuel maskine. Dette fører naturligvis til nogle spørgsmål:
Er alle sprog, der anvender en virtuel maskine, fortolkede?
Er de faktisk alle kompileret?
Man kan sige begge dele: et sprog kompileres først i en mellemform/et mellemliggende sprog, og derefter fortolkes denne mellemform på køretidspunktet. Hvilket også fører til et andet spørgsmål, en compiler og en fortolker skal ikke tænkes som ét program, men mere som en gruppe af programmer, et system. Det, som du som bruger opfatter som en compiler, kan i virkeligheden omfatte mere end et program. Det kan f.eks. omfatte en linker: et program, der kombinerer forskellige objektfiler i én fil, så den lettere kan bruges. Noget lignende kan siges om en fortolker.
Kan du fortælle mig alt om compilere & fortolkere?
Sådan, hvilke er alle de dele, der udgør en compiler eller en fortolker? Man kan søge efter et præcist og teknisk svar på sådanne spørgsmål i den akademiske verden. Eller du kan finde diskussioner om disse spørgsmål på StackOverflow.
Det, der virkelig betyder noget for os som udviklere, eller endda for os som skabere af et sprog, er, hvad forskellene er i arbejdet med dem. Begge har fordele og ulemper, og faktisk kan nogle sprog have både en fortolker og en compiler, eller mere end en. Det er det, vi skal se.
Den vigtigste pointe står stadig: en fortolker udfører koden nu, en compiler forbereder kildekoden til en senere udførelse. Alle de praktiske forskelle stammer fra disse forskellige mål.
Hvordan distribuerer man et program
Praktisk set er en vigtig forskel, at en compiler genererer et selvstændigt program, mens et fortolket program altid har brug for fortolkeren for at køre.
Når man har et kompileret program, kan man køre det uden at skulle installere noget andet. Dette forenkler distributionen. På den anden side fungerer det eksekverbare program på én bestemt platform: forskellige styresystemer og forskellige processorer har brug for forskellige kompilerede versioner. F.eks. kan et kompileret C++-program måske fungere på en computer med en x86-processor, men ikke på en computer med en ARM-chip. Eller det kan fungere på et Linux-system, men ikke på et Windows-system.
Hvis du skal fortolke et program, kan du distribuere den samme kopi til brugere på forskellige platforme. De vil dog have brug for en fortolker, der kører på deres specifikke platform. Du kan enten distribuere den originale kildekode eller en mellemform. En intuitiv måde at se på en fortolker på er følgende: den er ligesom eval
-funktionen i JavaScript. Den fungerer overalt, hvor JavaScript fungerer, men den skal bruge en JavaScript-fortolker til den pågældende platform for at kunne køre.
Understøttelse på tværs af platforme
Dette er en teknisk forskel, der fører til vigtige reelle konsekvenser: Det er lettere at lave programmer på tværs af platforme med et fortolket programmeringssprog.
Det skyldes, at man for det meste blot laver et program til fortolkerplatformen. Det vil være selve fortolkeren, der vil oversætte det til den rigtige form for den rigtige platform (f.eks. Windows/Linux og x86/ARM). Selvfølgelig er der stadig nogle forskelle på de enkelte platforme, som du skal være opmærksom på. Et almindeligt eksempel er tegn til adskillelse af mapper.
Når du kompilerer et program, skal du i stedet selv tage højde for alle de små forskelle mellem de enkelte platforme. Dette sker bl.a. fordi kompilerede sprog har en tendens til at være sprog på lav(ere) niveau, f.eks. C++, så de giver dig lavere adgang til systemet og dermed mere ansvar. Men en anden grund er, at alle de biblioteker, du bruger, selv skal understøtte forskellige platforme. Så hvis de ikke understøtter Windows, kan du ikke understøtte Windows.
Speed Has Multiple Faces
Igen, når det gælder hastighed, har vi en slags paradoks: en compiler er både hurtigere og langsommere end en fortolker. Mange mennesker ved, at et kompileret program er meget hurtigere end et fortolket, men det er ikke hele billedet. Et kompileret program er hurtigere at køre end et fortolket program, men det tager mere tid at kompilere og køre et program end blot at fortolke det.
En compiler producerer faktisk hurtigere programmer. Det sker grundlæggende, fordi den kun skal analysere hvert statement én gang, mens en fortolker skal analysere det hver gang. Desuden kan en compiler optimere den eksekverbare kode, som den producerer. Det er både fordi den ved præcis, hvor den skal køre, og fordi det tager tid at optimere koden. Tid, der ville gøre fortolkningen for langsom.
Runtime Speed Versus Development Speed
Du vil måske mene, at dette er småting: Hvis du kompilerer et program, kører det hurtigere, og den tid, det tager at kompilere, er ligegyldig. Dette er normalt den gamle skoleopfattelse. Og der er ingen tvivl om, at det resulterende program bliver kørt flere gange, end det er kompileret. Så hvem bekymrer sig om, at udviklingen tager mere tid? Tja, det kræver i hvert fald en “bring the pain”-holdning til udvikling, som er noget beundringsværdig. Men hvad nu hvis gevinsten i køretid ikke er relevant, mens tabet i udviklingsproduktivitet er betydeligt?
Det er én ting, hvis man laver et operativsystem, og en anden ting, hvis man laver en selfie-app. Selv dine brugere foretrækker måske et ikke engang mærkbart tab i kørselstidshastighed til gengæld for at få funktioner hurtigere. Der findes ikke et svar, der passer til alle: I nogle sammenhænge er produktivitet vigtigere end hastighed, i andre er det omvendte tilfældet.
Mysterierne om debugging
Der er et andet særligt aspekt, der ender med at være mere usikkert end det, man ville kunne forestille sig: debugging. På papiret er debugging nemmere, når man bruger en fortolker end når man bruger en compiler. Det er sandt af flere grunde:
- Med en fortolker er der én version af den eksekverbare fil; man har ikke brug for en debug-version til udvikling og en release-version til slutbrugeren
- der er færre platformsspecifikke fejl ved brug af en fortolker
- da fortolkeren transformerer koden i farten, er informationerne fra kildekoden stadig tilgængelige
- da fortolkeren udfører et statement ad gangen, er det lettere at finde en fejl
Den forskel, som udviklingsværktøjer gør
Selv om alt dette er sandt i praksis, er det måske mindre relevant, end det ser ud til. Faktisk vil du, hvis du tænker på dine erfaringer, sandsynligvis opdage, at det er sværere at debugge JavaScript end at debugge C++. Hvorfor er det sådan? Til dels er designet af selve sprogene. JavaScript anvender dynamisk typning, mens C++ anvender statisk typning. Sidstnævnte gør det lettere at opdage fejl tidligt. Men i sidste ende kommer det an på udviklingsværktøjerne. Det er svært at kompilere C++ i hånden, så de fleste mennesker bruger IDE’er til at udvikle med det. På den anden side kan man nemt bruge teksteditor og kommandolinjeværktøjer til at udvikle i JavaScript.
Det betyder i praksis, at hvis man udvikler med C++, kan man også debugge C++. I stedet kan du udvikle med JavaScript uden at vide, hvordan man laver ordentlig fejlfinding i JavaScript.
Hvis det er sagt, hvis vi sætter dem i samme sammenhæng, hver med et godt IDE og understøttende værktøjer, kommer situationen tilbage til det normale. Faktisk bruges mange fortolkede miljøer af folk, der ønsker at lære at bruge et nyt sprog. Det er lettere at teste og finde ud af, hvad der er rigtigt og forkert, ved at se på, hvad der sker linje for linje og i realtid.
Summary
Vi har set de vigtigste forskelle, der betyder noget mellem en compiler og en fortolker. Vigtigere er det, at vi har set, at konsekvenserne af forskellige filosofier er vigtigere end de tekniske konsekvenser. Kort sagt, der er kulturer, der følger med visse tekniske valg, som ender med at være relevante i sig selv. Hvis man ønsker hastighed og lethed i udviklingen, vælger man alle teknologier for hastighed og ikke kun én. Og dine brugere vil følge dig.
Dette er et afgørende aspekt at tænke igennem, især hvis du ønsker at skabe dit eget programmeringssprog. Rasmus Lerdorf skabte PHP for at det skulle være let at bruge. Og det var faktisk utroligt meget nemmere at bruge i forhold til alternativerne, i hvert fald på det tidspunkt, hvor det blev skabt. Men det startede mere som et bibliotek end som et sprog. Og selv om det er blevet meget bedre, lider det stadig under sin begyndelse. Man kan stadig lave god PHP-kode, men færre af dets brugere end normalt gør det. For hvis du bare har brug for noget, der virker, sikkerhed, vedligeholdelse osv. kommer alt det andet senere.
Hvis du vil vide, hvordan du praktisk kan bygge en fortolker eller en compiler til dit sprog, kan du tage et kig på ressourcerne til at skabe et programmeringssprog. Hvis du vil lære det, og alt det, du skal bruge for at skabe dit eget sprog, skal du blot vælge en god bog, der er elsket af både børn og voksne, om hvordan man skaber pragmatiske, lette sprog.
5 ting, du skal gøre rigtigt, når du bygger et sprog
Få tjeklisten pr. e-mail og få flere tips til at bygge sprog
Skriv et svar