all
Business
data science
design
development
our journey
Strategy Pattern
Thank you! Your submission has been received!
Oops! Something went wrong while submitting the form.
Thank you! Your submission has been received!
Oops! Something went wrong while submitting the form.
Pedro Rolo

25. februar 2024

Min Read

Elm programming language overview

Dette er den anden del af min artikel om Elm-programmeringssproget. På den første artikel Jeg fokuserede på de vigtigste funktioner, der gør Elm til et interessant alternativ til JavaScript.

Her vil jeg fokusere på det historiske perspektiv, der gør Elm værd at se, og vil gå dybere ind på sprogets to hovedtræk: funktionel renhed og statisk skrivning. Derefter vil jeg påpege nogle gode eksempler på, hvem der bruger Elm i produktionen.

blue arrow to the left
Imaginary Cloud logo

Elms arkitekturs lavprofilerede succes

Den bedste måde at forudsige fremtiden på er at opfinde den.
Alan Kay, designer af programmeringssproget Smalltalk

Før 2013 fulgte de fleste front-end-programmer meget bydende tilgange. Rammer som Backbone eller Angular v1 inspirerede sig til model-view-controller-mønsteret (MVC) og gjorde mutationen og observationen af visningsmodellerne til kernen i deres displaylogik. Håndtering af så mange tilstande og begivenheder var hårdt og ubehageligt for mange webudviklere, for hvem det enkle dataflow i deres backend share-nothing web-rammer fik dem til at sukke efter de gamle dage, hvor JavaScript og AJAX endnu ikke havde overtaget deres verden.

Envejs dataflow

Reagere var det første projekt, der rystede dette bydende korthus. Det mest karakteristiske træk ved dette projekt er den virtuelle DOM, som gør det muligt for programmører at tænke på deres webside som noget, der effektivt kan genberegnes og gengives uden store omkostninger.

En sådan effektivitet er det, der gør det muligt for Reacts måde at modellere frontenden på: En webside består af et træ af komponenter, og hver gang brugeren interagerer med dem, beregnes hele sidens udseende baseret på den nye tilstand, der er gemt i disse komponenter. Du behøver ikke aktivt at ændre DOM længere; React tager sig af det for dig.

På trods af at React gjorde det lettere at modellere webapplikationer, foreskrev det ikke en måde at adskille forretningslogikken fra gengivelseslogikken. Facebook foreslog en arkitektur kaldet Flux for at løse dette problem, selvom mange af de tidligere implementeringer var mere komplekse end nødvendigt og tog tid at få trækkraft.

En funktionel arkitektur til React-applikationer

Det var i 2015, at Redux dukkede op og opstod som en enklere implementering af Flux-arkitekturen. Hovedideen er, at applikationens tilstand skal gemmes i et enkelt tilstandstræ, og at ændringer til dette træ skal modelleres som en reduktionsfunktion. Dette bør i sig selv være resultatet af sammensætningen af flere reduktionsfunktioner, der hver er ansvarlig for en del af applikationens tilstand, modellerer logikken til at behandle hver handling og opnå en ny version af staten.

Redux er et simpelt bibliotek med en meget lille kerne (omkring et dusin små funktioner). Det er let at forstå, behageligt at bruge og tillader brug af seje udviklingsfunktioner som tidsrejsende debuggere og genindlæsning af hot module.

På trods af enkelheden er dens tilgang ikke intuitiv og føles fremmed for JavaScript. Skrivning af reduceringsfunktioner, der ikke ændrer den tidligere version af tilstanden, er ikke trivielt, og det anbefales endda at bruge et bibliotek til at håndtere tilstanden på en uforanderlig måde. Det er således uden stor overraskelse, at Redux forfatter gjorde det meget klart at sådan arkitektur er stærkt inspireret af Elm.

blue arrow to the left
Imaginary Cloud logo

Statisk indtastning

Mod er at vide, hvad man ikke skal frygte.
— Platon

Hvis Elms arkitektur lykkedes efter at være blevet blandet med en fremmed imperativ teknologi som JavaScript, selv på bekostning af at fjerne udviklere fra deres komfortzone, hvor rart kan det være, hvis det holdt sig væk fra „hermeneutikken“ ved dynamisk typing og usikkerheden ved vilkårlige tilstandsmutationer? Er der mere at tage fra denne lode? Er der andre hemmeligheder under Elm?

JavaScript-økosystemet ser ud til at have brug for statisk skrivning

Når et softwareprojekt starter, er hele koden smuk, lyserød og skinnende. Derefter begynder du at stå over for deadlines, fejl, hotfixes, omfangsændringer, virksomhedsfusioner, opkøb og en horde af overallokerede udviklere, der ændrer koden, mens den oprindelige forfatter er på ferie, syg eller død. Efter aldring bærer hver kodelinje højden af sin historie, og ofte er der ingen til at fortælle.

På dårligt aldrede projekter lyver variabelnavne, funktionsnavne lyver, klassenavne lyver og typenavne lyver. Men når vi bruger dynamisk indtastede sprog - som JavaScript - giver kun navne og tests os information om semantikken i et program og om, hvordan det kan ændres og forbedres.

Til ros for statisk skrivning

Statisk typede sprog - på den anden side - kontrollerer projektets semantik og sikrer dets rigtighed. Navnene kan være forkerte, men vi ved, hvilke operationer der matcher hvilke typer, og kompilatoren kontrollerer automatisk, om vores ændringer giver mening.

Oplysningerne til udviklerne af sådanne systemer er tusind navne værd, og disse systemer er lettere at ændre og kræver meget mindre test, fordi typesystemet undgår flere fejl, som ellers skulle kontrolleres ved en automatiseret test udviklet af et menneske.

Ulempen ved statisk typning

Problemet med typer er, at de - på de fleste sprog - kommer i vejen, når der udvikles ny kode og debugger eller eksperimenterer med, hvordan koden opfører sig. Normalt tilføjer typer en masse unødvendig støj til den klare tale, som udviklere har med maskinen andre udviklere, mens de koder.

Med typer er udviklere også tvunget til at skrive mere - og selvom det måske ikke er meget dårligt, når du bruger editorens automatiske færdiggørelse - er det en katastrofe, når man eksperimenterer i interaktive miljøer som kommandolinjen eller debuggeren. Storheden ved at have koden fuld af typeinformation skaber masser af inerti og indebærer et enormt tab af smidighed. At vælge mellem statisk og dynamisk skrivning ender således som en afvejning mellem Brugervenlighed og vedligeholdelsesevne.

JavaScript-økosystemet bevæger sig mod gradvis skrivning

Det er således uden overraskelse, at vi finder flere initiativer, der bringer statisk skrivning ind i JavaScript-verdenen. De mest berygtede er Strømning (Facebook), Typeskript (Microsoft), og Dart (Google). Selvom disse ikke er ændringer i selve JavaScript-sproget, er de enten supersæt af sproget, der tilføjer skrivning eller lignende sprog, der direkte konkurrerer med det. Dette skaber masser af pres på udviklere til at gå over til en statisk skrevet tilgang, fordi værktøjerne og bibliotekerne også bevæger sig på den måde.

Der er dog en fælles tendens blandt alle disse tilgange: For at undgå den statiske typografiske massefylde har de valgt at gøre typer valgfrie. Således - afhængigt af konteksten - er udviklerne fri til enten at tilføje typeoplysninger til deres kode eller vælge at arbejde uden typekontrol - og den typesikkerhed, der følger med det.

Resultaterne er bedre end uden typer, men stadig relativt begrænsede. Da typerne er gradvise, er det ofte umuligt at kontrollere, om typesignaturerne giver mening, og mængden af verifikation afhænger meget af udviklerens disciplin og af, om de anvendte biblioteker har typeoplysninger til det samme typesystem.

Elm har en anden tilgang

Elms ideer kommer fra den typede funktionelle verden, hvor årtiers udvikling resulterede i brugen af typeinferens. I modsætning til dynamisk eller gradvis indtastning kontrollerer kompilatoren typerne på koden. Selvom, i modsætning til de fleste statiske typesystemer, er typeinformationen ikke påkrævet at blive indtastet eksplicit af programmereren og udledes af kompilatoren.

Programmereren kan vælge senere at tilføje typesignaturer til sine funktioner, selvom disse typesignaturer adskilles fra funktionsdefinitionerne. På denne måde bliver de ikke forvirrende for den, der senere læser eller redigerer koden.

Det skal dog bemærkes, at selv om Elm er inspireret af funktionelle sprogtypesystemer, ikke overholder deres mest komplekse funktioner. Det vedtager det, der synes nyttigt for front-end-programmører og holder en pragmatisk tilgang. Det er som om JavaScript blev redesignet til dets nuværende brug.

blue arrow to the left
Imaginary Cloud logo

Ren funktionel programmering

Ægte visdom kommer til hver enkelt af os, når vi indser, hvor lidt vi forstår om [...] verden omkring os.
— Sokrates

Elm er et rent funktionelt programmeringssprog. Dette betyder, at alle dens udtryk nyder en simpel egenskab kaldet Referencegennemsigtighed som stammer fra flere interessante konsekvenser. Vi fortsætter med at beskrive, hvad der er Referencegennemsigtighed og derefter undersøge dens konsekvenser.

Referencegennemsigtighed

Et udtryk eller en funktion siges at være referencegennemsigtig, når dens resultater opfører sig på en logisk måde. Med andre ord, når det leveres med et bestemt input, vil et referentielt gennemsigtigt udtryk altid evaluere til det samme resultat.

Rene funktioner er nemme at resonnere om og teste

Hvis vi tænker på det matematiske begreb funktion Vi bemærker måske, at det faktisk nyder denne ejendom. Det er faktisk ret svært at forestille sig, hvordan det kunne være anderledes. Funktionen, der beregner arealet af en firkant, evalueres altid til 4 kvadratmeter, når den er forsynet med et input på 2 meter og vil altid opføre sig som sådan. Der er ingen måde at skrive en funktion, der tager siden af firkanten som enkelt input og får den til at returnere forskellige værdier på forskellige tidspunkter.

I det mindste i den matematik, som de fleste af os er blevet tænkt, synes matematikere at have valgt en sådan abstraktion som et meget vigtigt - hvis ikke det vigtigste - værktøj til at modellere og ræsonnere om verden. Jeg vil sige, at dette ikke var nogen tilfældighed.

Hvis en funktion altid returnerer de samme resultater, kan vi evaluere og teste den uden at have noget i betragtning bortset fra dens input og output. Vi ved præcis, hvad vi skal levere, og hvad vi kan forvente, når vi tænker på modellering og test det.

Ingen mutation

Men referencegennemsigtighed er ikke en realitet i de fleste programmeringssprog. Med udviklingen af digitale computere valgte de fleste programmeringssprog at modellere verden på en måde, der ligner den måde, maskinerne fungerer internt på snarere end den, matematikere brugte til at modellere verden.

Der var forsøg på at følge den første vej siden udviklingen af de første kompilatorer. Imidlertid var computerne på det tidspunkt ikke magtfulde nok til at håndtere en sådan beregningsmodel, og den maskinlignende måde at modellere verden på blev en indgroet del af vores computervidenskabelige kultur.

Den maskinlignende måde at modellere verden på (imperativ programmering) er for det meste baseret på en muterende tilstand. I den kan beregninger modelleres ved at læse og ændre tilstanden for en hukommelsesenhed, indtil en endelig tilstand beregnes. Ved tilføjelse af funktioner til denne model valgte de fleste sprog at dele denne tilstand mellem funktioner og dermed bryde referencegennemsigtigheden.

Funktioner afhænger ikke af deres input; deres resultater afhænger af den hukommelse, de læser og skriver, og de returnerer ofte ikke nogen værdi, udelukkende tjener formålet med at ændre værdierne i den delte tilstand.

I modsætning hertil deles ingen tilstand mellem vores funktioner i rent funktionel programmering. Og hvis ingen stat deles, ophører der med at være en grund til at ændre tilstanden af de værdier, der bruges. Formålet med vores funktioner holder op med at handle om at ændre værdier og begynder at bruge dem som input til at beregne andre værdier. I rent funktionel programmering er enhver definition uforanderlig.

Elm passer til denne sprogfamilie, og derfor er alle dens definitioner uforanderlige, og alle dens funktioner er referentielt gennemsigtige.

Kørslen er ansvarlig for bivirkninger

Rene funktioner alene er ubrugelige. Vi udfører beregninger, fordi vi ønsker at læse inputværdier fra den ydre verden, og fordi vi ønsker at ændre det i henhold til værdierne i vores beregninger. Den ydre verden er således som en tilstand, der ændres af vores program i samme forstand som hukommelsen af vores imperative programmer.

Nogle funktionelle programmeringssprog fandt matematiske måder at håndtere dette problem elegant på i ren funktionel stil og på en generel måde, men ved at bruge nogle begreber, der har vist sig at være ret svære at forstå.

Elm har en anden tilgang. Dens runtime og arkitektur skjuler dette problem for os. Vores program ender med at være et sæt funktioner, der bruges til at beregne, hvad der skal vises til brugeren givet en bestemt sekvens af brugerhandlinger eller andre miljøinput.

Grundlæggende tager Elm-runtime og arkitektur sig af at interagere med verden i dette særlige domæne, hvilket gør det på en behagelig og enkel måde.

blue arrow to the left
Imaginary Cloud logo

Elm fra den virkelige verden?

Fremtiden er ikke lagt ud på et spor. Det er noget, vi kan beslutte, og i det omfang vi ikke overtræder nogen kendte love i universet, kan vi sandsynligvis få det til at fungere, som vi vil.
Alan Kay

Elms økosystem er ret umodent og udvikler sig langsomt. Imidlertid er bibliotekets kvalitet ofte meget god, og kompilatoren giver os masser af garantier for deres stabilitet. For nu er Elm passende til små dynamiske websidekomponenter eller til enkle websider, der ikke kræver gengivelse på serversiden.

Der er nogle vigtige funktioner, der kun forventes at komme med følgende version (0.19):

  • Serversidegengivelse - afsendelse af HTML med det oprindelige svar;
  • Trærystning - trimning af ubrugt kode (normalt kaldet eliminering af død kode eller DCE);
  • Kodeopdeling - opskæring af kode i mindre bidder for bedre caching;
  • Lazy loading - sender kun de kodestykker, der er nødvendige for en bestemt side.

Hovedformålet med denne version vil være at tilvejebringe et acceptabelt system til udvikling af komplekse enkeltsidede webapplikationer.

Brug i den virkelige verden

At klæde sig ud er uundgåeligt en erstatning for gode ideer. Det er ikke tilfældigt, at teknisk uduelige forretningstyper kaldes 'dragter'.
- Paul Graham

På trods af sin umodenhed er der allerede nogle succeshistorier i branchen:

  • NoreDink er en virksomhed inden for uddannelses- og softwareområdet;
  • Prezi udvikler software til at oprette interaktive præsentationer i browseren;
  • CBANC-netværk - Et netværk af bankfolk med værktøjer til banker til at samarbejde samt styre deres forretning. Al ny front-end udvikling udføres i Elm;
  • CircuitHub (GitHub) - CircuitHub leverer elektronikproduktion efter behov med øjeblikkelige tilbud;
  • YarilaBs - En portugisisk virksomhed, der udvikler software ved hjælp af funktionelle sprog
  • Andre virksomheder: Adrima; Bendyworks; Futurice; Gizra; Test Dobbelt; Mimo; SMRxT; TruQu; PinMeTo; Lyt; Dag et; Spottt; imby.bio; wonktonk; Smukke destinationer; AS Tallink Grupp; CARFAX.
blue arrow to the left
Imaginary Cloud logo

Relaterede sprog

Kontekst er 80 IQ-point værd.
- Alan Kay

Elm er stærkt inspireret i Haskell og inspirerer stærkt Purescript. Her er en oversigt over, hvad det hele handler om:

Haskell

Haskell er langt det sprog, der mest påvirkede Elm. Det er den nuværende standard for dovne programmeringssprog og er udviklet af et udvalg af akademikere fra området. De vigtigste forskelle fra Elm er:

  • Det er et programmeringssprog til generelle formål;
  • Det giver et meget polymorf og komplekst type system;
  • Evalueringen er doven (udtryk evalueres kun, når deres værdier er nødvendige);
  • Normalt er det kompileret til samling;
  • Har kørselsfejl.

PureScript

PureScript falder et sted imellem Haskell og Elm. Begge udvikler sig sammen og påvirker hinanden, når de vokser. Dens vigtigste egenskaber er:

  • Programmeringssprog til generelle formål;
  • Kompilerer til JavaScript;
  • Ligesom Haskell understøtter et meget polymorft og komplekst type system;
  • Værre fejlmeddelelser end Elm;
  • Bruger JavaScripts runtime snarere end sin egen runtime;
  • Nemme (og usikre) interaktioner med JavaScript-kode;
  • Like Elm (and unlike Haskell), it supports strict evaluation;
  • Has runtime errors.

Due to its complex type system, I do not think it is feasible for most JavaScript programmers to jump into Purescript. However, its easy (and unsafe) interaction with JavaScript makes it an interesting option for people who might have gone through Elm's or Haskell's stepping stones.

There are three projects in this language's ecosystem that try to address the same problem as the Elm architecture:

  • Thermite - A wrapper around React;
  • Halogen - A front-end framework taking advantage of the Purescript's complex type system;
  • Pux - When using Halogen they realized that the elaborate typing made it very hard for beginners, they then implemented Elm's architecture in Purescript, without deviating much from the simplicity of Elm's approach. The outcome was a framework called Pux.
blue arrow to the left
Imaginary Cloud logo

Conclusion

Elm is an interesting front-end specific programming environment that supports an immature software ecosystem. Due to the language design this young ecosystem ends up providing atypically strong safety guarantees. Many of these stem from the friendly compiler that guarantees that there are no runtime errors.

It's very pleasant to work with and allows easy development and refactoring with unprecedented safety and joy. It was designed to fulfill the needs of a modern JavaScript programmer and to be easy to get started with.

For now, it's not ready to develop complex single-page web applications due to lacking server-side rendering and some important optimizations. The next release (0.19) is expected to address these issues and while it is not ready it might not be a good idea to use it for more than small applications or components.

It is worth keeping some attention on this project that seems to have the potential of becoming a very competitive tool.

At Imaginary Cloud we have a team of experts on software development. If you think you could use some help with your digital project, drop us a line here!

Ready for a UX Audit? Book a free call

Found this article useful? You might like these ones too!

blue arrow to the left
Imaginary Cloud logo
blue arrow to the left
Imaginary Cloud logo
blue arrow to the left
Imaginary Cloud logo
blue arrow to the left
Imaginary Cloud logo
blue arrow to the left
Imaginary Cloud logo
Pedro Rolo
Pedro Rolo

Rails-udvikler med 10+ års erfaring med forskellige teknologier. Jeg er interesseret i funktionel programmering.

Read more posts by this author

People who read this post, also found these interesting:

arrow left
arrow to the right
Dropdown caret icon