Vortrag über Ideen für eine neue Sprache für Spieleentwickler [youtube]



  • Kellerautomat schrieb:

    volkard schrieb:

    Nee. Serialisierter, die Standdardkonstruktoren verlangen, sind für mich indiskutabel.

    Gib mal ein Beispiel von einem Typen, bei dem es Sinn macht, keinen Standardkonstruktor zu haben.

    Umgekehrt! Wo braucht man ihn? Was man nicht braucht, soll man nicht in die Schnittstelle tun.
    Also mal alle Monstertypen im Rollenspiel sollen keinen haben. Wäre doch totaler Unfug. Streams sollen keinen haben. Ich könnte auch damit leben, daß Zahlen und Strings keinen haben. Manche rohe Typen dürften, um andere Meckerstellen der Sprache zu umgehen, sowas erlauben wie

    int i=uninitialized;//neues schlüsselwort. ein =0 wäre zu lahm und 
      //die magic number wäre inhaltlich äußerst fragwürdig. 
    do
      i=rand()%100;//meckerstelle: i kann hier nicht erzeigt werden, weil…
    while(schonGezogen(i));//…i hier gebraucht wird
    return i;
    

    .
    Zusammen mit dem RAII-Dingens mache ich eigentlich meine Variablen so lokal, daß ich sie stets erst anlege, wenn sie schon sinnvoll initialisiert werden können.
    Ok, man braucht dafür, um kein schlechtes Gewissen zu bekommen, auch mal emplace_back und einen vector mit fixer Maximalgröße, der nicht im Freispeicher wohnt.



  • volkard schrieb:

    Umgekehrt! Wo braucht man ihn? Was man nicht braucht, soll man nicht in die Schnittstelle tun.

    Alles, was irgendwie in Container soll. Alles, was irgendwie Movable ist bzw. einen "empty" Zustand hat.

    volkard schrieb:

    Also mal alle Monstertypen im Rollenspiel sollen keinen haben. Wäre doch totaler Unfug.

    Noe, warum. Wenn du ein Monster default-Konstrutierst, haste sowas wie ein moved-from Monster. Das kriegst du spaetestens wenn du einen Move-Konstrutkor / operator = verwendest. Also kannst du auch gleich einen Defaultkonstruktor bereitstellen.

    volkard schrieb:

    Streams sollen keinen haben.

    Genau wie mit den Monstern.

    volkard schrieb:

    Ich könnte auch damit leben, daß Zahlen und Strings keinen haben. Manche rohe Typen dürften, um andere Meckerstellen der Sprache zu umgehen, sowas erlauben wie

    int i=uninitialized;//neues schlüsselwort. ein =0 wäre zu lahm und 
      //die magic number wäre inhaltlich äußerst fragwürdig. 
    do
      i=rand()%100;//meckerstelle: i kann hier nicht erzeigt werden, weil…
    while(schonGezogen(i));//…i hier gebraucht wird
    return i;
    

    .
    Zusammen mit dem RAII-Dingens mache ich eigentlich meine Variablen so lokal, daß ich sie stets erst anlege, wenn sie schon sinnvoll initialisiert werden können.
    Ok, man braucht dafür, um kein schlechtes Gewissen zu bekommen, auch mal emplace_back und einen vector mit fixer Maximalgröße, der nicht im Freispeicher wohnt.

    uninitialized finde ich auch gut. Hat aber mit Defaultkonstruktoren wenig zu tun.



  • Alle Deine Argument für Standardkonstruktoren sind also nicht inhaltlicher Art im Sinne der Anwendungslogik, sondern programmiertechnische Zugeständnisse.

    Kellerautomat schrieb:

    volkard schrieb:

    Umgekehrt! Wo braucht man ihn? Was man nicht braucht, soll man nicht in die Schnittstelle tun.

    Alles, was irgendwie in Container soll. Alles, was irgendwie Movable ist bzw. einen "empty" Zustand hat.

    Ja, auch ein Punkt, den ich doof finde: Objekte wegmoven, ohne daß der Bezeichner verschwindet. Ich hätte gerne

    ding.foo();
    aufruf(move(ding));
    //ding.foo();//gäbe compilerfehler
    

    aufruf müßte die unbedingte Destuktionsverantwortung haben. Normalerweise wird an einen Subaufruf weitergemovt. Im Falle eines vorhergehenden return/throw muss ding halt wie eigene lokale Variablen destruiert werden. Für solche Sachen werfe ich Augen auf Rust und Konsorten.

    Kellerautomat schrieb:

    uninitialized finde ich auch gut. Hat aber mit Defaultkonstruktoren wenig zu tun.

    Bei ints auf dem Stack schon.



  • Kellerautomat schrieb:

    Ok, ich gestehe. Fuer sowas hab ich auch schon Exceptions verwendet. Aber vielleicht koennte man etwas bauen, das aehnlich funktioniert, ohne gleich Exceptions zu brauchen. Ein Sprung zum naechsten Error-Handler oder so?
    [...]
    Uebersetz mal "Exception" auf Deutsch.

    Das ist ja lustig. Und wenn die Exceptions anders hießen, würdest du dich evtl. überwinden, sie zu verwenden, anstatt sie von Hand nachzubauen?



  • volkard schrieb:

    Ja, auch ein Punkt, den ich doof finde: Objekte wegmoven, ohne daß der Bezeichner verschwindet. Ich hätte gerne

    ding.foo();
    aufruf(move(ding));
    //ding.foo();//gäbe compilerfehler
    

    Hmm:

    if(random() % 2)
        foo(move(bar));
    bar.foobar();
    


  • Ethon schrieb:

    Hmm:

    if(random() % 2)
        foo(move(bar));
    bar.foobar();
    

    Wie in Rust: Sobald es auch nur einen Weg gibt, auf dem ein Objekt uninitialisiert ist oder weggemoved wurde, gibt es einen Compilerfehler. Der Programmierer hat dann sicherzustellen, dass es bei allen Wegen gueltig ist. In deinem Beispiel koennte man z.B. ein else einbauen oder ein neues Objekt erzeugen.

    EDIT: In C++ sind alle Methodenaufrufe von Standardklassen ausser die pointer undefiniertes Verhalten, wenn das Objekt weggemoved wurde und nicht neu zugewiesen wurde.



  • Ethon schrieb:

    volkard schrieb:

    Ja, auch ein Punkt, den ich doof finde: Objekte wegmoven, ohne daß der Bezeichner verschwindet. Ich hätte gerne

    ding.foo();
    aufruf(move(ding));
    //ding.foo();//gäbe compilerfehler
    

    Hmm:

    if(random() % 2)
        foo(move(bar));
    bar.foobar();
    

    Verboten. Auch nach geiftem move ist der Bezeichner weg. Wer sowas machen will, darf smartpointers/optional etc nehmen.



  • Und was machst du dann mit Membern?



  • Kellerautomat schrieb:

    Und was machst du dann mit Membern?

    Auch wegwerfen, wie üblich.



  • struct Foo
    {
            string s;
            string t;
    
            void f()
            {
                    string throwaway = move(s);
                    void(throwaway);
            }
    
            void g()
            {
                    cout << s;
            }
    };
    
    Foo foo;
    foo.f();
    foo.g(); // error, objekt tot?
    f.s = ...; // nope
    f.t = ...; // ok/error?
    

    Und was, wenn ich das Objekt wiederbenutzen will? Und wie siehts aus, wenn es gar keinen Namen fuer das Objekt gibt?



  • Du stellt Dich jetzt aber störrisch.

    Members aus einem lebenden Objekt kann man nicht wegmoven.

    Wenn Du es wiederbenutzen willst, dann willste es nicht wegmoven.

    Wenn keinen Namen fürs Objekt gibt, ist es Dir doch egal. Der Compiler destruiert es ganz normal am Ende des Ausdrucks, außer es wurde schon im Ausdruck weggemovet.



  • volkard schrieb:

    Members aus einem lebenden Objekt kann man nicht wegmoven.

    Warum nicht? Unnoetige Beschraenkung.

    volkard schrieb:

    Wenn Du es wiederbenutzen willst, dann willste es nicht wegmoven.

    Oh doch. Ein ServerSocket hat einen ClientSocket als Member und akzeptiert da Verbindungen mit. Sobald eine Verbindung da ist, wird der ClientSocket weggemoved und neu verwendet fuer die naechste Verbindung. Das ganze natuerlich Async.

    volkard schrieb:

    Wenn keinen Namen fürs Objekt gibt, ist es Dir doch egal. Der Compiler destruiert es ganz normal am Ende des Ausdrucks, außer es wurde schon im Ausdruck weggemovet.

    vector<Movable> v;
    move(v[0]);
    v[0]; // ???
    


  • Kellerautomat schrieb:

    volkard schrieb:

    Members aus einem lebenden Objekt kann man nicht wegmoven.

    Warum nicht? Unnoetige Beschraenkung.

    Damit man es nicht nötog hat, überhaupt von toten Objekten auszugehen.
    Wer evtl tote Objekt haben mag nimmt smartpointers oder boost::optional oder sowas.

    Kellerautomat schrieb:

    volkard schrieb:

    Wenn Du es wiederbenutzen willst, dann willste es nicht wegmoven.

    Oh doch. Ein ServerSocket hat einen ClientSocket als Member und akzeptiert da Verbindungen mit. Sobald eine Verbindung da ist, wird der ClientSocket weggemoved und neu verwendet fuer die naechste Verbindung. Das ganze natuerlich Async.

    Eben da nimmste smartpointers oder boost::optional oder sowas.

    Kellerautomat schrieb:

    volkard schrieb:

    Wenn keinen Namen fürs Objekt gibt, ist es Dir doch egal. Der Compiler destruiert es ganz normal am Ende des Ausdrucks, außer es wurde schon im Ausdruck weggemovet.

    vector<Movable> v;
    move(v[0]);
    v[0]; // ???
    

    Auch nicht möglich.



  • volkard schrieb:

    Eben da nimmste smartpointers oder boost::optional oder sowas.

    Also eine unnoetige Allokation oder semantisch komplett falsche Klasse weil... volkard das so besser gefaellt?

    volkard schrieb:

    Auch nicht möglich.

    Und das wird wie verhindert? Woher weiss der Compiler, ob v[0] gerade gueltig ist oder nicht?



  • Kellerautomat schrieb:

    volkard schrieb:

    Eben da nimmste smartpointers oder boost::optional oder sowas.

    Also eine unnoetige Allokation oder semantisch komplett falsche Klasse weil... volkard das so besser gefaellt?

    Nur das, was jetzt soo viele Klassen innendrin selber machen müssen, um movable zu sein.

    Kellerautomat schrieb:

    volkard schrieb:

    Auch nicht möglich.

    Und das wird wie verhindert? Woher weiss der Compiler, ob v[0] gerade gueltig ist oder nicht?

    Es kann nicht ungültig sein. :p



  • audacia schrieb:

    Das ist ja lustig. Und wenn die Exceptions anders hießen, würdest du dich evtl. überwinden, sie zu verwenden, anstatt sie von Hand nachzubauen?

    Noe. Ich will n Feature, das die guten Faelle von Exceptions erlaubt, waehrend es die schlechten verhindert.

    volkard schrieb:

    Nur das, was jetzt soo viele Klassen innendrin selber machen müssen, um movable zu sein.

    Also extra Arbeit, weil volkards move sowas nicht erlaubt.

    volkard schrieb:

    Es kann nicht ungültig sein. :p

    Was soll das denn jetzt heissen? Willst du v[0] einfach ungueltige Syntax machen oder was?

    Und zu dem read-Problem: Da koennte man dann eigentlich uninitialized verwenden, dann brauchst du keinen Default Ctor. Vielleicht haste dann Recht, was Entities angeht. Da kann man auch uninitialized nehmen.



  • Kellerautomat schrieb:

    volkard schrieb:

    Nur das, was jetzt soo viele Klassen innendrin selber machen müssen, um movable zu sein.

    Also extra Arbeit, weil volkards move sowas nicht erlaubt.

    Die Vorteile würden überwiegen.

    Kellerautomat schrieb:

    volkard schrieb:

    Es kann nicht ungültig sein. :p

    Was soll das denn jetzt heissen? Willst du v[0] einfach ungueltige Syntax machen oder was?

    v[0] gäbe eine normale referenz zurück. also kann man das nicht wegmoven.



  • Kellerautomat schrieb:

    audacia schrieb:

    Das ist ja lustig. Und wenn die Exceptions anders hießen, würdest du dich evtl. überwinden, sie zu verwenden, anstatt sie von Hand nachzubauen?

    Noe. Ich will n Feature, das die guten Faelle von Exceptions erlaubt, waehrend es die schlechten verhindert.

    Bei "Fälle von Exceptions" geht es dir aber doch um Anwendungsszenarios, oder? Ansonsten verstehe ich nicht, wo du da in der Semantik eine Unterscheidung vornehmen willst. Kannst du das mal ausführen?

    volkard schrieb:

    v[0] gäbe eine normale referenz zurück. also kann man das nicht wegmoven.

    Und was ist dann hier:

    Movable u;
    Movable v[10];
    move (u); // u ist fortan unberührbar
    move (v[rand () % 10]); // ...und v?
    

    Gerade sowas brauche ich ja, wenn ich meinen eigenen Vector implementiere.



  • volkard schrieb:

    v[0] gäbe eine normale referenz zurück. also kann man das nicht wegmoven.

    Ok. D.h. eine normale Referenz kann man nicht moven, weil man nur Observer ist. Das ergibt sogar Sinn. Aber wie willst du dann Objekte wieder aus einem vector rausbekommen, wenn man ihn nicht mehr braucht?



  • Kellerautomat schrieb:

    volkard schrieb:

    v[0] gäbe eine normale referenz zurück. also kann man das nicht wegmoven.

    Ok. D.h. eine normale Referenz kann man nicht moven, weil man nur Observer ist. Das ergibt sogar Sinn. Aber wie willst du dann Objekte wieder aus einem vector rausbekommen, wenn man ihn nicht mehr braucht?

    resize, clear, überschreiben.


Anmelden zum Antworten