Rekursive Abkürzungen



  • Ist euch schonmal aufgefallen, dass diese ganzen rekursiven Abkürzungen, die ja vor allem im Unix-Umfeld so beliebt zu sein scheinen, eigentlich einen Designfehler haben?

    GNU: GNU is Not Unix
    WINE: WINE Is Not an Emulator
    PHP: PHP Hypertext Preprocessor

    Ich meine, wenn man schon so geekig sein will, dann sollte man es auch richtig machen. Denn diese Rekursionen, wie sie hier benutzt werden, würden als Programmcode niemals irgendetwas liefern:

    void WINE()
    {
        WINE();
        Is();
        Not();
        Emulator();
    }
    

    Diese Funktion würde einfach nur immer wieder in sich selbst springen. Die Funktionen Is, Not und Emulator würden niemals aufgerufen.

    Wenn man also eine funktionierende rekursive Abkürzung machen will, müsste die Rekursion ans Ende:

    IAFOI: I'm A Fan Of IAFOI

    void IAFOI()
    {
        Im();
        A();
        Fan();
        Of();
        IAFOI();
    }
    

    Und schon ist alles im Lot:

    I'm a fan of IAFOI
                   |
                   |
                   V
                 I'm a fan of IAFOI
                                |
                                |
                                V
                              I'm a fan of IAFOI
    

    Aber diese Rekursionen, die diese Möchtegern-Geeks benutzen, sind doch absolut falsch konstruiert:

    WINE
     |
     |
     V
    WINE
     |
     |
     V
    WINE
    


  • Einfache Antwort: Rekursive Akronyme stellen keinen Programmcode dar. Rekursion gibt es auch nicht nur bei Programmcode, sondern auch bei Grammatiken oder allgemein Ersetzungsvorschriften. Da wirst du eher fündig werden, denn da gibt es auch Linksrekursion.



  • <loriot>Ach!</loriot>



  • Das ist Text, kein Programmcode. Deshalb darfst du nicht von Programmcode ausgehen, höchstens von Makros (aka Textersetzung):

    #define WINE WINE Is Not an Emulator
    
    int main()
    {
    	WINE;
    	return 0;
    }
    

    Expandiert zu:

    int main()
    {
    	WINE Is Not an Emulator;
    	return 0;
    }
    

    Problem gelöst. 🙂



  • Besserwisser schrieb:

    Ist euch schonmal aufgefallen, dass diese ganzen rekursiven Abkürzungen, die ja vor allem im Unix-Umfeld so beliebt zu sein scheinen, eigentlich einen Designfehler haben?

    Jo, sie erklären nix. Ich halte sie für störend.

    Besserwisser schrieb:

    GNU: GNU is Not Unix
    WINE: WINE Is Not an Emulator
    PHP: PHP Hypertext Preprocessor

    Man könnte es auf die Spitze treiben mit
    ABC: ABC

    So ein Blödsinn.



  • Bashar schrieb:

    Einfache Antwort: Rekursive Akronyme stellen keinen Programmcode dar.

    Ich bin mir relativ sicher, dass die Programmierer hier an Rekursion in Programmen dachten.

    Aber gut, es ist kein Programmcode. Aber ein Wort/eine Abkürzung, die man von links nach rechts liest und die man somit, rein theoretisch, von links nach rechts "versteht":

    In meinem Beispiel könnte man sich das folgendermaßen als Dialog vorstellen:

    "Mein Programm heißt IAFOI."
    "Was bedeutet 'IAFOI'?"
    "'IAFOI' ist eine Abkürzung."
    "OK, wofür stehen die Buchstaben in der Abkürzung?"
    "Die Buchstaben stehen für 'I'm A Fan Of IAFOI'."
    "Gut, gehen wir die einzelnen Wörter durch: Was bedeutet 'I'm'?"
    "'I'm' bedeutet 'Ich bin'."
    "Was bedeutet 'A'?"
    "'A' bedeutet 'ein'."
    "Was bedeutet 'Fan'?"
    "'Fan' bedeutet auch im Deutschen 'Fan'."
    "Was bedeutet 'Of'?"
    "'Of' bedeutet 'von'."
    "Was bedeutet 'IAFOI'?"
    "'IAFOI' ist eine Abkürzung."
    "OK, wofür stehen die Buchstaben in der Abkürzung?"
    "Die Buchstaben stehen für 'I'm A Fan Of IAFOI'."
    "Gut, gehen wir die einzelnen Wörter durch: Was bedeutet 'I'm'?"
    "'I'm' bedeutet 'Ich bin'."
    "Was bedeutet 'A'?"
    "'A' bedeutet 'ein'."

    ... ad infinitum.

    Nun der gleiche Dialog mit WINE:

    "Mein Programm heißt WINE."
    "Was bedeutet 'WINE'?"
    "'WINE' ist eine Abkürzung."
    "OK, wofür stehen die Buchstaben in der Abkürzung?"
    "Die Buchstaben stehen für 'WINE Is Not an Emulator'."
    "Gut, gehen wir die einzelnen Wörter durch: Was bedeutet 'WINE'?"
    "'WINE' ist eine Abkürzung."
    "OK, wofür stehen die Buchstaben in der Abkürzung?"
    "Die Buchstaben stehen für 'WINE Is Not an Emulator'."
    "Gut, gehen wir die einzelnen Wörter durch: Was bedeutet 'WINE'?"
    "'WINE' ist eine Abkürzung."
    "OK, wofür stehen die Buchstaben in der Abkürzung?"
    "Die Buchstaben stehen für 'WINE Is Not an Emulator'."
    "Gut, gehen wir die einzelnen Wörter durch: Was bedeutet 'WINE'?"

    Merkst du den Unterschied? I, N und E werden niemals erreicht.

    Oder ein anderes Beispiel: Versuch mal, "Ein Mops kam in die Küche" so umzuändern, daß der Text mit "Auf einem Grabstein stand:" beginnt und der gesamte Text des Liedes trotzdem der gesamte Text des Grabsteins ist.

    "Auf einem Grabstein stand: Ein Mops kam in die Küche" funktioniert nicht. Denn in diesem Szenario fehlt auf dem Grabstein der Text "Auf einem Grabstein stand". Der Text auf dem Grabstein geht hier mit "Ein Mops kam in die Küche" los, während das Lied in dieser Version mit "Auf einem Grabstein stand" losgeht. Somit sind Lied und Grabsteintext nicht mehr komplett identisch.

    Würde man es also konsequent durchziehen, würde folgendes passieren:
    "Auf einem Grabstein stand: Auf einem Grabstein stand: Auf einem Grabstein stand: ..."

    Deshalb müssen Rekursionen, die keine Abbruchbedingung haben, sondern unendlich weiterlaufen sollen, immer am Ende stehen. Ob nun bei Programmcode oder bei Begriffsdefinitionen, ist relativ egal: Solange man chronologisch vorgeht (und Abkürzungen liest man nunmal von links nach rechts) ist eine Rekursion wie WINE oder GNU rein technisch gesehen schlecht, weil sie in der Definition, die auch in die Rekursion reingeht, niemals über den ersten Buchstaben hinauskommt.

    DarkShadow44 schrieb:

    Das ist Text, kein Programmcode. Deshalb darfst du nicht von Programmcode ausgehen, höchstens von Makros (aka Textersetzung):

    #define WINE WINE Is Not an Emulator
    
    int main()
    {
    	WINE;
    	return 0;
    }
    

    Expandiert zu:

    int main()
    {
    	WINE Is Not an Emulator;
    	return 0;
    }
    

    Problem gelöst. 🙂

    Nee, das ist ja wieder ganz was anderes: In dem Fall ist das Makro WINE ein anderes Element als der Typ/die Variable/die Konstante WINE, die innerhalb des Makros aufgerufen wird:

    typedef int WINE;
    
    #define WINE WINE isNotAnEmulator = 1
    
    int main()
    {
        WINE;
    }
    

    typedef int WINE ist hier ein anderes Element als #define WINE, und beides wird von verschiedenen Programmen interpretiert: Der Präprozessor macht erstmal eine simple Textersetzung, kennt für sich also kein Element typedef int WINE. Und der Compiler weiß am Ende nichts mehr vom #define WINE. Somit hat dieses Beispiel jetzt gar nichts mit Rekursion zu tun, weil niemand hier jemals etwas mit sich selbst definiert hat bzw. nichts sich selbst aufruft.
    (Und würde ich das typedef int WINE weglassen, würde der Code nicht kompilieren, weil ihm WINE nicht bekannt wäre. Aber er würde ja zum Beispiel nie und nimmer versuchen, WINE mit WINE zu definieren und in eine Unendlichschleife laufen.)

    Ahnlich wie jetzt zum Beispiel das hier ja auch keine Rekursion wäre, bloß weil die Namen zufällig gleich sind:

    void Funktion(int i)
    {
        void Funktion();
    }
    


  • Besserwisser schrieb:

    Bashar schrieb:

    Einfache Antwort: Rekursive Akronyme stellen keinen Programmcode dar.

    Ich bin mir relativ sicher, dass die Programmierer hier an Rekursion in Programmen dachten.

    Aber deine eigene Schlussfolgerung führt dich doch darauf, dass diese Annahme absurd ist. Wieso hältst du daran fest?



  • Besserwisser schrieb:

    Nee, das ist ja wieder ganz was anderes: In dem Fall ist das Makro WINE ein anderes Element als der Typ/die Variable/die Konstante WINE, die innerhalb des Makros aufgerufen wird

    Nö:

    #define Is
    #define Not
    #define an
    #define Emulator
    #define WINE WINE Is Not an Emulator
    
    int main()
    {
    	int WINE;
    
    	return 0;
    }
    

    Wenn der Präprozesser nicht automatisch stoppen würde, würde es endlos ersetzt werden.
    Du darfst natürlich kein zweites WINE einführen. 🙄

    Bashar schrieb:

    Einfache Antwort: Rekursive Akronyme stellen keinen Programmcode dar. Rekursion gibt es auch nicht nur bei Programmcode, sondern auch bei Grammatiken oder allgemein Ersetzungsvorschriften. Da wirst du eher fündig werden, denn da gibt es auch Linksrekursion.

    Folgende Grammatik:

    WINE -> WINE Is Not An Emulator
    

    "WINE" ist ein Nichtterminal, " Is Not an Emulator" ist ein Terminal. Und jetzt sag nochmal dass das nicht rekursiv definiert ist ?



  • Besserwisser schrieb:

    GNU: GNU is Not Unix
    WINE: WINE Is Not an Emulator
    PHP: PHP Hypertext Preprocessor

    PHP passt meines erachtens nach nicht in die Liste. Denn die Abkürzung PHP stammt Ursprünglich von Personal Home Page Tools.

    Nur so als Anmerkung.



  • Ja, bescheiden anfangen, dann die coolen Jungs schlecht nachahmen. Ein wiederkehrendes Thema bei PHP, in jeder Hinsicht.



  • Besser zweistufig rekursive Akronyme verwenden: HURD -> HIRD of Unix-Replacing Daemons; HIRD -> HURD of Interfaces Representing Depth

    Bashar schrieb:

    Ja, bescheiden anfangen, dann die coolen Jungs schlecht nachahmen. Ein wiederkehrendes Thema bei PHP, in jeder Hinsicht.

    👍


Log in to reply