einzug
sitemap.org: site/.published
site/.published: index.org external-rss.org $(arnebab_DATA) setup.el .emacs.d/init.el ## create and publish the site according to setup.el
rsync -ruv assets/ site/assets
- echo -e Yes\\nYes > $$(tty) ; Xvfb :3 -screen 0 1024x768x16 & time DISPLAYY=:3 GUILE_QUIET=1 HOME="$(realpath @abs_top_builddir@)" timeout 300 emacs --load .emacs.d/init.el --load setup.el "$<" --eval "(setq org-babel-ditaa-java-cmd \"LD_LIBRARY_PATH=$${LD_LIBRARY_PATH}:$$HOME/.guix-profile/lib/ java\" plantuml-executable-path \"plantuml\" org-plantuml-jar-path \"$${GUIX_ENVIRONMENT=/home/$(whoami)/.guix-profile}/share/java/plantuml.jar\" org-plantuml-exec-mode 'plantuml)" --eval '(org-publish-current-project "arnebab-org")' -f kill-emacs && touch "$@" < $$(tty) > build.log || time DISPLAYY=:3 GUILE_QUIET=1 HOME="$(realpath @abs_top_builddir@)" timeout 1800 emacs --load .emacs.d/init.el --load setup.el "$<" --eval "(setq org-babel-ditaa-java-cmd \"LD_LIBRARY_PATH=$${LD_LIBRARY_PATH}:$$HOME/.guix-profile/lib/ java\" plantuml-executable-path \"plantuml\" org-plantuml-jar-path \"$${GUIX_ENVIRONMENT=/home/$(whoami)/.guix-profile}/share/java/plantuml.jar\" org-plantuml-exec-mode 'plantuml)" --eval '(org-publish-current-project "arnebab-org")' -f kill-emacs && touch "$@" < $$(tty) > build.log && rm -f site/*~ site/*/*~ site/*/*/*~ site/*/*/*/*~ && rm -r site/.emacs.d/
+ echo -e Yes\\nYes > $$(tty) ; Xvfb :3 -screen 0 1024x768x16 & time DISPLAYY=:3 GUILE_QUIET=1 HOME="$(realpath @abs_top_builddir@)" timeout 300 emacs --load .emacs.d/init.el --load setup.el "$<" --eval "(setq org-babel-ditaa-java-cmd \"LD_LIBRARY_PATH=$${LD_LIBRARY_PATH}:$$HOME/.guix-profile/lib/ java\" plantuml-executable-path \"plantuml\" org-plantuml-jar-path \"$${GUIX_ENVIRONMENT=/home/$(whoami)/.guix-profile}/share/java/plantuml.jar\" org-plantuml-exec-mode 'plantuml)" --eval '(org-publish-current-project "arnebab-org")' -f kill-emacs && touch "$@" < $$(tty) > build.log || time DISPLAYY=:3 GUILE_QUIET=1 HOME="$(realpath @abs_top_builddir@)" timeout 1800 emacs --load .emacs.d/init.el --load setup.el "$<" --eval "(setq org-babel-ditaa-java-cmd \"LD_LIBRARY_PATH=$${LD_LIBRARY_PATH}:$$HOME/.guix-profile/lib/ java\" plantuml-executable-path \"plantuml\" org-plantuml-jar-path \"$${GUIX_ENVIRONMENT=/home/$(whoami)/.guix-profile}/share/java/plantuml.jar\" org-plantuml-exec-mode 'plantuml)" --eval '(org-publish-current-project "arnebab-org")' -f kill-emacs && touch "$@" < $$(tty) > build.log && rm -f site/*~ site/*/*~ site/*/*/*~ site/*/*/*/*~ && rm -rf site/.emacs.d/
$(minified_assets) : assets/.minified
assets/.minified : $(wildcard assets/*png) assets/shrink.sh
:FEEDSTATUS:
-(("https://rollenspiel.social/@ArneBab/115122468716434622" t
- "fe994bfed5d90064151ba755aac0a13bc35a4236")
- ("https://rollenspiel.social/@ArneBab/115125584815231337" t
- "2f3d4e05d6cf1b1762317de9d9a84fbfe8073583")
- ("https://rollenspiel.social/@ArneBab/115133632804567546" t
- "94bc937e434a4f9e3e2cd1d7f04da3c469805076")
- ("https://rollenspiel.social/@ArneBab/115136028248606311" t
+(("https://rollenspiel.social/@ArneBab/115136028248606311" t
"34f19d8436ed94cf678b75ccf4148c355fa9a580")
("https://rollenspiel.social/@ArneBab/115138955680665065" t
"29b1c9718328fd86d88173bd549af0ed35965a01")
("https://rollenspiel.social/@ArneBab/115187704767751893" t
"7aa157387b7784d39fd820e2c92b263ad1f51ead")
("https://rollenspiel.social/@ArneBab/115189998202683635" t
- "2657c5109bfdd5f06fdb88298bc454723d2a96a0"))
+ "2657c5109bfdd5f06fdb88298bc454723d2a96a0")
+ ("https://rollenspiel.social/@ArneBab/115196736864616766" t
+ "1ccfa08838770d365baffd3f423b106935a32a93")
+ ("https://rollenspiel.social/@ArneBab/115199191123908160" t
+ "851d5e4bce2a6376a5330afafe4c603e26a93f06")
+ ("https://rollenspiel.social/@ArneBab/115202424900336551" t
+ "8650f71c4f69cb0c8ce4c51638d542cd86e9c844"))
:END:
+** [2025-09-14 So 11:31]
+ while wealth_breeds_wealth and wealth_gives_power:
+
+https://www.draketo.de/censor-the-net
+
+ [[https://rollenspiel.social/@ArneBab/115202424900336551]]
+
+
+** [2025-09-13 Sa 21:49]
+ “How can you be so certain it was the devil who fell?”
+
+
+Can you guess the source of this #quote?
+
+
+#anime
+
+ [[https://rollenspiel.social/@ArneBab/115199191123908160]]
+
+
+** [2025-09-13 Sa 11:25]
+ "DU willst heute die AfD wählen? Dann hör kurz zu."
+
+https://www.youtube.com/watch?v=yD5He4wqhg4
+
+
+#politik nrw KommunalwahlNRW
+
+ [[https://rollenspiel.social/@ArneBab/115196736864616766]]
+
+
** [2025-09-12 Fr 06:51]
Yesterday was 9/11 - 24 years ago now - it’s crazy how much the world
changed.
[[https://rollenspiel.social/@ArneBab/115136028248606311]]
-** [2025-09-02 Di 07:56]
- TIL¹ that the US government did not know that agent orange would
-monstrously destroy people in Vietnam.
-
-
-Because Monsanto and Dow claimed it would “only” destroy the forest,
-but be harmless to people.
-
-
-Even though they had explicitly been warned of the danger to humans by
-German pesticide companies: the production method caused contamination
-with dioxin.
-
-
-And Monsanto workers had already fallen sick in 1949.
-
-
-Source: https://www.youtube.com/watch?v=CxVXvFOPIyQ
-
-
-¹ today I learned
-
- [[https://rollenspiel.social/@ArneBab/115133632804567546]]
-
-
-** [2025-08-31 So 21:50]
- Heute einen neuen Charakter erschaffen: Iginio di Martino, als Kind
-aus Italien nach Deutschland gebracht, dort Richter geworden und jetzt
-bei Kreuzrittern im Heiligen Land.
-
-
-Rechtschaffen, Gläubig, Verloren, und mit einem Rabenschädel, den er
-bei einer Flamme gefunden hat, die er richten musste.
-
-
-Sein Vorgänger opferte sich im Kampf gegen einen Götzendiener und
-rettete so seine Seele. Oder verdammte sie, das wissen wir nicht
-genau …
-
-#Cthulhu Mittelalter pnpde
-
- [[https://rollenspiel.social/@ArneBab/115125584815231337]]
-
-
-** [2025-08-31 So 08:37]
- Die Rechtsextremistin Liebich hat sich wohl ins Ausland abgesetzt,
-nachdem alle Medien über ihr Stöckchen gesprungen sind:
-
-
-https://www.deutschlandfunk.de/behoerden-fahnden-nach-liebich-106.html
-
-
-Die ganze Panik über das Frauengefängnis war also erstmal viel Lärm um
-nichts.
-
-
-Wieso genau fallen wir immer wieder auf die Provokationen von
-Rechtsextremist:innen herein?
-
- [[https://rollenspiel.social/@ArneBab/115122468716434622]]
-
-
* Gute Neuigkeiten
important disagreements to be worked out” ← das hieß es immer
wieder, und dann hat die Hamas abgelehnt. Zu sagen, dass “truce
within reach” war, ist also Spekulation.*
+- “Netanyahu told him that Hamas had finally softened its negotiating
+ position. »We may have a deal,« Netanyahu said … Ben-Gvir swiftly
+ intervened … Netanyahu refused to come outside. Ben-Gvir turned to
+ social media” ← *Netanyahu hat versucht, Ben-Gvir zu umgehen, um den
+ Waffenstillstand zu ermöglichen. Das zerbricht die weitverbreiteten
+ Dämonisierungs-Narrative über Netanyahu.*
- “when Gideon Saar, an opposition leader, agreed to shore up
Netanyahu’s majority … far harder for Ben-Gvir and Smotrich to make
ultimatums” ← *das sollte der CDU eine Warnung sein, dass sie
:END:
#+BEGIN_SRC sh :eval yes :exports results :results output raw
- for i in $(ls rollenspiel | grep \\.org$ | grep "^flight.org$\\|^love-country.org$\\|^nyarlathotep.org$\\|^schlange.org$"); do echo '- [[file:rollenspiel/'$i']['$(basename $i .org)']]' - $(grep '#+title:' "rollenspiel/$i" | sed 's/#+title: *//'); done
+ for i in $(ls rollenspiel | grep \\.org$ | grep "^flight.org$\\|^heilig.org$\\|^love-country.org$\\|^nyarlathotep.org$\\|^schlange.org$"); do echo '- [[file:rollenspiel/'$i']['$(basename $i .org)']]' - $(grep '#+title:' "rollenspiel/$i" | sed 's/#+title: *//'); done
#+END_SRC
-
* ⚅ Weitere
:PROPERTIES:
:CUSTOM_ID: weitere
:END:
#+BEGIN_SRC sh :eval yes :exports results :results output raw
- for i in $(ls rollenspiel | grep \\.org$ | grep -v "^flight.org$\\|^love-country.org$\\|^nyarlathotep.org$\\|^schlange.org$"); do echo '- [[file:rollenspiel/'$i']['$(basename $i .org)']]' - $(grep '#+title:' "rollenspiel/$i" | sed 's/#+title: *//'); done
+ for i in $(ls rollenspiel | grep \\.org$ | grep -v "^flight.org$\\|^heilig.org$\\|^love-country.org$\\|^nyarlathotep.org$\\|^schlange.org$"); do echo '- [[file:rollenspiel/'$i']['$(basename $i .org)']]' - $(grep '#+title:' "rollenspiel/$i" | sed 's/#+title: *//'); done
#+END_SRC
------
-/Das Dryadenbild stammt von Trudy Wenzel. Danke!/
+/Das Dryadenbild stammt von Trudy Wenzel --- danke!/
# TODO: category needs no level, because it must not include the setupfile anyway
#+setupfile: org-templates/level-0-rollenspiel.org
- ?: Ist doch alles gleich hier, dieses Gesocks!
- G: Nein, ist es nicht, seht sie trägt das Zeichen unseres Herrn.
- ?: Ihr sprecht mit Baron Franck de Montblanc!
-- G: Erinnert euch an die Vorgaben Gottfried von Buillons.
+- G: Erinnert euch an die Vorgaben Gottfried von Bouillons.
Der Mann hat sich um die Besitztümer der Kirche gekümmert. Wir fragen
ihn, ob er auch die Burg verwalten kann. *Dawud ibn Habil*.
#+begin_quote
*Gefolge/Bedienstete*:
-- *Ritter Burkhart* mit drei Rittern und einem Invaliden.
+- *Ritter Burkhart* mit drei Rittern und einem Invaliden. *Gustav*,
+ *Guntherr* und *Hagen*. Und *Gausbert*.
- *Verwalter Dawud ibn Habil* mit Familie.
- *Sechs frühere Huren mit angetrauten Kämpfern*.
- *Sechs frühere Huren mit angetrauten Handwerkern*.
#+end_quote
+* Einzug
+:PROPERTIES:
+:CUSTOM_ID: einzug
+:END:
+
+Die Araber plappern als unsere Reisegesellschaft die Taschen auflädt.
+*Linhard, Gregorius, Ritter Burkhart* und seine Ritter sitzen auf. Der
+Verwalter *Dawud ibn Habil* fährt mit mir auf dem Wagen. Die neuen
+Eheleute bleiben noch in der Stadt.
+
+Ein kleiner Tross guter Pferde mit Gepäck kommt hinterher, damit sie
+nicht gestohlen werden. Am dem Meer entlang, auf dem selbst Tote
+schwimmen.
+
+Nach einigen Stunden enden die Verwüstungen des Krieges. Ein karges
+Land, aber von Bauern bewirtschaftet. Linhard sieht einen Reiter, der
+aus der Höhe auf uns herab blickt.
+
+Linhard schickt Ritter *Hagen* voran, um nach einem Hinterhalt
+Ausschau zu halten. Gegen Abend deutet Hagen auf ein Dorf. Als wir in
+Sichtweite kommen, verschwinden die Dörfler von den Straßen.
+
+Die Häuser sehen wohlhabend aus, doch ein paar haben Brandspuren und
+die Tür der Moschee wurde mit einer Axt angegriffen. Vor der Moschee
+stellt sich ein Mann auf die Straße. Gregorius grüßt ihn, dann kommen
+sehr schnelle Antworten.
+
+Nachdem Gregorius langsam antwortet, ändern sich die Antworten.
+
+- ?: Ihr Franken wollt also unsere Gastfreundschaft?
+
+Er zeigt uns ein Haus, das geplündert wurde. Im Stall daneben stellen
+wir unsere Pferde ab. Auf der Erde vor dem Stall sind noch dunkle
+Flecken von Getöteten.
+
+- Iginio: Wahrscheinlich werden wir uns wiedersehen.
+
+Bald darauf kommt er zurück, zwei Frauen tragen einen Topf. Gregorius
+gibt ihm ein eher teures Schmuckstück als Geschenk.
+
+Wir teilen uns in Wachen ein. Ich beginne. Ein kleiner Junge schaut
+aus dem Fenster. Es ist still, doch Leute kommen von den Feldern oder
+brechen zu den Feldern auf. Nichts passiert und ich wecke Linhard. Er
+hört Leute reden in der Nacht. Gregorius sieht dann in der letzten
+Wache Funken hinter dem Fenster. Er lässt die zweite Wache stehen und
+sieht einen Mann mit brennenden Fackeln.
+
+- Gregorius (auf Arabisch): Halt!
+- ?: Sterbt ihr fränkischen Schweine!
+
+Eine der Fackeln trifft das Strohgedeckte Lehmdach. Wir schlagen das
+Stroh vom Dach und löschen mit unseren Resten von Wasser. Kurz darauf
+werfen Dorfbewohner Wasserbehälter auf die Flammen.
+
+- Gregorius: Ein dummer Junge.
+- Dorfältester: Wirklich ein dummer Junge.
+- Iginio: Wenn ihr ihn wieder seht, lasst ihn das Dorf reparieren.
+
+Nach dem Frühstück gibt Gregorius dem Dorfältesten ein weiteres
+Schmuckstück.
+
+- Dorfältester: Es gibt die CHOCHTA, die beten an die alten Götter.
+- Gregorius: Weder an Gott noch an Allah? Wie kommt ihr mit ihnen aus?
+- D: Sie lassen uns in Ruhe und wir lassen sie in Ruhe.
+- G: Wie geht es der Umgebung?
+- D: Seit die Burg Al Rama zerstört wurde, kümmert sich hier niemand
+ mehr um die Sicherheit. Was wollt ihr damit?
+- G: Das ist unser Ziel.
+- D: Es könnte gut sein, dass sich dort Banditen eingenistet haben.
+
+Auf der anderen Seite der Furt gibt es einen Lagerplatz, und dann
+erneut auf halbem Weg nach *Al Rama*.
+
+Auf dem Weg sehen wir wieder einen Reiter. Auf einem anderen Pferd. Er
+taucht immer wieder auf. Die Sonne sinkt, als kurz vor der Furt der
+Reiter ein Zeichen gibt. Ein Aussätziger geht auf der Straße.
+
+Neben der Straße ist zu viel Vegetation, um ihm aus dem Weg zu gehen.
+
+Ich springe vom Wagen und sage ihm auf 20 Schritt Abstand in
+gebrochenem Arabisch: Geh auf die Seite. Dann werfe ich ihm einen
+Beutel mit Brot und Trockenfrüchten hin. Er bleibt auch in der Mitte,
+als ich zurück auf dem Kutschbock die Axt in die Hand nehme.
+
+Als Linhard noch 10 Schritt von ihm entfernt ist, gibt er seinem Pferd
+die Sporen. Der Mann springt zur Seite und flucht durchgehend, während
+wir an ihm vorbeireiten.
+
+Rund um die Furt ist wenig Bewuchs. Hagen reitet voran. Dann folgen
+wir. Und sehen zu spät die Bogenschützen in den Büschen. Ein Pfeil
+trifft Linhard, durchbohrt aber kaum die Rüstung.
+
+Die Pferde am Wagen scheuen. Gregorius dagegen hält sich sicher im
+Sattel. Ein Pfeil hängt in meiner Rüstung, die anderen Ritter fangen
+Pfeile mit ihren Schilden ab.
+
+Linhard reitet zwei der Angreifern nieder, die anderen fliehen. Ich
+befrage den Überlebenden, er flucht aber nur.
+
+Ich köpfe beide, dann stellen wir sie als Mahnung auf Speeren
+aufgespießt an den Wegesrand auf der anderen Seite der Furt.
+
+Die Nacht verbringen wir am Lagerplatz. Ich habe die erste Wache.
+Irgendetwas streicht um unser Lager, aber ich finde es nicht. Dann
+übernimmt Linhard.
+
+/Zwei Rote Augen, die in deine Richtung gucken. Dann sind sie weg./
+
+Linhard übergibt an Burkhart.
+
+- Linhard: Hier streunen irgendwelche Tiere herum. Wir könnten
+ angegriffen werden.
+- Burkhart: Wäre gut gewesen, Fallen aufzustellen.
+
+Dann weckt Burkhart Gregorius:
+
+- Burkhart (flüstert): Vater Gregorius! Es ist eure Wache. Und hier
+ streifen Teufel. Rotäugige Teufel.
+
+Gregorius findet Knochen am Rand von unserem Lager. Gerade wo das
+Lager zum Weg übergeht. Im Fackellicht sieht er einen
+Oberschenkelknochen und andere Reste. Ganz frisch.
+
+Im Morgengrauen finden wir weiter den Weg hinunter noch mehr Knochen.
+Ein Mensch ohne Kopf.
+
+- Gregorius: passt das zu den Aussagen des Dorfältesten über CHOCHTA?
+
+Der dritte Tag der Reise verläuft ereignislos und wir erreichen zum
+Einbruch der Dunkelheit ein Dorf.
+
+Eine befestigte Mauer, eine Kirche, ein paar Gebäude außerhalb der
+Dorfmauer. Die Menschen ziehen sich hinter die Mauer zurück. Ein
+kräftiger Bärtiger steht vor dem Tor.
+
+- ?: Salam Aleikum, wohin des Weges?
+- Gregorius: wir brauchen einen Lagerplatz für die Nacht.
+- ?: Hat das mit der Burg zu tun? Dann sucht euch einen Platz.
+- G: Was sind denn für Leute auf der Burg?
+- ?: Edle Herrschaften, wie ihr.
+- Iginio: Ich bin Iginio di Martino. Mit wem haben wir die Ehre?
+- ?: Ich bin der Älteste *Tarteos Saroian*.
+- I: Sehr erfreut. Dann hoffe ich, dass wir uns in Zukunft häufiger
+ unter guten Vorzeichen sehen.
+- T: Das hoffe ich auch, so Gott will.
+- G: So Gott will. Wie heißt euer Dorf?
+- T: Niegolsbach.
+
+Wir dürfen in einem Haus nächtigen, werden aber noch misstrauischer
+beäugt. Immer wieder sind Bögen und Speere zu sehen.
+
+Zwei junge, gutaussehende Frauen bringen uns Essen und bleiben dann
+stehen. Gregorius gibt ihnen einen Lohn für das Essen, dann geht sie
+auf die Knie vor ihm.
+
+- Gregorius: Gott sei mit euch, was wollt ihr denn?
+- ?: Wir sollen euch zu Diensten sein, dass ihr freundlich seid.
+- G: Das ist nicht unser Dienst.
+- ?: Können wir nicht trotzdem bei euch bleiben. Es wäre nicht gut für
+ uns, wenn wir von euch abgelehnt werden.
+
+Keiner der Ritter wagt es, sie anzurühren, nachdem der Priester
+abgelehnt hat.
+
+Zum nächsten Vormittag erreichen wir die Burg. Eine Mauer ist
+zerstört, der Graben ist zugeschüttet, das Vorwerk ist vernichtet. Der
+Rauch von Kochfeuern steigt auf. Eine Braun-Weiße Flagge weht auf den
+Zinnen.
+
+Der auf dem Turm stehende scheint einen fränkischen Helm zu tragen.
+
+- Iginio: Sollten wir uns bei ihnen bedanken, dass sie die Burg
+ bewahrt haben?
+
+Wir reiten ihnen offen entgegen. Grüßen sie.
+
+- Gregorius: Wie ist den Euer Name?
+- ?: Ich bin Siegfried von Jenseits des Jordan!
+- G: Ihr habt euch euren Titel selbst verliehen.
+- Siegfried: Gott hat ihn mir verliehen.
+
+Nach ein paar Worten fällt der Vorwurf „Ketzer“ und Gregorius tauscht
+sich mit einem Priester aus.
+
+Wir geben den Besatzern 20 Gold, zwei Pferde und den Dank des wahren
+Lehnsherrn. Dann verlassen sechs Besatzer das Schloss richtung
+Jerusalem.
+
+Auf der Rückseite versucht einen Gruppe zu fliehen. Als wir sie
+stellen, kauern sie sich zusammen und der Prister stellt sich vor die
+Gruppe.
#+toc: headlines 2
+** Usage
+
+Example usage:
+
+#+begin_src scheme
+(define-typed (hello typed-world) (string? string?)
+ typed-world)
+(hello "typed")
+;; => "typed"
+(hello 1337)
+;; => type error ~a ~a #<procedure string? (_)> 1337
+(define-typed (hello typed-world) (string? string?)
+ "typed" ;; docstring
+ #((props)) ;; more properties
+ 1337) ;; wrong return type
+(procedure-documentation hello)
+;; => "typed"
+(procedure-properties hello)
+;; =>((argument-types #<procedure string? (_)>)
+;; (return-type . #<procedure string? (_)>)
+;; (name . hello) (documentation . "typed") (props))
+(hello "typed")
+;; type error: return value ~a does not match ~a (1337) #<procedure string? (_)>
+#+end_src
+
+Optional and required keyword arguments:
+
+#+begin_src scheme
+(define-typed* (hello #:key typed-world) (string? #:key string?)
+ "typed" #((props)) typed-world)
+(hello #:typed-world "foo")
+;; => "foo"
+;; unused keyword arguments are always boolean #f as input
+(hello)
+;; => type error ~a ~a #<procedure string? (_)> #f
+;; typing optional keyword arguments
+(define (optional-string? x) (or (not x) (string? x)))
+(define-typed* (hello #:key typed-world) (string? #:key optional-string?)
+ (or typed-world "world"))
+(hello)
+;; => "world"
+(hello #:typed-world "typed")
+;; => "typed"
+(hello #:typed-world #t)
+;; => type error ~a ~a #<procedure optional-string? (x)> #t
+;; optional arguments
+(define-typed* (hello #:optional typed-world) (string? #:optional optional-string?)
+ (or typed-world "world"))
+(hello)
+;; => "world"
+(hello "typed")
+;; => "typed"
+(hello #t)
+;; => type error ~a ~a #<procedure optional-string? (x)> #t
+#+end_src
+
+Multiple return values:
+
+#+begin_src scheme
+;; fixed return values
+(define-typed
+ (multiple-values/fixed num)
+ ((number? number?) number?)
+ (values (* 2 (abs num)) num))
+(multiple-values/fixed -3)
+;; => 6
+;; => -3
+;; check return values via procedure
+(define-inlinable (all-numbers? args)
+ (not (member #f (map number? args))))
+(define-typed
+ (multiple-values/proc num)
+ ((all-numbers?) number?)
+ (values (* 2 (abs num)) num))
+(multiple-values/proc -3)
+;; => 6
+;; => -3
+;; check return values via lambda
+(define-typed
+ (multiple-values/lambda num)
+ (((λ(vals) (apply > vals))) number?)
+ (values (* 2 (abs num)) num))
+(multiple-values/lambda -3)
+;; => 6
+;; => -3
+#+end_src
+
+There are four different ways to check the return types:
+
+#+begin_src scheme
+;; check a single return value
+(define-typed (magnitude x y) (float? float? float?) ...)
+
+;; check all return values via procedure that receives them as list
+(define-typed (magnitude x y) ((all-float?) float? float?) ...)
+
+;; require a fixed number of return values (2)
+(define-typed (magnitude x y) ((float? float?) float? float?) ...)
+
+;; do not check return value(-s): #f as return type skips the check
+(define-typed (magnitude x y) (#f float? float?) ...)
+#+end_src
+
+Checking multiple return values has a negative impact on performance
+in the current implementation. Checking a single value or skipping the
+check does not have a significant impact.
+
** Implementation
For performance reasons, the following defines =define-typed= and
=define-typed*= also supports keyword-arguments (thanks to Zelphir
Kaltstahl’s [[https://codeberg.org/ZelphirKaltstahl/guile-examples/src/commit/0e231c289596cb4c445efb30168105914a8539a5/macros/contracts][contracts]]), but is slower.
-** Usage
-
-Example usage:
-
-#+begin_src scheme
-(define-typed (hello typed-world) (string? string?)
- typed-world)
-(hello "typed")
-;; => "typed"
-(hello 1337)
-;; => type error ~a ~a #<procedure string? (_)> 1337
-(define-typed (hello typed-world) (string? string?)
- "typed" ;; docstring
- #((props)) ;; more properties
- 1337) ;; wrong return type
-(procedure-documentation hello)
-;; => "typed"
-(procedure-properties hello)
-;; =>((argument-types #<procedure string? (_)>)
-;; (return-type . #<procedure string? (_)>)
-;; (name . hello) (documentation . "typed") (props))
-(hello "typed")
-;; type error: return value ~a does not match ~a (1337) #<procedure string? (_)>
-#+end_src
-
-Optional and required keyword arguments:
-
-#+begin_src scheme
-(define-typed* (hello #:key typed-world) (string? #:key string?)
- "typed" #((props)) typed-world)
-(hello #:typed-world "foo")
-;; => "foo"
-;; unused keyword arguments are always boolean #f as input
-(hello)
-;; => type error ~a ~a #<procedure string? (_)> #f
-;; typing optional keyword arguments
-(define (optional-string? x) (or (not x) (string? x)))
-(define-typed* (hello #:key typed-world) (string? #:key optional-string?)
- (or typed-world "world"))
-(hello)
-;; => "world"
-(hello #:typed-world "typed")
-;; => "typed"
-(hello #:typed-world #t)
-;; => type error ~a ~a #<procedure optional-string? (x)> #t
-;; optional arguments
-(define-typed* (hello #:optional typed-world) (string? #:optional optional-string?)
- (or typed-world "world"))
-(hello)
-;; => "world"
-(hello "typed")
-;; => "typed"
-(hello #t)
-;; => type error ~a ~a #<procedure optional-string? (x)> #t
-#+end_src
-
-Multiple return values:
-
-#+begin_src scheme
-;; fixed return values
-(define-typed
- (multiple-values/fixed num)
- ((number? number?) number?)
- (values (* 2 (abs num)) num))
-(multiple-values/fixed -3)
-;; => 6
-;; => -3
-;; check return values via procedure
-(define-inlinable (all-numbers? args)
- (not (member #f (map number? args))))
-(define-typed
- (multiple-values/proc num)
- ((all-numbers?) number?)
- (values (* 2 (abs num)) num))
-(multiple-values/proc -3)
-;; => 6
-;; => -3
-;; check return values via lambda
-(define-typed
- (multiple-values/lambda num)
- (((λ(vals) (apply > vals))) number?)
- (values (* 2 (abs num)) num))
-(multiple-values/lambda -3)
-;; => 6
-;; => -3
-#+end_src
-
-There are four different ways to check the return types:
-
-#+begin_src scheme
-;; check a single return value
-(define-typed (magnitude x y) (float? float? float?) ...)
-
-;; check all return values via procedure that receives them as list
-(define-typed (magnitude x y) ((all-float?) float? float?) ...)
-
-;; require a fixed number of return values (2)
-(define-typed (magnitude x y) ((float? float?) float? float?) ...)
-
-;; do not check return value(-s): #f as return type skips the check
-(define-typed (magnitude x y) (#f float? float?) ...)
-#+end_src
-
-Checking multiple return values has a negative impact on performance
-in the current implementation. Checking a single value or skipping the
-check does not have a significant impact.
-
** Benchmark
=define-typed= automates some of the guards of [[https://dthompson.us/posts/optimizing-guile-scheme.html][Optimizing Guile Scheme]], so