Bogen "The Pragmatic Programmer" (hvis du ikke har læst den, så stop med at læse denne artikel og gør det nu!) siger, at vi hvert år bør lære et nyt programmeringssprog.
Selv om nogle måske vil mene, at det er for besværligt, kan vi alle blive enige om, at det er en god idé. Det er ikke så let at vælge et nyt sprog at lære. Vi vil jo ikke bruge vores tid på noget, som vi måske aldrig kommer til at bruge i praksis, vel? Men måske skal vi nogle gange gøre en undtagelse og lære noget bare for at have det sjovt? Jeg vil gerne præsentere dig for Brainfuck-sproget. Det er et sprog, som du kan lære på et par minutter, så der er ikke noget problem med at investere for meget af din tid forgæves. Jeg kan også love, at det vil stimulere din hjerne at løse et hvilket som helst problem med Brainfuck (alle f*cks er bare en bonus ;)). Lad os komme i gang!Ifølge Wikipedia:
Hjernevrider er en esoterisk programmeringssprog skabt i 1993 af Urban Müller. Sproget består kun af otte simple kommandoer og en instruktions-pointer. Selv om det er fuldt Turing-komplet, er det ikke beregnet til praktisk brug, men til at udfordre og underholde programmører.
Oversigt over sprog
Forestil dig et uendeligt langt bånd, der består af celler, som hver især er initialiseret til 0. Der er også en bevægelig datapointer, som i starten peger på den første celle. Der er også to strømme af bytes til input og output. Instruktioner udføres sekventielt, en efter en. Maskinen stopper, når den sidste er udført.
Kommando
Hvad gør den?
>
Flyt datapointeren til den næste celle til højre
<
Flyt datapointeren til den næste celle til venstre
+
øger værdien af den aktuelle celle
–
reducerer værdien af den aktuelle celle
.
udsender byte for en aktuelt peget celle i ASCII Kode
,
læs en byte fra stdin og gem dens værdi i den aktuelle celle
[
hvis den aktuelle celle er 0, så spring til den matchende ]
]
spring til den matchende [
Alle andre tegn end ><+-.,[] bliver ignoreret.
Lad os se på et enkelt eksempel:
,+.
Det vil blive fortolket på følgende måde:
læs en byte og gem den i den aktuelle celle (cell0)
Forøg værdien af den aktuelle celle (cell0 = cell0 + 1)
skriv indholdet af den aktuelle celle til output
Resultatet er, at et tegn læses fra input, og det næste tegn udskrives fra ASCII-tabellen.
Fortolker / Compiler
Før vi skriver nogle nyttige (?) programmer i Brainfuck, har vi brug for en fortolker eller en compiler. AFAIK er der ingen officiel, men det er ikke noget problem. Der findes snesevis af uofficielle på internettet. Jeg kan anbefale disse to:
"Hello World!" bør være det første program, vi skriver, når vi lærer et nyt sprog. Men det er lidt sværere at skrive det i Brainfuck end i andre sprog. Vi er nødt til at starte med noget lettere ... Lad os skrive et program, der udskriver et enkelt bogstav "H" på skærmen (så spændende :D):
Hvordan fungerer det? Den sætter værdien af den aktuelle celle til 72 (med 72 trin) og udskriver den på skærmen ved hjælp af "." (H har koden 72 i ASCII). Nu ved du, hvad vi skal gøre for at udskrive "Hello World!" på skærmen, men inden da vil vi foretage en lille refaktorering. At skrive alle de '+' kræver for meget indtastning og optælling. Vi kan gøre det kortere ved at bruge [ og ] til looping. For at sætte værdien til 72 kan vi f.eks. lave en løkke, som øger værdien 7 gange med 10. På den måde får vi 70. Hvis vi lægger 2 til, bliver det 72. Det ser sådan ud:
++++++++++ # sæt cell0 til 10
[ # loop, indtil cell0 er 0
- # reducer cell0
> # flyt datapointeren til højre (celle1)
+++++++ # forøger celle1 med 7
# flyt datapointeren til højre (cell1)
++ # øges med 2
. # udskriv resultatet
Jeg har inkluderet kommentarer for at gøre det klart, hvordan det hele fungerer. Det samme program uden kommentarer:
++++++++++[->+++++++++.
Er det ikke smukt?
Hej verden!
Hvis vi går tilbage til vores "Hello World!"-program. Vi kunne sætte værdien af den første celle til 72 (H) og udskrive den, sætte værdien af den anden celle til 101 (e) og udskrive den, sætte værdien af den tredje celle til 108 og udskrive den og så videre. Her er implementeringen af denne algoritme:
Ja, kun 1120 bytes til at udskrive "Hello World!" ... Men vi kan gøre det bedre! I stedet for at bruge en ny celle til hvert tegn, så lad os nøjes med én. For at udskrive bogstavet "e" (101) kan vi genbruge værdien i celle 0 (72). Vi kan øge den med én 29 gange (101 - 72). Og resultatet er som følger:
Det er kun 106 bytes, og den udskriver en ny linje i slutningen! Fantastisk.
At vende en streng
Nu er vi klar til at skrive noget mere udfordrende. Lad os skrive et program, som læser en linje fra input og udskriver den i omvendt rækkefølge. Det første problem er at læse tegn og stoppe ved det nye linjetegn. Husk, at der ikke er nogen pause, hvis eller andre lignende udsagn. Vi er nødt til at bruge [ og ]. Lad os starte med et program, der læser alle tegn fra input og placerer dem i successive celler:
,[>,]
Den starter med at læse det første tegn og fortsætter indtil det sidste. , Operationens afkast 0. Men den vil loope for evigt i en implementering, der returnerer noget andet end O for EOF (sproget specificerer ikke denne opførsel). Så hvordan kan vi stoppe på det nye linjetegn? Her er tricket:
+[++++++++++>,----------]
Vi starter med at sætte cell0 til 1 for at sikre, at vores løkke udføres mindst én gang. I et loop øger vi værdien af den aktuelle celle med 10, flytter datapointeren til den næste celle, læser et tegn og reducerer værdien med 10. På denne måde stopper programmet i næste iteration, hvis der læses et nyt linjetegn (10 i ASCII), ellers gendannes dets værdi ved at tilføje 10.
Efter dette trin vil vores celler se sådan ud:
11 C1 C2 C3 0* 0 0
Cn er det n'te tegn fra input, og * er den aktuelle dataposition. Nu skal vi begynde at flytte datamarkøren til venstre og udskrive alle celler, indtil vi når værdi 11. Her er mit bud på opgaven:
Jeg opfordrer dig til at analysere det på egen hånd :-).
Sammenfatning
Da jeg faldt over Brainfuck, et esoterisk programmeringssprog, afviste jeg det i første omgang som intet andet end en gimmick eller en joke. Dette særegne og, som mange måske vil hævde, ufatteligt svære sprog forekom mig kun at være beregnet til underholdning. Men med tiden ændrede min opfattelse af Brainfuck sig ret dramatisk.
Brainfucks gådefulde natur udfordrer dig og presser dig til at udvide dit perspektiv på programmeringssprog. Dette esoteriske sprog giver dig mulighed for at sætte pris på skønheden og nødvendigheden af de højniveausprog, vi er vant til. Det sætter fokus på betydningen af abstraktioner, korrekte navngivningskonventioner og et organiseret hukommelseslayout inden for programmeringssprog. Det er noget, som Brainfuck med sit minimalistiske design bestående af blot otte enkle kommandoer ikke tilbyder.
Brainfuck er et Turing-komplet sprog, der yderligere understreger vigtigheden af at have en klar, sammenhængende kildekode. På trods af at det er anerkendt som et af de mest udfordrende esoteriske sprog at skrive programmer i, skinner det ironisk nok som en begynderfavorit for alle, der ønsker at skabe deres egen Brainfuck-compiler eller Brainfuck-fortolker. Årsagen er enkelheden i kommandosættet og det faktum, at det ikke kræver kompleks parsing.
At lave et Brainfuck-program er unikt på to måder. For det første skal du vænne dig til at bruge en enkelt hukommelsespointer, hvilket tvinger dig til at tænke anderledes om din kildekode. Og for det andet har man 'zero option', som er muligheden for at nulstille hukommelsescellen til nul, en funktion, der ikke er almindelig i andre formelle programmeringssprog.
Når det gælder læring, er der mere end man tror, når det gælder Brainfuck. Hvis man har tid nok og den rette indstilling, er det muligt at skrive det samme program på mange forskellige måder ved hjælp af forskellige Brainfuck-koder. Den sidste halvdel af denne rejse handler om at være opfindsom og finde nye, kreative måder at bruge de seks symboler på.
Selvom Brainfuck-fortolkerne er minimalistiske, giver de dig en dybtgående forståelse af, hvordan koden kører, hvad programmet udskriver, og den underliggende mekanik i et Turing-komplet sprog. I sidste ende er Brainfuck ikke bare endnu et esoterisk programmeringssprog. Det er en helt ny dimension, et anderledes syn på, hvordan vi ser, forstår og skriver programmer.