HugoNikanors blogg‽ http://blog.hornquist.se/hugo A blog about nothing, but mostly itself. sv Välkommen! http://blog.hornquist.se/hugo/?filename=20150714Valkommen.md http://blog.hornquist.se/hugo/?filename=20150714Valkommen.md Tue, 14 Jul 2015 00:00:00 +0200

Främling, välkommen till Snökonungens rike!

-Gustav II Adolf, Civ V

Att ha en blogg verkade kul, så nu har jag en. Bloggen kommer mestadels att vara fokuserad på den teknik som intresserar mig för nuvarande, de program jag skriver samt de spel jag spelar. Den kan dock komma att innehålla andra saker ur mitt liv som jag anser relevanta att dela.

Bloggen kommer mestadels vara skriven på Svenska, vissa inlägg kan dock komma att vara skrivna på ett språk framförallt talat på andra sidan Atlanten.

Om allt fungerar som det ska kommer bloggen att uppdateras inta allt för infrekvent, förhoppningsvis minst en gång i veckan (men det är inte någonting du bör ta mitt ord för).

Nu hoppas jag att du tycker att det jag skriver är intressant att läsa.

/Hugo

]]>
Att bygga en webbsida http://blog.hornquist.se/hugo/?filename=20150715Att_bygga_en_webbsida.md http://blog.hornquist.se/hugo/?filename=20150715Att_bygga_en_webbsida.md Wed, 15 Jul 2015 00:00:00 +0200 #cssCool { background-color: pink; color: darkblue; border: 3px solid green; padding: 3px; letter-spacing: 2em; }

Att bygga den här webbsidan har varigt intressant för mig. När jag gick in i projektet kunde jag bara de absoluta grunderna i html, css samt php. Nu när jag dock har skrivit en webbsida är åtminstånde mina css kunskaper en

bra bit bättre.

Dock har det varigt intressant att bygga en webbsida och se alla delarna komma samman för att forma den helhet som du nu ser på skärmen.

Även om webbsidan nu är live så anser jag mig inte vara klar med den. Framförallt vill jag snygga till url:n. I nuläget så visas serverns IP adress istället för min domän http://hugoweb.ga. Det efter snedstrecket (blog.php?filename=20150715Att_bygga_en_websida.md) är någonting jag vill snygga upp. Så jag får väll ta och lära mig den regex jag behöver för det.
Jag hoppas att jag kan få url:n att se ut enligt följande:

http://hugoweb.ga/blog/20150715Att_bygga_en_websida


Servern kör från en gammal laptop, knappt stark nog att faktiskt göra någonting. Men förhoppningsvis kommer inte den lilla webbtrafik jag har knäcka den.

Bild på servern


Om någon råkar vara intresserad finns majoriteten av källan till den här sidan tillgänglig för nedladdning här.

]]>
Program av alla de slag http://blog.hornquist.se/hugo/?filename=20150804Program_av_alla_de_slag.md http://blog.hornquist.se/hugo/?filename=20150804Program_av_alla_de_slag.md Tue, 04 Aug 2015 00:00:00 +0200 Jag har skrivit några program av ifrågasättningsbar användbarhet. Alla programmen är testade och kompilerar utan problem på min Linux maskin. Hur vida de fungerar på Windows, eller över huvud taget, är upp till någon annan att testa.

Allting är skrivet i c++.


Alla ord

Ett litet program som skapar en textfil med alla bokstavskombinationer av en satt längd från de 26 (A - Z) bokstäverna.
Jag har lyckats köra programmet med 6 bokstäver. Då fick jag 26⁶ (308 915 776) olika kombinationer. Dock kunde jag inte se på allting då min textredigerare crashade. Körtiden var då 8 minuter.

Notera att programmet kör mycket snabbare om du har en SSD istället för en HDD.

Ett stycke av outputen:

...
cgib
cgic
cgid
cgie
cgif
cgig
cgih
cgii
cgij
cgik
cgil
...

Programmet var inspirerat av de böcker som nämndes i den, för tillfället, senaste videon från VSauce.


Yathzee simulator

Ett litet program som försöker slå yathzee (alla tärningar har samma sida upp) med ett av användaren bestämt nummer av tärningar. Programmet matar sedan ut hur många slag det tog, och de vinnande ögonen. Statistik på det får du göra själv.

Programmet get tyvärr inte någon output då det saktade ner det avsevärt. Om man vill kan man dock ganska enkelt redigera källkodsfilen för att få output.

Det mest anmärkningsvärda med ett annars oanmärkningsvärt program är testet om man har fått en Yathzee.

do {
    count++;
    for(int i = 0; i < noDices; i++) {
        dices[i] = rand() % 6 + 1;
        if(i != 0) {
            if(dices[i] != dices[i - 1]) {
                break;
            } else if(i == noDices - 1) {
                yathzee = true;
            }
        }
    }
} while(!yathzee);

Koden ovan visar hur programmet rullar en tärning åt gången, och kollar sedan om den har samma "värde" som den innan. Om den har det rullar programmet nästa tärning. Annars så börjar det om. En sidoeffekt av det systemet jag har är att man kan inte köra programmet med 1 tärning. Varför man nu skulle vilja det.


ASCIItabell

Och slutligen ett program som har så pass stor nytta att jag redan skrev det för länge sedan. Nu har jag bara piffat upp det lite grand.

Programmet skriver ut alla tecken i ASCII-8 tabellen. De tecken enkelt tillgängliga i c++. : Det jag nu har lagt till är möjlighet att få numreringen båda hexadecimalt och decimalt. Samt möjlighet att välja vid programkörning. Jag har dock noterat att åtminstone på min version av Ubuntu är stödet för tecken i ASCIItabellen högre än 127 nonexistent.

Tabellen ser ut enligt följande för er som inte själva vill köra programmet:

1f. �    20.      21. !    22. "    23. #    24. $    
25. %    26. &    27. '    28. (    29. )    2a. *    
2b. +    2c. ,    2d. -    2e. .    2f. /    30. 0    
31. 1    32. 2    33. 3    34. 4    35. 5    36. 6    
37. 7    38. 8    39. 9    3a. :    3b. ;    3c. <    
3d. =    3e. >    3f. ?    40. @    41. A    42. B    
43. C    44. D    45. E    46. F    47. G    48. H    
49. I    4a. J    4b. K    4c. L    4d. M    4e. N    
4f. O    50. P    51. Q    52. R    53. S    54. T    
55. U    56. V    57. W    58. X    59. Y    5a. Z    
5b. [    5c. \    5d. ]    5e. ^    5f. _    60. \`    
61. a    62. b    63. c    64. d    65. e    66. f    
67. g    68. h    69. i    6a. j    6b. k    6c. l    
6d. m    6e. n    6f. o    70. p    71. q    72. r    
73. s    74. t    75. u    76. v    77. w    78. x    
79. y    7a. z    7b. {    7c. |    7d. }    7e. ~

Majoriteten av övriga tecken visas med en sifferrepresentation av tecknet, eller med tecknet för saknat unicode tecken (�).

Nedladdning på GitHub


Disclaimer

Inget av programmen är garanterade att fungera.
Jag tillhandahåller ingen officiell support för dem.
Vid frågor kan det hända att jag har svar.

]]>
URL:er, eller? http://blog.hornquist.se/hugo/?filename=20150912URLer_eller.md http://blog.hornquist.se/hugo/?filename=20150912URLer_eller.md Sat, 12 Sep 2015 00:00:00 +0200 Är det inte kul att majoriteten av inlägg på bloggen handlar om hur jag kan sätta upp en webbsida att ha bloggen på!/s

Tidigare i veckan gick ett strömavbrott över staden, all elektronik slogs ut så pass länge att min internetleverantörs IP-adresser nollstäldes, men inget annat påverkades i någon större utskänkning.

Problemet med den här lilla nollställningen var att jag aldrig hade fått en ordentlig URL att fungera på min webbsida (här), vilket gjorde nästan alla gamla länkar obrukbara.

Därav har jag nu sätt till att hugoweb.ga faktiskt pekar till min IP-adress, på ett sådant sätt att det efter "snedsträcket" fungerar som förväntat. Därav fungerar inte längre alla URL:er jag har delat ut som har en IP som del av dem, eftersom IP:n nu är bytt. I framtiden kommer det dock bara vara mitt ansvar att se till att hugoweb.ga pekar på rätt IP-adress.


Eftersom jag ändå var i farten med att uppdatera min URL passade jag på att få den lite finare som jag tidigare nämnt att jag velat. Nu ser altså URL:erna ut enligt följande:

hugoweb.ga/blogg/20150912URLer_eller.md

Då de tidigare såg ut så här:

hugoweb.ga/blog.php?filename=20150912URLer_eller.md

De gamla URL:erna kommer fungerar fortfarande, och kommer troligen att alltid fortsätta att göra det, eftersom de nya skrivs om till de gamla i smyg. Dock kommer de att behöva uppdateras till att använda hugoweb.ga istället för 83.251.18.52, då den IP-adressen inte längre är min.

Omskrivningarna sker helt med Apaches url rewriting system, som jag fortfarande knappt förstår hur de fungerar.

Det största problemet med omskrivningarna var dock att under en tid fick jag de bara att fungera om jag satte serverns port till att vara en som inte är 80.
Någonting som jag efter mycket frustration kom fram till var för att det fanns en Virtual Host aktiv för just port 80, och dess regler hade företräde över de jag angav globalt. För nuvarande är det löst på det lagom eleganta sättet att VirtualHosten pekar på en port som inte används, medan de globala inställningarna skickar runt användarens URL:er till det du ser ovan.

]]>
I hopp om bättre kommentarer http://blog.hornquist.se/hugo/?filename=20150926I_hopp_om_battre_kommentarer.md http://blog.hornquist.se/hugo/?filename=20150926I_hopp_om_battre_kommentarer.md Sat, 26 Sep 2015 00:00:00 +0200 Jag tror på fri programvara (GNU GPL), den här bloggen är dock inte fri. Det som hindrar mig från att placera den under en fri licens är kommentarsfältet.

I ungefär en veckas tid har jag försökt kolla på alternativ till det nuvarande systemet, vilket är tillhandahållet av Disqus. Efter ett kort sökande fann jag Hashover, vilket är ett kommentarssystem skrivet just som ett fritt alternativ till Disqus. Det var dock en bra bit klumpigare än vad jag hade hoppats på.

Att få grundläggande kommentarsfunktionalitet att fungera med Hashover gick utan några större problem. Kommentarer var enkla att skriva, det var tydligare hur man kommenterade utan att logga in. Ingen epostadress krävdes. Dock började jag se fler och fler problem med systemet. Först var det små saker, som att "gilla" och "svara" knappen inte var vänstercentrerade korrekta. Det blev dock snart värre. Kommentarer gick inte att publicera när servern körde på en port utöver 80, ett problem som jag förvisso kunde hitta i koden och lösa, men det bådar inte gått när programmet man använder är så pass smalt anpassat. Jag märkte också att "svara" knappen inte fungerade och att avatarer (som ända hade varigt nästintill oanvända) inte laddade rätt utan visade en "saknad bild" markör.

Tillsammans hindrade alla dessa problem mig från att uppgradera mitt kommentarssystem. Troligen kommer jag, vid tillfälle, att göra ett nytt försök med att byta kommentarssytemet. Kanske försöker jag igen med Hashover, eller möjligen testar jag Hashover 2.0 som för nuvarande är under aktiv utveckling. Eller så skriver jag mitt helt egna system, som dock troligen skulle ha flertalet brister även det.


Det bör kanske också nämnas att kommentarerna från de tre första inläggen är försvunna från bloggen. Dock bör de finnas kvar i Disqus's arkiv (eftersom det mer eller mindre är ett vanligt internetforum). Förhoppningsvis kommer inga kommentarer att försvinna mer i framtiden. Det eftersom jag hittade att man kunde be Disqus låtsas om som att en sidan har en annan URL än den har. Vilket låter mig se till att alla länkar som pekar på samma inlägg får samma kommentarer. Grovt ilustrerat enligt kodsnutten nedan.

<?php
    $canon_url = 'http://' . $_SERVER['HTTP_HOST'] . getUrlFilename( 'default', $filename );
?>
<script>
    var disqus_identifier = '<?php echo($canon_url); ?>';
</script>
]]>
JavaFX, gymnasiearbete & livesändningar http://blog.hornquist.se/hugo/?filename=20151011JavaFX_gymnasiearbete_och_livesandningar.md http://blog.hornquist.se/hugo/?filename=20151011JavaFX_gymnasiearbete_och_livesandningar.md Sun, 11 Oct 2015 00:00:00 +0200 Mitt gymnasiearbete är igång, och eftersom det för nuvarande är mitt mest aktiva projekt tyckte jag att det kunde vara passande att skriva några rader om det.

Gymnasiearbetet innefattar ett fantasykortspel i samma anda som Magic the Gathering. Än så länge har jag skapat kod för att hantera informationen på korten, samt har jag ritat ut alla de olika korten och börjat förflytta dem på skärmen. Nedan följer ett kort klipp som visar det jag än så länge har åstadkommit.

A preview of the program

Programmet bygger enbart på JavaFX samt min egen kod. Ett val jag gjorde då JavaFX är skapligt väldokumenterat, samtidigt som jag ville bygga spelet så mycket från grunden som möjligt.

Tidigare har jag använt Javax swing, och den största skillnaden jag har blivit tvungen att anpassa mig till är att JavaFX kräver att det startas statiskt. Vilket för mig krävde en omstrukturering från att ha grafiken i en egen gren av programmet till att ha den fullt integrerad. Någonting som jag dock tror gör programmet bättre och överskådligare i slutändan.


Helt relaterat och fullständigt frikopplat har jag ibland börjat strömma min programmering online, på https://livecoding.tv/hugonikanor/. Det är inget stort, mest jag som sitter och försöker att inte lite bra kod skriven, samtidigt som jag tänker halvhögt om vad jag håller på med, samt försöker prata med de personerna som har vägarna förbi.

]]>
A new "A New Hope" http://blog.hornquist.se/hugo/?filename=20151216A_new_new_Hope.md http://blog.hornquist.se/hugo/?filename=20151216A_new_new_Hope.md Wed, 16 Dec 2015 00:00:00 +0100 Det kom visst ut en ny Star Wars film idag, och tydligen har jag sätt den. Eller möjligen "A New Hope" igen.

Jag ska börja med att säga att jag tyckte inte filmen var dålig, men samtidigt inte fantastisk.


I "Star Wars: A New Hope" börjar historien börjar med att en av huvudkaraktärerna blir tillfångatagen av imperiet strax efter att denne skickar iväg en liten robot med information som kan leda rebellerna till en seger.

Roboten med informationen tar sig till en annan person på en ökenplanet. Personens hem blir överfallet av imperiet och denne tvingas fly i "The Millenium Falcon".

Precis samma sak händer i "The Force Awakens". Dock slutar inte likheterna där.

  • De beger sig till en udda bar för att få information
  • imperiet har en Dödstjärna med vilken de spränger planeter.
  • En av dem är fånge på dödstjärnan och behöver räddas
  • Dödstjärnan har en tydlig svag punkt man kan slå ut från utsidan
  • Det finns en maskerad Sith, som den här gången är son och inte far till en av huvudkaraktärerna.
  • En av huvudkaraktärerna visar sig kunna "använda" kraften.
  • Samt många mer små referenser och scener som liknar de gamla...

Och som vi nu vet; Han Solo klarade "The kessel run" på mindre än 12 parsecs (och inte 14 som vissa tror).

The kessel run

]]>
Oj då, jag portade Vim... http://blog.hornquist.se/hugo/?filename=20160302Vim_var_det.md http://blog.hornquist.se/hugo/?filename=20160302Vim_var_det.md Wed, 02 Mar 2016 00:00:00 +0100 https://github.com/hugonikanor/vimcc

Till Minecraft finns det en liten hemmagjord modifikation av spelet som lägger till fullt programmerbara datorer vilka arbetar i Lua. Det var på en av dem som jag lärde mig stora delar av grunderna till min programmering.

Numera återvänder jag dock ibland till dem eftersom de tillhandahåller några små robotar vilka är mycket enkla att hantera.

Nu är det dock så att den inbyggda textredigeraren är usel! (sämre än ms notepad usel!) Vilket jag upptäckte när jag skulle göra några små ändringar till ett annat litet projekt. Därmed sätter jag ut för att lösa problemet. Jag börjar skriva en port av Vim.


Nyligen färdigställde jag en körbar version av programmet som knappt crashar och har majoriteten av de funktioner jag använder (åtminstone för små ändringar i filer). De flesta grundläggande rörelsekommanden finns, tillsammans med vissa redigerings och raderingsverktyg.

Textredigeraren i sig är inte allt för intressant, dock är det här det första programmet jag publicerat och berättat om där det finns folk som lyssnar (alltså inte här). En "port" har redan skrivits för ett annat mycket likt Minecraft mod av någon annan, eftersom han såg det behovet samt ansåg att min kod var så pass välskriven att ändringarna för ett lite annat system inte var några större problem.


I framtiden är målet att få klart de sista grundläggande funktionerna, men inte större än så. Det här var bara tänkt som ett litet projekt vilket skulle låta mig enklare göra mycket små filändringar inne i spelet. Och inte en komplett och perfekt port av redigeraren.

]]>
Schack http://blog.hornquist.se/hugo/?filename=20160319Schack.md http://blog.hornquist.se/hugo/?filename=20160319Schack.md Sat, 19 Mar 2016 00:00:00 +0100 Spela!

Centrering är svårt...

Under kvällen fick jag för mig att skriva ett litet schackbräde...

Ideén kom när jag insåg att det nog skulle vara ganska enkelt att rita upp ett schackbräde i html och css. Därefter insåg jag att för att kunna flytta runt spelpjäser behövde jag bara fånga upp alla knapptryckningar på brädet, och sedan flytta pjäsen från positionen av den föregående tryckning till den senaste tryckningens position.

Som en bieffekt av att html och javascript redan är ganska krosskompatibla mellan enheter fungerar spelet på det mesta. Dock behöver systemet ha tillräcklig unicode support då pjäserna är unicodesymboler.

Spelet kan spelas utan att ladda bloggen här.
Koden kan ses tydligare här.

]]>
Blogg version 2! http://blog.hornquist.se/hugo/?filename=20160327Blog2.0.md http://blog.hornquist.se/hugo/?filename=20160327Blog2.0.md Sun, 27 Mar 2016 00:00:00 +0100 Min lilla (och fortfarande ganska dåliga) bloggmotor är nu uppdaterad till sin andra version!

I somras lärde jag mig skriva PHP samtidigt som jag skrev den första versionen av min bloggmotor. Likt alla program skrivna i ett språk man knappt kan var koden skapligt usel. Så i veckan bestämde jag mig för att skriva om systemet till att vara snäppet bättre.

Målet med den nya motorn var inte att lägga till ny funktionalitet, utan göra den som fanns enklare att underhålla och bygga vidare på. Det medför att på sidan syns det ingen skillnad mellan den gamla och den nya.

En sak som dock ändrade sig är URLerna. Vilka nu är tillbaka i sin "fula" form. Jag planerar att syngga upp dem, men apaches omskrivningsssytem är aningen krångligt. Dock har jag sätt till att alla gamla "snygga" URLer fortfarande bör fungera. Med förbehållet att de omdirigerar än till en sådan URL som ni troligen ser ovan.

Den nya bloggmotorn finns tillgänglig på GitHub, dock för tillfället är det ganska uselt dokumenterad.

Kommentarer

Orelaterat till den nya motorn, men framprovocerat av den, är mitt nya kommentarssystemet. Tidigare använde jag Disqus kommentarsystem, Vilket jag inte uttryckt allt för höga tankar om. Därav har jag nu valt att skriva ett eget system.

Kommmentarssystemet är nästintill så simpelt det går. I textformuläret anger du ditt namn samt din kommentar. De skickas sedan till servern där ett PHP program tar hand om informationen och lägger till den till en MySQL databas. När kommentarerna sedan ska visas plockar PHP programmet på servern fram alla inlägg med kopplad till den nuvarande "artikeln" och sorterar dem i fallande tidsordning med den nyaste först.

Systemet stödjer även Markdown via Parsedown, om det finns tillgängligt. Markdown är ett formateringsspråk designat för att vara simpelt. Det använder vissa "enkla" kontrollkaraktärer, för att sedan omvandla texten till HTML. Nedan följer några exempel.

*text*   <i>text</i>
**text** <b>text</b>
#text    <h1>text</h1>

Om jag inte klantat till installationen bör det vara aktiverat nedan. Om någon vill prova det, eller bara skrika hårdare i den kommentar de ända skulle publicerat.

Koden för kommentarssystemet finns tillgängligt på github

]]>
Angående Pantsamlare http://blog.hornquist.se/hugo/?filename=20170813Pantsamlare.md http://blog.hornquist.se/hugo/?filename=20170813Pantsamlare.md Sun, 13 Aug 2017 00:00:00 +0200 I ett hål i marken levde en pantsamlare. I vanliga fall till nytta för stackars folk vilka anser att ens tid är värd mer en penningvärdet på en tomburk. Just denna dag ansåg dock folket att pantens värde faktiskt kunde vara värd någonting, någonting pantsamlaren sedan länge vetat.

Även om pantens ringa värde kan verka som en harmlös historia, ledde den snart till ett av historiens största konflikter. Historien börjar när en pantsamlare ansåg att alla burkar och flaskor dess ögon kunde se tillföll deras samlingar. Detta var någonting en grupp fattiga studenter inte höll med om.

Första anfallet var när pantsamlarna tog tydligt undanställda burkar, allt emedans de använde all sin list för att undvika folks illvilja. [1] Studenterna försökte stå emot, men oförberedda på ett anfall hade de ingenting att försvara sig med.

Utmattade efter ett förlorat första slag bestämde sig studenterna för att de fortfarande behövde pant, och gjorde som studenter gör och producerade ny pant. [2] Dock skulle inte denna pantproduktion länge få vara i fred. Långt innan chocken från föregående attack var glömda anföll pantsamlarna igen! Dock hade studenterna, genom sin gemensamma pantproduktion fått nya krafter och lyckades slå tillbaka och skydda sin pant.

Studenterna insåg att för att skydda sin pant måste drastiska åtgärder vidtas. Sakta men säkert börjades system byggas upp i hopp om att pantsamlarna inte skulle kunna anfalla igen. Även om det gav ett skydd gav inte de (enligt dem själva) tappra pantsamlarna upp.

Allt emedans skydd för tomburkarna byggdes upp började deras rikedomstid leda mot sitt slut. Burkarnas värde föll ständigt för pantsamlarna, och de började bli desperata. Vändpunkten kom dock den timmen pantsamlarna insåg att även glasflaskor i back är pant. I ett ädelmodigt [3] anfall försökte en pantsamlare ta både flaskor, back, och innehåll i ett enda stort svep. Till hans förtret var studenterna dock evigt vaksamma, och slog tillbaka med en sådan kraft att ingen pantsamlare någonsin mer syndes till på den platsen.

Hurvida historien om pantsamlaren är sann är en fråga få är änse om. Många historiker svär sin karriär på dess historiska betydelse, medans andra bara ser det som en simpel saga för att skrämma nyankommna studenter.


[1] Sedan textens skrivande har historikerna kommit fram till att pantsamlarnas försök till att undvika illvilja oftast bara ledde till större irritation hos vanligt folk. Även värt att notera att deras metoder ofta innefattade att låtsas inte förstå infödingarnas språk. Samt feltolka samtliga signaler vilka skickas emot dem.

[2] Efter det sorgliga bortspolandet av alla historisk bokföring om händelserna vet tyvärr ingen längre om hur studenterna producerade pant.

[3] Enligt vem? Ö. An.

]]>
Hur jag skrev "Hello, World!" i Rust http://blog.hornquist.se/hugo/?filename=20180103Hello_Rust.md http://blog.hornquist.se/hugo/?filename=20180103Hello_Rust.md Wed, 03 Jan 2018 00:00:00 +0100 Nyligen har jag funderat på att skriva en client till ett protokoll vilket agerar via TCP sockets. Min första tanke var att skriva det i C, eftersom det är ett simpelt språk. Tyvärr var alla exempel alldeles för krångliga, och innehöll stora mängder DNS av någon anledning. Efter viss diskussion om C, C++ och andra språk blev kom vi fram till att Rust nog var ett trevligt mellansteg.

Nu har jag hört att varje gång man börjar med ett nytt programmeringsspråk ska man alltid först skriva "Hello, World!". Så jag började jobba. Flera minuter efter att innan aldrig skrivit Rust innan var jag klar:

use std::io::prelude::*;
use std::net::TcpStream;

fn main () {
    let mut stream = TcpStream::connect ("127.0.0.1:8080").unwrap();

    let _ = stream.write(&[1]);
    let mut data = [0; 128];
    let _ = stream.read(&mut data);
    println!("{}", String::from_utf8_lossy(&data));
}

För att köra behöver först en "Hello, World!" server skapas, vilket enklast görs genom:

echo "Hello, World!" | nc -l 8080

När programmet sedan körs skrivs "Hello, World!" ut på skärmen. Jag överväger om det finns ett enklare sätt att få samma resultat. Men eftersom jag inte kan Rust kan jag inte uttala mig i frågan.

]]>
Mer RSS till folket http://blog.hornquist.se/hugo/?filename=20180104RSS.md http://blog.hornquist.se/hugo/?filename=20180104RSS.md Thu, 04 Jan 2018 00:00:00 +0100 Så många gånger har jag fått förfrågan om det finns något sätt att faktiskt följa den här bloggen. Vissa har ställt frågan precis så, allt emedans andra har bett om faktisk RSS. Nu har vi det.

Jag kan förstå att det finns förfrågan efter en feed. Bloggen är nog egentligen inte interessant nog för att kommas ihåg att öppnas och kollas. Samt så publicerar jag nya inlägg väldigt sällan (förutom just nu, då vi har ett streak på 2 dagar).

När jag lade till RSS funktionalitet till bloggmotorn insåg jag också hur hopplös den är. Ingen metadata är nämligen sparad i någon ordentlig databas. Istället får jag datum och kort titel från filnamnet. Lång rubrik från första raden i varje fil. Och författare är hårdkodat. Allt det gör att RSS strömmen nog inte är den vackraste, och saknar nog en hel del finurligheter som skulle kunna vara trevliga. Till exempel sammanfattningar av artiklarna, eller fina rubriker. Dock bör det fungera.

Länk till RSS. Finns även i övre högra hörnet av headern, om du inte redan noterat det enda elementet med färg på sidan.

]]>
Att Flytta en Webbsida http://blog.hornquist.se/hugo/?filename=20180123Att_flytta_en_webbsida.md http://blog.hornquist.se/hugo/?filename=20180123Att_flytta_en_webbsida.md Tue, 23 Jan 2018 00:00:00 +0100 Efter att ha övervägt det flera gånger har den här bloggen till slut flyttat in på min "riktiga" domän. Det som ledde ändringen var att jag ännu en gång blev utakstad från min lånade domän hugoweb.ga.

FreeNOM, vilket är varifrån jag lånade domänen, har en bra ide. Låna ut domäner till folk för snåla för att betala för en egen. Och aggera aggregator av de olika gratis topdomäner som finns. Tyvär kommer de också med krav. Jag har blivit tillfälligt utkastad för att servern inte pekade på någon HTTP server. För att servern inehåller för mycket spam (spambottar hittade kommentarerna, vilka för övrigt är påslagna igen). Den här gången har jag inte fått någon anledning eller notifikation om det. Därav har jag bara gett upp på att kunna få tillbaka den igen.

Bloggen ligger nu här på http://blog.hornquist.se/hugo, men kan även nås på http://blogg.hornquist.se/hugo. Vilket har den trevliga fördelen av nu kan flera användare enkelt köra sina bloggar parallelt under liknande urlr. För tillfället är dock jag den enda personen med en blogg här. Så http://blog.hornquist.se skickar en vidare hit.

]]>
A Monad is a Monoid in the Category of Endofunctors http://blog.hornquist.se/hugo/?filename=20190410monad.md http://blog.hornquist.se/hugo/?filename=20190410monad.md Wed, 10 Apr 2019 00:00:00 +0200 I have recently tried to get a better grip on how Monads in Haskell actually work. Mostly I was perplexed by the state monad; so I decided to go ahead and implement some of it in scheme.

Full source code available at my git server

Bind

I took bind, (>>=) as a base, giving some basic definitions for it.

(define-method (>>= (this <null>) proc) '())
(define-method (>>= (this <pair>)
                    (proc <procedure>))
  (apply append (map proc this)))

Binding on a list is simple mapping the function over the list, and concatenating together the results. Which is a way to model calculations with multiple return values. For example:

(>>= '(1 2) (lambda (x) (list x (1+ x))))
;; ⇒ '(1 2 2 3)

We also give the default binding of the sequence operator (>>) as

(define-method (>> (a <top>) (b <top>))
  (>>= a (lambda args b)))

Which is a direct match to Haskells default implementation:

m >> k = m >>= \_ -> k

Fmap

I could from there go back to map. Since a Monad is Monoid in the category of Endofunctors (whatever that means) everything that is a monad must also be a functor, something that can be mapped over. Leading to the very simple implementation of fmap, (<$>):

(define (<$> f m_)
  (>>= m_ (lambda (m) ((return m_) (f m)))))

Assorted bindings

As a quick side mark, I also implemented the do notation from Haskell with the simple macro

(define-syntax do
  (syntax-rules (<- let =)
    ((_ let ptrn = val rest ...)
     (match val
       (ptrn (do rest ...))))
    ((_ ptrn <- val rest ...)
     (>>= val (match-lambda (ptrn (do rest ...)))))
    ((_ a) a) ; Base case
    ((_ token rest ...)
     (>> token (do rest ...)))))

allowing forms such as the one used in implementing functor application

(define (<*> f_ i_)
  (do f <- f_
      i <- i_
      ((return f_) (f i))))

Other Fun Monads

From this I implemented a few different monads. Some trivial, like optional (maybe)

(define (div d)
  (if (zero? d)
      (nothing)
      (just (/ d))))

(mapM div '(0 1 2 3))
;; ⇒ [Nothing]

(mapM div '(1 2 3))
;; ⇒ [Just (1 1/2 1/3)]

and writer

(run-writer
  (do "Hello, "
      "World"
      (return-writer 10))))
;; ⇒ '(10 "Hello, World")

The interesting one, which prompted this whole project, is however:

State

To start of, an example:

(run-state
  (do let y = 7
      (modify (lambda (x) (+ x y)))
      (get))
  10)

The state monad requires at least the get and put procedures which works "inside" it, along with run-state, which runs a composition of "stateful"* procedures and returns a "regular" value.

The interesting parts are however how it is implemented. State is internally created in two parts. One is the <state> type, which simply is a procedure which maps state pairs to state pairs. And the other is (thankfully) state pairs.


The implementation both uses the define-stateful macro, which creates functions that creates functions which take state pairs as a secondary argument, and returns state mappers.

(define-syntax-rule (define-stateful ((proc args ...) st) body ...)
  (define (proc args ...)
    (make-state ; creates <state> objects
     (lambda (st) body ...))))

From there get and put are trivially implementable as

(define-stateful ((get) st-list)
  "Sets the return value of state to st."
  (match st-list
    ((_ st)
     (list st st))))

and

(define-stateful ((put v) st-list)
  "Sets st to v."
  (list '() v))

From here we can then build up further abstraction without ever caring about how state actually is implemented. for example, a simple (and probably buggy) stack implementation:

(define (pop)
  (do st <- (get)
      let top = (car st)
      (put (cdr st))
      (return-state top)))

(define (peek)
  (do st <- (get)
      (return-state (car st))))

(define (push v)
  (do st <- (get)
      (put (cons v st))))

* The whole point of the state monad is to emulate state, without actually modyfying anything

Everything is a Monad

I also realized that we can give a definition for bind for all types which lack their own.

(define-method (>>= (a <top>) (proc <procedure>))
  (proc a))

This has the fun effect that it allows all values to act as belonging to the same monad, the monad of the primitive scheme type. So expressions such as (>>= 1+ 10) ; ⇒ 11, and (<$> 1+ 5) ; ⇒ 6 suddenly work.

About Monoids

I however still don't understand why a Monad is a Monoid. A Monoid (ℝ, ×) is as known just pair between a group ℝ, and a binary operation ×, which is closed under application of the operator, is associative, and have a "0" element which any applied together with any other object results in the other object.

I do see that monads have many of these characteristics, with >> sort of acting like ×, but I'm missing at least one piece for understanding the whole puzzle.

Refrences

Further Reading

]]>
Wolfenometry http://blog.hornquist.se/hugo/?filename=20190615Wolenometry.md http://blog.hornquist.se/hugo/?filename=20190615Wolenometry.md Sat, 15 Jun 2019 00:00:00 +0200 As is well known Wolfenstein 3D is a 2D game, which uses simple raycasting to figure out the distance from the player to the wall's in front of her. As a small hobby project I set out to recreate this. Since my levels (like the original) are bound to a strict grid we don't actually have to do a "real" ray-caster. But can instead just calculate the distance to next tile-border the ray will pass through, and immediately jump there.

This should have been easy, but due to a number of bad missteps on my parts (mostly involving trying to decide my move based on if my angle was pointing left-right or up-down) it took way to long to figure out the proper equations.

In the end it was as simple as:

(define (find-next-wall x y a callback)
  (let ((dx-ampl (mod (* -1 (sgn (cos a)) (decimals x)) 1))
        (dy-ampl (mod (* -1 (sgn (sin a)) (decimals y)) 1)))
    ;; Try moving to vertical wall
    (let* ((dx (* 1.01 dx-ampl (sgn (cos a))))
           (dy (* dx (tan a))))
      (if (<= (abs dy) dy-ampl)
          (callback (+ x dx) (+ y dy))
          ;; if that failed, try horizontal wall instead
          (let* ((dy (* 1.01 dy-ampl (sgn (sin a))))
                 (dx (* dy (cot a))))
            (callback (+ x dx) (+ y dy)))))))

Along with a trivial decimal-truncation and array reference to check if a given square contains a wall or not. The end result looks rather ok, except some fish-eye effect and bad color blending.

Full Source

Screenshot

]]>
Macro Walking http://blog.hornquist.se/hugo/?filename=20191223Macro_Walking.md http://blog.hornquist.se/hugo/?filename=20191223Macro_Walking.md Mon, 23 Dec 2019 00:00:00 +0100 Understanding Lisp-macros is hard, even harder is understanding how to effectively use them. Here I delve deeper into code walking through macros on my journey to really understand what makes Lisp macros, and by extension Lisp, unique.

One of the best information sources for advanced macros I have found is the book Let over Lambda, which I'm currently (slowly) making my way through. So far the major take-away from it is that macros are my tool for parsing lisp code [Section 5.4].


The code in this page is written in Guile, but most of it is applicable to any Lisp. Syntax-case appears to be non-standard.

Let Lazy & Symbol Macros

One really simple, but still powerful example of code walking through macros is let-lazy; a variant of let which creates lazy bindings, and only evaluates them on demand. [1].

Just to be clear, the expected behavior is the value of a binding is only evaluated if needed, and then only evaluated once. For example:

(let-lazy ((x (begin (display "Hello\n")
                     10)))
  (+ x x))
⊣ Hello
⇒ 20

(let-lazy ((x (begin (display "Hello\n") 10)))
  'x)
⇒ x

Also note that this isn't possible to achieve with functions in an eager language, since function parameters are evaluated before a function is called.

[1] This assumes that our Lisp already has `delay` and `force` forms. Otherwise they are not much more than wrapping a value in a function, and calling the function to get the value (caching it for future accesses along the way).

My first naïve solution used a simple macro, along with a manual tree-map.

;; apply proc to each node in tree, keeping structure.
;; optionally pass descend: #f to skip a branch.
(define* (tree-map proc tree #:key (descend (const #t)))
  (cond ((not (list? tree)) (proc tree))
        ((null? tree) '())
        ((list? (car tree))
        (cons (if (descend (car tree))
                (tree-map proc (car tree) #:descend descend)
                (car tree))
            (tree-map proc (cdr tree) #:descend descend)))
        (else (cons (proc (car tree))
                    (tree-map proc (cdr tree) #:descend descend)))))

(define (quote? form)
  (and (not (null? form))
       (eq? 'quote (car form))))

(define-macro (let-lazy bindings . body)
  (let ((keys (map car bindings)))
      `(let ,(map (lambda (b) `(,(car b) (delay ,@(cdr b))))
                  bindings)
      ,@(tree-map (lambda (t) (if (memv t keys) `(force ,t) t))
                  body #:descend (negate quote?)))))

It works decently, but quickly brakes down. For example, something as simple as a back-tick in the body breaks it.

(let-lazy ((x (begin  (display "Hello\n") 10))) `x)
⇒ (force x)

And as Let over Lambda mentions, there are many more special forms in a lisp than expected, and continues to issue the following Common Lisp example, where exactly one of the following blah should be expanded.

(let (blah (blah (blah blah)))
  blah)

;; Borrowed from Let over Lambda under fair use.

My updated solution instead uses my underlying Lisp interpreter to handle my variable substitution. In the bellow example I introduce my field mappings in a let-syntax towards the bottom, followed by me giving control back to scheme to figure the rest of the tree out.

(define-syntax let-lazy
  (syntax-rules ()

      ;; Match rule, and capture symbols
      [(_ ((field value) ...)
          body ...)

       ;; give symbols their delayed slots
       (let ((field (delay value)) ...)
          ;; introduce local syntax for replacing fields with
          ;; their forced counterparts
         (let-syntax ((field (identifier-syntax (force field))) ...)
           body ...))])).

The macro is also rewritten in scheme's hygienic macro system. Here it doesn't make a big difference, but identifier-syntax gets happier, and I sleep better knowing that symbols don't slip in our out of macro-expanded code.

Structures and Self Reference

Another more practical example (which actually was written earlier) was my attempt to create objects with an implicit reference to self, similar to C++ or Java. In this example my end goal was a way to generate static configuration files [2], so I could do away with updating slots.

[2] I later realized I just reinvented Puppet.

After expansion my forms look more or less like

(define struct-1
  `(a (b ,(lambda (self) (get-field self '(c)))))).

Of note is that the field /a/b wants the value /c, which is allowed since it doesn't get evaluated before I actually instantiate the object, and that my system allows for rudimentary inheritance.

Before expansion the same information is written:

(struct struct-1 ()
    (a (b ,(? c))))

Which is rather similar. But keep in mind that the (? c) can be deep within arbitrary other code.


The base macro struct is just basic setup, but is here for completeness sake,

;; Comments added for this article.

(define-syntax struct
  (lambda (stx)
    (syntax-case stx ()
      [(_ name (parent ...) (key value ...) ...)

       ;; allow the symbol `?' to be used within the
       ;; input. Required due to hygienic macros
       (with-syntax ((? (datum->syntax stx '?)))
         #'(define name
             ;; Call to inner
             (let ((new-data (inner ? (acc-name ,(symbol->string 'name))
                                    (key value ...) ...)))

               ;; Inheritance (mostly unimportant)
               (lambda (mergable)
                 (alist-merge mergable
                              (fold $ new-data
                                    (list parent ...)))))))])))

Inner is however where all the fun stuff happens! To get it out of the way: all rules takes ? due to above mentioned hygienic macros, the leaves of the tree are wrapped in functions to delay evaluation, and the first case below matches on unquote (,) in a stroke of ingenuity madness when I realized that I could hijack scheme's syntax for my own bidding.

(define-syntax inner
  (syntax-rules (unquote)
    ;; case 1
    [(_ ? (unquote value))
     (lambda (self)
       ;; actually give a value to `?'
       (let-syntax ((? (with-ellipsis
                        .. (syntax-rules ()
                             [(? path ..) (get-field self `(path ..))]))))
         ;; give scheme the job to find all intances of (? ...)
         value))]

    ;; case 2
    [(_ ? (key sub ...) ...)
     (sort* `((key ,(inner ? sub ...)) ...)
            symbol<=? #:get car) ]

    ;; case 3
    [(_ _ v v* ...)
     (lambda _ (values `v `v* ...))]))

Relevant to code walking and macros is case one. The self is captured, the ? is finally given a value through let-syntax, which uses our captured self in a simple call to get-field. The core is still the same as above; introduce a binding with let-syntax and let our scheme do the job of finding all appropriate instances of our symbol. Here we just have more fancy stuff around it.


The scripts in their entirety can be found on GitHub, even though it feels a bit to intimate to share them this way. Struct there is called account, due to the code's original use case.

References

Let over Lambda

Full Scripts

]]>
Up Again! http://blog.hornquist.se/hugo/?filename=20211029Up_again.md http://blog.hornquist.se/hugo/?filename=20211029Up_again.md Fri, 29 Oct 2021 00:00:00 +0200 My blog (and server in general) is up again! I still host it on that puny server. The problem was however that my parents ISP earlier misbehaved with their DHCP-server, and their front line support not knowing anything.

ComHem has however since been bought by Tele2, and while I can't vouch for their customer service, they have at least configured their DHCP server correct, allowing both their home router and this server to get their public IP:s as expected.

Now we just hope that everything keeps working until we finally get IPv6.

]]>
Lisps Quasiquotation http://blog.hornquist.se/hugo/?filename=20220616Quasiquote.md http://blog.hornquist.se/hugo/?filename=20220616Quasiquote.md Thu, 16 Jun 2022 00:00:00 +0200 A while ago I noted that macros are the tool for handling code. I have since then realized just how powerful they are when left to their own devices. Previously I believed that quasiquotation would be hard to implement, having to seek the whole tree for unquotes, but the macro is simply

(define-syntax quasiquote
  (syntax-rules (unquote unquote-splicing)
    ((_ ,form)              form)
    ((_ (,@forms rest ...)) (append forms `(rest ...)))
    ((_ (lit     lits ...)) (cons   `lit  `(lits ...)))
    ((_ a)                  'a)))
]]>
When C Looks Like Java http://blog.hornquist.se/hugo/?filename=20221115When_C_Looks_Like_Java.md http://blog.hornquist.se/hugo/?filename=20221115When_C_Looks_Like_Java.md Tue, 15 Nov 2022 00:00:00 +0100 A while ago on r/programminghorror someone posted this beautiful code snippet:

private static int stringSize(String s){
    int size = 0;
    for (int i = 0; i < s.length(); i++) {
        size++;
    }
    return size;
}

It was initially tagged C, which someone commented on.

Why is this tagged as C? Pretty sure this is Java or a similar language.

TheGhostOfInky

Which got the response (with the name removed since they removed their comment).

Its definitely legal c code, don't know what you're on about

[DELETED]

I however got slightly nerd-sniped by this. Could this be legal C code? Unfortunately not, since private isn't a function or storage-class specifier in C. But for arguments say lets assume someone has a null macro as some form of weird inline documentation.

#define private

This leaves us with s.length(). It's obviously legal C, assuming that String is a typedef:ed struct containing a function pointer length, e.g.

typedef struct String {
    size_t (*length)(void);
    /* ... */
} String;

This however doesn't seem to help us. Length has no way to known who called it, since there is no this object in C. Or is there some way to find this information‽

The object s must reside on the call stack (since we access the method with a period[1]). So if we could access the call stack, and have some way of identifying the string object then we could just search the stack until we find it. The top of the stack could theoretically be accessed by taking the address of a stack allocated variable. C however officially doesn't have a stack between procedures, so instead I opt for the GNU extension __builtin_frame_address. I then place a magic value at the start of each String, and search for that value.

Is it stupid? Yes. Does it work? Barely? Should you do this? Maybe in C++.

Code Listing

Here's a complete and compilable code listing for the stuff described above.

It compiles with 0 warnings and errors, through gcc -std=gnu11 -Wall -O0 main.c, but once we increse the optimization level it segfaults.

#include <stddef.h>
#include <string.h>
#include <stdio.h>

#define private

/* Magic cookie used to find strings on stack */
#define COOKIE 0xA1891EE4C9E90839

typedef struct String {
    unsigned long long cookie;
    size_t (*length)(void);
    char *data;
} String;

/* Find our magic cookie on stack, and return that string */
String *find_string(void) {
    /* __builtin_frame_address is a GNU extension. This is tested on
     * x86_64 Linux, and will most likely break elsewhere */
    for (char *sp = __builtin_frame_address(0);; ++sp) {
        if (*((unsigned long long *) sp) == COOKIE) {
            return (String*) sp;
        }
    }
}

size_t string_length(void) {
    return strlen(find_string()->data);
}

String make_string(char *data) {
    return ((String){
        .length = &string_length,
        .data = data,
        .cookie = COOKIE,
    });
}

private static int stringSize(String s) {
    int size = 0;
    for (int i = 0; i < s.length(); i++) {
        size++;
    }
    return size;
}

int main() {
    String s = make_string("Hello, World!");
    printf("%d\n", stringSize(s));
}

Footnotes

  1. role="doc-endnote" id="footnote1">

    It could techically be passed by register. It however probably isn't since the structure looks rather heavy (containing its own vtable).

]]>
Yet Another Static Site Generator http://blog.hornquist.se/hugo/?filename=20230227Yet_Another_Static_Site_Generator.md http://blog.hornquist.se/hugo/?filename=20230227Yet_Another_Static_Site_Generator.md Mon, 27 Feb 2023 00:00:00 +0100 I recently released my very own static site generator! For the time being simply called ssg. It supports pages, templates, entries, and static files. But its "selling point" is its widget system.

A widget is reference to a (small) code fragment which can be referenced from a pages source code, for example:

Contact me at [[mailto:hugo@example.com]].

Would expand through the following widget

(define (widget address)
  (delay
    `(a (@ (href "mailto:" ,address)) ,address)))

Which eventually would resolve into

Contact me at <a href="mailto:hugo@example.com">hugo@example.com</a>.

It remains to see if rolling your own site generator is a good idea, or if I should take time to actually learn some existing ones. This blog switching to SSG would be a good indicator that I at least believe a bit in it.

Source Code: https://git.lysator.liu.se/hugo/ssg
A page using the system: https://for3.lysator.liu.se (Archived version)

]]>
Gotta Deploy em All http://blog.hornquist.se/hugo/?filename=20230417Gotta_Deploy_em_All.md http://blog.hornquist.se/hugo/?filename=20230417Gotta_Deploy_em_All.md Mon, 17 Apr 2023 00:00:00 +0200 https://hugonikanor.github.io/pokemon-stuff

I have recently played a bit of Pokémon, trying to finally complete my Platinum living dex. Keeping track of which 'mons I was missing was however becoming ever more difficult, since many of the "empty" spaces where filled with extra Pokémon which I didn't have the heart to release (or simple needed for trade fodder later). The solution was obvious: create a program to help me with the tracking!

https://github.com/HugoNikanor/pokemon-stuff

With a working prototype in hand I realized I wanted to share the program, but didn't feel comfortable self-hosting it, since I don't have any proper deployment chains at the moment. So why not deploy it on someone else's server, while simultaneously testing another CI/CD system in to better understand what I want myself.

https://github.com/HugoNikanor/pokemon-stuff/blob/master/.github/workflows/main.yml

Writing the workflow took quite a few tries. GitHub actions are sufficiently documented, if you know where to look. I didn't. I however eventually figured out how to share artifacts between jobs (but not between different jobs...), and how to automatically deploy to GitHub pages. The major hurdles to overcome was that the actions/deploy-pages@v2 module didn't make it to clear which format it wanted its input on, and that it, along with actions/upload-page-artifacts@v1.0.8 specified that a gzipped tarball was needed, while only providing a non-zipped one (which thankfully worked).

The final result is available at https://hugonikanor.github.io/pokemon-stuff, and my current "save file" is

000000000000000000000000000000000000100000000000000000000000800500e00080012000000083012a00001c200200000000c0001000000000000c

It's unfortunately Base16 encoded instead of Base64 encoded, since JavaScripts atob and btoa procedures insisted on the binary data being valid strings, which kind of defeats the point.


A footnote about Spriters Resource: The Pokémon sprites used are pulled from Spriters Resource (see the GitHub action). These are obviously "stolen", which makes me find it interesting/humorous that so many demand credit for their work. In this case credit is actually given, by me exporting the un-cropped sprite sheet to the client (not displaying it, but it's technically there).

]]>