Programmierung

Berichten von Bugs

Ich bin gestern über einen (für mich zumindest) schwerwiegenden Bug in einem Programm gestolpert, das ich benutze. Nichts sicherheitsre­levantes (von sowas habe ich zumindest keine Ahnung), aber es beeinträchtigt die Nutzbarkeit des Programms schon in einigen Fällen. Nachdem ich ein wenig umhergeschaut habe, wie man deinen einen Bugreport zukommen lassen kann, fand ich heraus, daß es keinen Bugtracker gibt – sie benutzen ein Forum dafür. Gut, es ist deren Entscheidung; ich muß damit ja nicht zurechtkommen. Aber dort anmelden reicht erst mal noch nicht, daß ich auch Beiträge erstellen kann. Ich muß zunächst freigeschaltet werden und darauf warte ich immer noch (seit 2010–11–10 12:10).

Ich schätze mal, es ist im Interesse der Entwickler, das Berichten von Fehlern einfach zu machen. Immerhin opfert nicht jeder Benutzer die Zeit, einen Bugreport zu schreiben, wenn er einen Fehler findet und von daher sollten sie dankbar sein, wenn es jemand tut, statt ihn in eine Warteschlange zu schieben, aus der er erst nach Tagen wieder heraus kommt. Zumindest für mich ist der Willen, einen guten Bugreport zu schreiben, nicht mehr so sehr vorhanden, je länger ich warten muß.

Wie Benutzer Programme sehen

Kürzlich wurde mir jenes Bild zugespielt:

Wie Benutzer Programme sehen

Im Grunde fasst es das Grundproblem gut zusammen. Benutzer und Entwickler denken auf sehr unterschiedlichen Abstraktionsebenen. Für einen Entwickler ist die Benutzeroberfläche lediglich „eine weitere Schale“ um den Kern herum und das meiste komische Verhalten in selbiger kann er problemlos anhand anderer Teile des Systems erklären. Für den Benutzer allerdings ist die Benutzeroberfläche das Programm. Und er wird sich nicht die Mühe machen, viel mehr als das zu durchschauen und zu begreifen. Für alle praktischen Belange ist der Rest, also, wie ein Programm eigentlich funktioniert, tatsächlich Magie.

Nun ist obiges Bild leider etwas klein und ich fand weder den Originalautor noch eine hoch aufgelöste Version. Also habe ich mich mal hingesetzt und eine Vektorgrafik auf der Basis erstellt, die hier angehängt ist. Tatsächlich sind es sogar zwei geworden: Einmal weiß auf schwarz und einmal schwarz auf weiß, was sich wohl etwas tonersparender drucken lassen sollte.

Wie Benutzer Programme sehen – weiß auf schwarz Wie Benutzer Programme sehen – schwarz auf weiß

Die Schrift, die in den Grafiken verwendet wurde, ist die freie (und hübsche) Fontin.

Ich habe auch die Ausgangsdateien von Expression Design angehängt. Vielleicht mag jemand ja die „Quell“dateien haben. Sowohl die Design- als auch die PDF-Dateien veröffentliche ich hiermit gemeinfrei.

Angehängt sind hier sowohl die deutschen als auch die englischen Varianten.

Scripting Games

Die Skript-Sommerspiele 2009 werden heute eröffnet. Ich werde teilnehmen und versuchen, die einzelnen Probleme auch zu golfen.

Die Ankündigung der einzelnen Ereignisse ist leider etwas schwer zu finden, deswegen habe ich auch erst heute gemerkt, daß sie schon bei Event 5 sind. Aber eigentlich und offiziell beginnt das ganze heute.

Meine Lösungen liegen in meinem SVN-Repository.

Update (2009–08–06): Ich habe eine signierte Ausgabe von Windows Powershell: Step by Step gewonnen.

Zelluläre Automaten mit Wolfram-Regeln in Windows Batch

Zelluläre Automaten

Eindimensionale zelluläre Automaten lassen sich relativ einfach beschreiben: Letztlich hat man nur eine Kette von Zellen, die jeweils einen von zwei Zuständen haben: An oder Aus (0 oder 1, lebendig oder tot, wie auch immer man es bezeichnen will). Das kann man natürlich dann auch einfach mit Bits repräsentieren.

Zustände in allen zellulären Automaten ändern sich aufgrund der Nachbarschaft einer Zelle im jeweils vorhergehenden Zustand. Nehmen wir an, man hat eine lebendige Zelle (An, 1) und ihre Nachbarn in beide Richtungen sind tot (Aus, 0). Nehmen wir uns weiterhin eine Tabelle, in der steht, daß für exakt diese Konfiguration der Zelle und ihrer Nachbarn ihr Zustand zu tot wechselt (kann gut passieren, vielleicht starb sie ja aus Vereinsamung). In einer anderen Konfiguration sind die Nachbarn vielleicht nicht tot, sondern lebendig und in diesem Falle lebt die Zelle weiter. In noch einer anderen Konfiguration hat man vielleicht eine tote Zelle und egal, wie ihre Nachbarn aussehen, ändert sie ihren Zustand zu lebendig.

Zustandsübergänge

So eine Tabelle braucht im Grunde nicht viele Dinge: Der Zustand einer Zelle, die Zustände aller Nachbarzellen (nur zwei in diesem Fall) und der Zustand, den die Zelle in der nächsten Generation haben soll. Wir können das auch folgendermaßen darstellen:

Tabellenrepräsentation der Regeln eines eindimensionalen zellulären Automaten

In der oberen Zeile haben wir jeweils eine Zelle mit ihren zwei Nachbarn, links und rechts, also immer drei Zellen. Die untere Zeile liefert den jeweiligen Folgezustand für jede Konfiguration. Wie man vielleicht bemerkt hat, gibt es nur acht mögliche verschiedene Konfigurationen. Auf diesen können wir eine einfache Ordnung definieren, indem wir sie jeweils als drei Bits und damit als Zahl auffassen. Diese absteigende Ordnung habe ich hier auch verwendet. Haben wir diese Ordnung erst einmal, besteht diese komplette Regel nur noch aus acht Folgezuständen, die sich ebenfalls als Nullen und Einsen und damit als einzelne acht-bittige Binärzahl auffassen lassen. Diese Numerierung wurde vom britischen Mathematiker Stephen Wolfram erfunden und wird demzufolge auch als „Wolfram-Regel“ bezeichnet.

Die Regel in obigem Bild ist Regel 30.

Darstellung

Nun wissen wir, daß so ein zellulärer Automat als einzelne Zahl beschrieben werden kann und daß er im Laufe der Generationen seinen Zustand ändert. Nur was bringt uns das?

Wir könnten zum Beispiel einen einzelnen Zustand dieses Automaten als eine Reihe von schwarzen und weißen Kästchen darstellen:

Eine einzelne Generation des Regel-30-Automaten

und dann könnten wir jede Generation under der jeweils vorhergehenden darstellen:

Bildliche Repräsentation einiger Generationen von Regel 30

und siehe da, wir kriegen ein hübsches Bild. Ein wenig chaotisch, aber das ist nun mal bei der Regel so. Es gibt auch welche, die regelmäßigere Muster liefern.

Also war der Sinn und Zweck des Ganzen lediglich, ein merkwürdiges Bild zu erzeugen. Nun also zum spaßigen Teil: So etwas zu programmieren.

Der Quelltext

Es ist nicht gerade sonderlich schwer, das zu programmieren, also fangen wir einfach oben an:

Rem width of the area
Set width=81
Rem height of the area
Set height=40

Wir brauchen natürlich ein wenig Kontrolle darüber, wo das Programm aufhört zu berechnen. Ich setze eine einzelne Zelle mit Zustand 1 in die Mitte der ersten Generation (Anfangszustand), daher ist eine ungerade Breite nicht unsinnig, da sich viele Muster gleichmäßig nach links und rechts ausbreiten. Die Höhe hängt in ähnlicher Weise damit zusammen, da die Ergebnisse meist aufhören, sinnvoll zu werden, sobald ein sich ausbreitendes Muster den rechten und linken Rand erreicht.

Rem rule can be given via commandline, if not, just ask for it
Set rule=%1
If%1Neq "" GoTo dont_ask_rule
:ask_rule
Set /p rule=Rule?
:dont_ask_rule
If %rule% LssGoTo ask_rule
If %rule% Gtr 255 GoTo ask_rule

Wenn die Regel als Parameter für das Programm gegeben wird, brauchen wir nicht danach fragen, lediglich, wenn sie außerhalb des zulässigen Bereiches (0–255) liegt. Gefragt wird so lange bis eine korrekte Regel eingegeben wurde (ja, hier kann man noch hilfreiche Hinweise geben, aber da hatte ich keine Lust zu).

Call :dissect_rule

Ich habe hier ein kleines Unterprogramm geschrieben, welches die Regel in ihre acht Einzelkonfigu­rationen zerlegt:

:dissect_rule
For /l %%i In (0,1,7) Do Set /a wolfram_%%i=^(rule% ^>^> %%i^) ^& 1
GoTo :EOF

Hiernach haben wir acht Variablen, wolfram_x mit x zwischen 0 und 7, die jeweils die Folgezustände für jede Konfiguration beinhalten.

Call :init_field

Danach initialisieren wir den Bereich, wo die Zustände jeder Zelle für jede Generation gespeichert werden:

:init_field
For /l %%r In (1,1,%height%) Do (
    For /l %%c In (1,1,%width%) Do Set field_%%r_%%c=0
)
Set /a halfwidth=width/2
Set field1_%halfwid­th%=1
GoTo :EOF

Im Prinzip wird nur jede Zelle mit 0 initialisiert und eine einzelne 1 in der Mitte der ersten Generation hinzugefügt.

Wir haben allerdings noch ein kleines Problem mit diesem Ansatz: Wenn folgende Generationen berechnet werden, braucht jede Zelle eine Nachbarschaft. Nur wie sieht diese Nachbarschaft für die jeweils ersten und letzten Zellen einer Generation aus? Anfangs habe ich einfach nur eine weitere Null links und rechts an jede Zeile gehängt. Das funktioniert gut für die meisten Regeln und wir belassen es erstmal dabei. Wie man das nun in obigem Quelltext umsetzt, lasse ich als Übung für den Leser.

Was auch praktisch wäre, ist ein Unterprogramm, welches das komplette Bild ausgibt:

:show_field
For /l %%r In (1,1,%height%) Do Call :show_field_row %%r
Goto :EOF
:show_field_row
Set line=
For /l %%c In (1,1,%width%) Do If !field_%<span class=„re2“>1_%%­c!==1 (Set line=!line!X) Else (Set line=!line! )
Echo.!line!
GoTo :EOF

Es sind tatsächlich sogar zwei Unterprogramme, diese werden später noch praktisch.

Was natürlich immer noch fehlt, ist die Berechnung der Folgezustände. Also tun wir dies mal:

:compute_row
Rem %1 is the current row
For /l %%c In (1,1,%width%) Do Call :compute_row_fi­eld %%c %1
Call :show_field_row %1
GoTo :EOF

Nichts außeregwöhnliches hier, wir delegieren lediglich die Berechnung einer einzelnen Zelle an ein weiteres Unterprogramm. Wie vielleicht auffällt, zeige ich die Zeile sofort nachdem sie berechnet worden ist, was das Zuschauen während das Programm läuft, etwas weniger langweilig macht, da wir dann alle paar Sekunden eine neue Zeile sehen (ja, das Ganze ist so langsam).

:compute_row_fi­eld
Rem %1 is the field, %2 the current row
Set /a oldrow=%2 – 1
Call :get_case %oldrow% %1
Set field_%2_%1=!wol­fram_%<span class=„re2“>ca­se%!
GoTo :EOF
:get_case
Rem %1 is the row above the one currently calculated, %2 is the current field
Rem left and right neighbours
Set /a l=%2 – 1
Set /a r=%2 + 1
Set /a case=^(!field_%<span class=„re2“>1_%%! ^<^< 2^) + ^(!field_%<span class=„re2“>1_%2! ^<^< 1^) + ^(!field_%<span class=„re2“>1_%%!^)
GoTo :EOF

Hier wird der neue Zustand einer einzelnen Zelle berechnet unter Zuhilfenahme eines weiteren Unterprogramms, welches den spezifischen Fall aus der Tabelle sucht. Wir machen uns hier die Tatsache zunutze, daß die Zelle und ihre Nachbarn im Grunde eine drei-Bit-Zahl ist und die Tabelle auch zugreifbar ist, indem wir diese drei Bit in eine Dezimalzahl zwischen 0 und 7 überführen. Der Code dafür ist leider ein wenig unschön, da viel Escaping nötig ist (die Klammern habe ich jedoch lediglich aus Vorsicht so behandelt, da Klammern gern etwas kaputt machen, besonders, wenn man anfängt, Strukturen zu schachteln).

Aber das war eigentlich schon alles. Führt man diese Batchdatei nun ohne Argumente aus, kommt die folgende Abfrage:

\CMD\cellular_au­tomaton> wolfram.cmd
Rule? _

geben wir hier nun sagen wir 54 ein, kommt das folgende Bild zustande:

Rule? 54
                                       X
                                      XXX
                                     X   X
                                    XXX XXX
                                   X   X   X
                                  XXX XXX XXX
                                 X   X   X   X
                                XXX XXX XXX XXX
                               X   X   X   X   X
                              XXX XXX XXX XXX XXX
                             X   X   X   X   X   X
                            XXX XXX XXX XXX XXX XXX
                           X   X   X   X   X   X   X
                          XXX XXX XXX XXX XXX XXX XXX
                         X   X   X   X   X   X   X   X
                        XXX XXX XXX XXX XXX XXX XXX XXX
                       X   X   X   X   X   X   X   X   X
                      XXX XXX XXX XXX XXX XXX XXX XXX XXX
                     X   X   X   X   X   X   X   X   X   X
                    XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX
                   X   X   X   X   X   X   X   X   X   X   X
                  XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX
                 X   X   X   X   X   X   X   X   X   X   X   X
                XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX
               X   X   X   X   X   X   X   X   X   X   X   X   X
              XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX
             X   X   X   X   X   X   X   X   X   X   X   X   X   X
            XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX
           X   X   X   X   X   X   X   X   X   X   X   X   X   X   X
          XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX
         X   X   X   X   X   X   X   X   X   X   X   X   X   X   X   X
        XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX
       X   X   X   X   X   X   X   X   X   X   X   X   X   X   X   X   X
      XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX
     X   X   X   X   X   X   X   X   X   X   X   X   X   X   X   X   X   X
    XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX
   X   X   X   X   X   X   X   X   X   X   X   X   X   X   X   X   X   X   X
  XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX
 X   X   X   X   X   X   X   X   X   X   X   X   X   X   X   X   X   X   X   X
XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX

Der eigentliche Quelltext der Batchdatei ist ein wenig länger, da ich inzwischen auch eine Option anbiete, was mit dem linken und rechten Rand geschehen soll (alles null, alles eins, zylinderförmig und kopieren, letzteres ist nun die Standardeinste­llung, da zum Beispiel Regeln wie 169 sehr merkwürdig aussehen, wenn sie mit Null-Kanten berechnet werden).

Momentan arbeite ich noch an SVG-Export aus dieser Batch-Datei (der Grund, warum ich die eigentlich geschrieben habe) und hoffe, inzwischen alle größeren Bugs gefunden zu haben. Die erste funktionierende Version hatte übrigens nur 54 Zeilen. Ich denke, hätte ich Java benutzt (was hier gerade die einzige andere Alternative war), hätte ich deutlich mehr gebraucht.

UPDATE (2008–12–26 16:21): SVG-Export ist fertig und werkelt nun auch wie er soll. Momentan lasse ich den Terminal Server in der Uni an allen 256 Automaten gleichzeitig rechnen:

257 Instanzen von cmd … ich erinnere mich an Zeiten, wo schon nach 50 Taschenrechnern Schluß war …

gc – ein Kommandozeilen-Interface für (Teile von) Google calculator

Kürzlich stellte ich fest, daß die Suchvorschläge von Google, die in der Suchleiste von Internet Explorer oder Firefox erscheinen, den Google calculator mit benutzen:

Das Ergebnis einer Berechnung durch Googles Suchvorschläge

Also habe ich Fiddler angeworfen, um zu schauen, wo die Anfragen für solche Vorschläge hingehen und fand folgende URL (für die Anfrage 1+1):

http://sugges­tqueries.google­.com/complete/se­arch?output=fi­refox&client=I­E8&hl=en&qu=1%2B1

Die Antwort auf diese Anfrage war ein wenig JSON:

[„1+1“,
 [„= 2“,
  „1+1 канал“,
  „1+1 0“,„1+1 tv“,
  „1+1 internet“,
  „1+1 hosting“,
  „1+1.ua“,
  „1+1 ukraine“,
  „1+1.com“,
  „1+1 webmail“,
  „1+1 2 proof“
  ]
 ]

Ich habe das hier mal ein wenig aufgehübscht, eigentlich kommt es in einer langen Zeile. Wie man sehen kann, sind das im Wesentlichen zwei geschachtelte Arrays. Das erste Element des äußeren ist die Suchanfrage und das innere enthält die Vorschläge. Wenn die Vorschläge ein Ergebnis einer Berechnung durch Google Calculator enthalten, dann ist dies der erste Vorschlag, der zurückkommt.

Das wissend habe ich ein kleines Programm zusammengehackt, was seine Argumente an Google schickt und den ersten Vorschlag ausgibt (was hoffentlich ein Rechenergebnis is­t):

X:\>gc 1+1
= 2

X:\>gc the speed of light in dozen fathoms per quarter fortnight
= 4.13099844e12 (dozen fathoms) per (quarter fortnight)

X:\>gc mass of earth in lbs
= 1.31708565e25 pounds

X:\>gc 7 liters / 1 kilometer=
= 7.0e-6 m2

Am liebsten mag ich die Möglichkeit zur Einheitenkonver­tierung. Leider funktioniert nicht alles. An Naturkonstanten (Lichtgeschwin­digkeit, Elementarladung, …) und sonstige hübsche Zahlen (e, π, …) kommt man leider nicht direkt heran. Bei Naturkonstanten schafft man es manchmal mit einer expliziten Konvertierung in deren Einheit (c in kilometers per second), aber das wäre noch ein Punkt, wo man verbessern könnte.

Das Programm wurde in C# 2.0 geschrieben und benutzt LitJSON zum Parsen von JSON. Es läuft auch auf Mono, ich habe dort allerdings noch nicht versucht, es zu kompilieren. Aber da alles .NET 2.0 ist, sollte das eigentlich problemlos funktionieren.

Das Programm sowie der Quelltext hängen an.

UPDATE (2008–10–26 00:34): Ich habe Quelltext und ausführbare Datei wie folgt aktualisiert:

  1. Die Ausgabe erfolgt nun in Unicode (endlich weiß ich, wie das geht)
  2. Falls kein Rechenergebnis vorliegt (also das erste Ergebnis kein = am Anfang hat), werden alle Resultate zurückgeliefert. Das dient hauptsächlich der Nutzung der Suchvorschläge, wie sie vorgesehen waren, aber es hat einige spaßige Seiten:
X:\>gc mankind is
mankind is obsolete
mankind is obsolete lyrics
mankind is obsolete myspace
mankind is doomed
Das Google-rakel:
X:\>gc the future will be
the future will be better tomorrow

Batch-Tricks: Rekursion

Hach ja, Rekursion, das Lieblingstierchen jedes Programmierers. Sicher ist sowas auch in Batchdateien möglich (Ich versuche übrigens immer noch Turingvollständig­keit nachzuweisen :-)).

Der erste zaghafte Test wäre erstmal eine unendliche Rekursion:

@ECHO OFF
:JUMP
CALL :JUMP

Und siehe da, sie funktioniert:

******  B A T C H   R E C U R S I O N  exceeds STACK limits ******
Recursion Count=599, Stack Usage=90 percent
******       B A T C H   PROCESSING IS   A B O R T E D ******

Genau das, was wir haben wollten. Etwas sinnvolleres als einen Stacküberlauf hatten wir uns ohnehin nicht erhofft. Also offensichtlich kann cmd Rekursion.

Dann sollten wir das auch mal mit einem zumindest ansatzweise praxisbezogenem Problem testen: Fakultäten. Ungeachtet dessen, daß man die besser iterativ berechnet. Wir wollen aber nur sicherstellen, daß die Rekursion vernünftig funktioniert:

@ECHO OFF
SETLOCAL ENABLEEXTENSIONS ENABLEDELAYEDEX­PANSION

CALL :fac %1
ECHO %RETURN%

:end
ENDLOCAL
GOTO :EOF

:fac
IF %1==0 (
        SET RETURN=1
        GOTO :EOF
)
SET /A TEMP=%1 – 1
CALL :fac %TEMP%
SET /A RETURN*=%1
GOTO :EOF

Wir brauchen hier leider eine temporäre Variable, da cmd keine Berechnungen ohne SET /A erlaubt, aber ansonsten sieht es in etwa so aus, wie es sollte. Der Rekursionsabbruch wurde am Anfang des Unterprogramms durch ein IF abgefangen, leider gibt es keine funktionalen Nettigkeiten wie verschiedene Funktionsdefi­nitionen hier.

Und funktioniert das nun auch? Aber sicher:

> fac 5
120
> fac 10
3628800

Mein Taschenrechner sagt mir sogar, daß die Werte richtig sind. 12! ist leider die höchste Fakultät, die man damit berechnen kann, da wir auf 32-bittige vorzeichenbehaftete Ganzzahlen beschränkt sind. Ein kleiner Fehler ist noch vorhanden, wenn man negative Zahlen als Argument angibt (wieder eine unendliche Rekursion). Das ist allerdings in der angehängten Version behoben, ebenso bekommt man in selbiger eine hilfreiche Nachricht, wenn man die Batch ohne Parameter aufruft.

Und nur so nebenbei, eine nette Variante, Fakultäten zu berechnen, indem wir einfach den eingebauten „Taschenrechner“ von cmd benutzen:

@ECHO OFF
SETLOCAL ENABLEEXTENSIONS ENABLEDELAYEDEX­PANSION
SET TEMP=1
FOR /L %%i IN (1,1,%1) DO SET TEMP=!TEMP! * %%<span class=„re2“>i
SET /A TEMP=%TEMP%
ECHO %TEMP%
ENDLOCAL

Wir basteln uns hier einfach die komplette Berechnung in einer Zeile zusammen und lassen die dann von SET /A auswerten. Nichts großartig aufregendes aber wahrscheinlich schneller als Rekursion.

Zählen auf eklige Weise

@echo off
set X=0
echo set /a X+=1 >>%0
echo echo %%X%%>>%0

... es funktioniert ... jedes Mal, wenn man diese Batch-Datei ausführt, wächst die Liste der ausgegebenen Zahlen um eins :-)

Der interessante Teil hieran ist, daß die Zeilen, die erst zur Laufzeit des Skriptes hinzugefügt werden, noch im gleichen Durchlauf der Batch ausgeführt werden.

Nullity

Hat schon mal jemand von »Nullity« gehört? Ein wundertolles neues (naja, inzwischen 10 Jahre altes) Konzept (nicht zu verwechseln mit dem anderen mathematischen Konzept diesen Namens), welches von James Anderson erfunden wurde. Es erlaubt uns, Null durch Null zu teilen. Zusammen mit der Nullität kommt auch die sogenannte Transreelle Arithmetik. Im Grunde ist die Nullität eine besondere nicht-reelle Zahl, die als das Ergebnis von 0 ÷ 0 definiert ist. Es läßt sich beweisen, daß diese Zahl auch das gleiche ist wie 00 sowie 0 ⋅ ∞. Der einzige wirkliche Unterschied zu bestehenden Dingen wie NaN ist, daß Nullity (Φ) gleich sich selbst ist, während NaN ungleich NaN ist, zumindest in normaler IEEE-Gleitkomma-Arithmetik. Scheinbar hat er sogar eine Schule überredet, den Kram zu unterrichten und baut Computer, die das nutzen (nur wozu?). Was mich angeht, so bin ich noch keinem 0 ÷ 0 bzw. Φ begegnet, was ein fundamentales Problem darstellte. Bei Grenzwerten erlegt l'Hôspital das üblicherweise. Und da die meisten Berechnungen, die ich am Computer anstelle, ihre Wurzeln in der Mathematik haben, die Dinge wie NaN gar nicht mag, hatte ich das bislang auch eigentlich nie als Ergebnis (es sei denn, der Algorithmus lief sehr schief). Positive und negative Unendlichkeit sicherlich, aber kein NaN. Weiterhin ändert der Kram mit Nullity ohnehin wenig, abgesehen davon, daß man halt d.IsNullity() statt d.IsNaN() aufruft. Wikinews hat da noch ein wenig mehr zu dem Thema.

Experimente mit Syntax-Highlighting

Ich mochte es noch nie, wie mein Code hier bislang aussah: Einrückungen waren unmöglich, alles unbunt, … also suchte ich mal nach einem Drupal-Plugin, was Syntax-Highlighting übernehmen kann. Gefunden habe ich genau eins: GeSHi filter.

Es funktioniert zwar, aber es scheint nicht zu gut zu funktionieren. Der meiste Code auf dieser Seite sind momentan Batchdateien und gerade hier wirkt die Liste der Todos und bekannten Probleme nicht gerade ermutigend (frei übersetzt):
  * TODO (aktualisiert 2005/07/05)
 * -------------------------
 
 – Einen Weg finden, um %* hervorzuheben
 * – Pipes und Umleitungen hervorheben (brauchen wir das wirklich?)
 * – Fehlende Schlüsselwörter hinzufügen.
 * – Einen guten Link für die Schlüsselwörter finden.
 * – Styles verbessern.
 
KNOWN ISSUES (aktualisiert 2005/07/07)
 * ---------------------------------
 
 – Versucht nicht mal, Leerzeichen in Variablennamen oder Labels zu
 *   behandeln (Ich finde keinen verläßlichen Weg, herauszufinden, ob
 *   eine Zeichenfolge ein Name ist oder nicht, in einigen Fällen hängt das
 *   vom Kontext bzw. vom Zustand des Environments ab).
 * – Keine Unterstützung für die Pseudovariablen %%[Buchstabe], die in
 *   FOR verwendet werden (das sollte nur innerhalb des Scopes von FOR
 *   passieren: wie?).
 * – Keine Unterstützung für die Pseudoargumente %~[irgendwas].
 * – Wenn das gleiche Schlüsselwort am Ende einer Zeile und am Anfang der
 *   nächsten steht, wird das zweite nicht hervorgehoben (das dürfte ein
 *   GeSHi-Bug sein und nicht mit der Srpachdefinition hier zusammenhängen).
 * – Schlüsselwörter werden immer hervorgehoben, auch wenn sie nicht als
 *   solche genutzt werden sondern beispielsweise als Argumente für echo.
Offenbar gibt es hier schon einige Beschränkungen der Engine selbst. Irgendwie hätte ich gern Colorer hier, aber den mit PHP zum Laufen zu bringen, könnte etwas kompliziert werden (wiewohl es scheinbar Möglichkeiten gibt, das im Web zum Funktionieren zu bringen). Währenddessen versuche ich einfach, die Bugs, die mir wirklich störend auffallen, zu beheben. Ich habe schon enableextensions und enabledelayedex­pansion als hervorzuhebende Dinge hinzugefügt.

RSS für Seiten ohne Feed

Ich bin ein großer Fan von RSS, da es mir erlaubt, einfach auf die Schnelle nachzuschauen, ob diverse Seiten, die ich sonst alle einzeln abklappern müßte, neue Beiträge haben. Gerade mit einigen unregelmäßig aktualisierten Webcomics ist das recht praktisch. Hier sei noch angemerkt, daß ich es im Grunde gern hab, wenn die Comicstrips selbst auch im RSS von Webcomics auftauchen, statt nur ein Link zu der entsprechenden Seite; würde das Lesen wesentlich angenehmer machen (und dürfte den Traffic auch reduzieren).

Vor ein paar Stunden habe ich zwei reichlich widerliche Skripen zusammgengehackt, die einen Webcomic für einen Mitstudenten und einen für mich abholen und als RSS aufbereiten. Momentan scheint es zu funktionieren, mal abwarten, ob Updates irgendwelche unerwarteten Probleme zutage fördern.

Wer mag, kann die Skripten ja für sich selbst anpassen.

UPDATE (2008–01–31 10:20): Code für bash.org fehlte. Ist nun behoben.

UPDATE (2008–11–06 07:42): Code für ruthe.de angepaßt, da die Seite sich geändert hatte.

UPDATE (2008–02–27 14:16): Beim bash.org-Feed kam ungültiges RSS zustande, wenn Nicht-ASCII-Zeichen im Text standen. Das sollte nun behoben seni.

UPDATE (2010–04–14 12:40): Code für ruthe.de angepaßt, da die Seite sich schon wieder geändert hatte.

Syndicate content