Von C zu Rust wechseln?



  • großbuchstaben schrieb:

    Gut, dann brauche ich ja nicht zu rust zu wechseln (hatte ich eh' nicht vor)

    Ich habe das trotzdem gemacht, weil ich das Programmieren einfacher finde. Keine unnoetigen move-Aufrufe oder copy-constructors, automatische Generierung einfacher Operationen wie Vergleiche, Debug-Print, pattern matching statt grosser if-verzweigungen, bloecke als expressions, array-referenzen in die Sprache eingebaut, enums statt Variant, viel einfachere und maechtigere iteratoren, eingebaute tuples, type inference, bessere Fehlermeldungen, bessere Standard-library, einfaches Multithreading, besseres Errorhandling und viel weniger Debuggen.



  • Marthog schrieb:

    Ich habe das trotzdem gemacht, weil ich das Programmieren einfacher finde. Keine unnoetigen move-Aufrufe oder copy-constructors, automatische Generierung einfacher Operationen wie Vergleiche, Debug-Print, pattern matching statt grosser if-verzweigungen, bloecke als expressions, array-referenzen in die Sprache eingebaut, enums statt Variant, viel einfachere und maechtigere iteratoren, eingebaute tuples, type inference, bessere Fehlermeldungen, bessere Standard-library, einfaches Multithreading, besseres Errorhandling und viel weniger Debuggen.

    👍

    Ich mag auch cargo als Build- und Abhängigkeitsmanagement-Tool und das Ökosystem drumherum. Hab sogar jetzt mal ein kleines crate auf crate.io hochgeladen: crc24 für die Berechnung von CRC-24 Prüfsummen nach IETF RFC2440. 🙂



  • Seid ihr eigentlich immer noch nicht fertig mit der Rust Diskussion?



  • krümelkacker schrieb:

    Ich mag auch cargo als Build- und Abhängigkeitsmanagement-Tool und das Ökosystem drumherum.

    Sowas gibts aber auch für C++: biicode.com



  • Marthog schrieb:

    Ich habe das trotzdem gemacht, weil ich das Programmieren einfacher finde. Keine unnoetigen move-Aufrufe

    hab' ich mit C++ auch nicht.

    Marthog schrieb:

    oder copy-constructors,

    hab' ich mit C++ auch nicht, jedenfalls keine unnötigen, und wenn sie nötig sind, dann bin ich eigentlich eher froh, daß ich sie explizit machen muß.

    Marthog schrieb:

    automatische Generierung einfacher Operationen wie Vergleiche, Debug-Print,

    Debug-print hört sich ungefähr nach dem an, was ich mit do-it-yourself Protokoll-Klassen mache

    Marthog schrieb:

    pattern matching statt grosser if-verzweigungen,

    große if-Verzweigungen habe ich nicht, selten mal zweistufig. Tiefe if-Bäume halte ich nur in Ausnahmesituationen für guten Programmierstil.

    Marthog schrieb:

    viel einfachere und maechtigere iteratoren,

    in C++ kann ich Iterator-Klassen selbst definieren, mehr Flexibilität kann ich mir nicht vorstellen.

    Marthog schrieb:

    eingebaute tuples,

    "eingebaut" ist weniger flexibel als entsprechende Klassen in der standard lib. Dito mit syntaktischen Erweiterungen. Die C++-Strategie "eher die standard lib als die Syntax erweitern" ist schön flexibel, da im Bedarfsfall austauschbar.

    Marthog schrieb:

    type inference,

    auto
    

    Marthog schrieb:

    bessere Fehlermeldungen,

    das würde ich mir bei Template-Code öfter wünschen. Aber erstens wechsle ich deswegen nicht die Sprache, und außerdem werden die "concepts" (war glaub' schon bei C++0x im Gespräch, hat es aber leider nicht in C++11 geschafft) hier wohl Verbesserungen bringen, da die Anforderungen an Typ-Parameter verexplifiziert werden, was den Compiler früher erkennen läßt, ob eine Template-Instanziierung zulässig sein wird.

    Marthog schrieb:

    bessere Standard-library,

    mir fehlt in der C++11 Standard lib erstmal nichts, im Gegenteil, ich finde sie mit smart pointer, threads u.v.a. recht üppig ausgestattet.

    Marthog schrieb:

    einfaches Multithreading,

    darüber ließe sich diskutieren. Aber ob man das in die Sprach-Syntax einbauen soll, ist diskussionswürdig - mit einer entsprechend ausgestatteten standard lib ist man flexibel und könnte wahlweise aus Prozessebene, aus Threadebene, aus noch-mehr-lightweight- oder Coroutine-Ebene auswählen, was man braucht.

    Marthog schrieb:

    besseres Errorhandling und viel weniger Debuggen.

    ich entwickle täglich C++ und brauche den Debugger fast nie. Mein Entwicklungsstil ist "erst denken, dann tippen, dann testen" und kostet mich typischerweise weniger Zeit als "erst tippen, dann testen, dann debuggen, dann denken, dann neu tippen" 🙂



  • Ich gehe bewusst nur auf zwei einzelne Punkte ein:

    großbuchstaben schrieb:

    "eingebaut" ist weniger flexibel als entsprechende Klassen in der standard lib. Dito mit syntaktischen Erweiterungen. Die C++-Strategie "eher die standard lib als die Syntax erweitern" ist schön flexibel, da im Bedarfsfall austauschbar.

    Ich mag den C++-Ansatz auch sehr und finde es unschön, wenn andere Sprachen mit Features vollgeknallt werden, die man genau so gut als Bibliothek anbieten könnte. Allerdings hat die Strategie auch Nachteile, etwa schlechtere Integration. Beispiel: bevor es Lambdas gab, nahm man oft boost::lambda (inzwischen sogar Teil des Standards). Und im Prinzip ist es auch eine tolle Idee, dass man sich anonyme Funktionen mit _1 * 2 , _1 + _1 o.ä. bauen kann. Aber z.B. sqrt(_1) geht nicht. Offenbar fand man die Einschränkungen groß genug, um Lambdas als Sprachfeature aufzunehmen.

    großbuchstaben schrieb:

    Marthog schrieb:

    type inference,

    auto
    

    Auto ist deutlich weniger mächtig als type inference. Type inference erlaubt das inferieren des Typs einer Variable auch daraus, wie sie später benutzt wird.



  • großbuchstaben schrieb:

    Marthog schrieb:

    Keine unnoetigen move-Aufrufe

    hab' ich mit C++ auch nicht.

    Mir knallt der Compiler immer wieder unnoetige kopien rein.

    unique_ptr<SomeType> a;
     ...
    auto b = a; // error, weil kein move
    

    In Rust hat man default-move und kopien lediglich bei primitiven Datentypen oder per explizitem .clone()-Aufruf.

    großbuchstaben schrieb:

    Marthog schrieb:

    oder copy-constructors,

    hab' ich mit C++ auch nicht, jedenfalls keine unnötigen, und wenn sie nötig sind, dann bin ich eigentlich eher froh, daß ich sie explizit machen muß.

    Im Gegenteil. In C++ werden sie implizit generiert und muss sie explizit deaktivieren. Ausserdem muss man die rule-of-three (bzw. five) beachten. In Rust gibt es erstmal gar nichts und alles muss man sich explizit dazuschreiben oder mit einer expliziten Anweisung automatisch generieren lassen.

    großbuchstaben schrieb:

    Debug-print hört sich ungefähr nach dem an, was ich mit do-it-yourself Protokoll-Klassen mache

    EInmal #[deriving(Debug)] vor die Klasse schreiben und schon wird einem das alles automatisch generiert. Wenn man will, kann man immer noch die entsprechende Methode ueberschreiben. Einzig allein in Haskell ist es genauso einfach.

    großbuchstaben schrieb:

    Marthog schrieb:

    viel einfachere und maechtigere iteratoren,

    in C++ kann ich Iterator-Klassen selbst definieren, mehr Flexibilität kann ich mir nicht vorstellen.

    In C++ sind die iteratoren zu 80% boilerplate. boost::iterator_facade macht das einfacher, aber in Rust reicht Fall eine Methode, die ein Option<SomeType> zurueckgibt und nur fuer spezielle Faelle muss man mehr schreiben. Zudem hat man gleich auch wichtige operationen wie map, filter, fold, zip als Wrapper fuer diese Iteratoren vordefiniert.

    großbuchstaben schrieb:

    Marthog schrieb:

    eingebaute tuples,

    "eingebaut" ist weniger flexibel als entsprechende Klassen in der standard lib. Dito mit syntaktischen Erweiterungen. Die C++-Strategie "eher die standard lib als die Syntax erweitern" ist schön flexibel, da im Bedarfsfall austauschbar.

    großbuchstaben schrieb:

    Marthog schrieb:

    einfaches Multithreading,

    darüber ließe sich diskutieren. Aber ob man das in die Sprach-Syntax einbauen soll, ist diskussionswürdig - mit einer entsprechend ausgestatteten standard lib ist man flexibel und könnte wahlweise aus Prozessebene, aus Threadebene, aus noch-mehr-lightweight- oder Coroutine-Ebene auswählen, was man braucht.

    Rust hat einen ziemlich kleinen Sprachkern, bzw der Hauptteil geht fuer die Auswertungsregeln der traits (sind quasi verpflichtende concepts) drauf. Tatsaechlich ist fast alles in der Standard-library geregelt. Der Sprachkern sorgt sich lediglich um ein paar sicherheitsregeln.

    Beispiel:

    let (tx, rx) = mpsc::channel();
    
    spawn(move || {
        while some_condition {
            let val = calculate_something();
            tx.send(val);
        }
    });
    

    Der Sprachkern kuemmert sich um type inference (man muss keine Datentypen angeben), moves (tx wird in die innere Funktion verschoben und ist von ausserhalb nicht sichtbar), Pattern matching (der rueckgabewert von channel() wird in die komponenten aufgeloest). Alles andere wie channel, spawn, Transmitter, Receiver wird in der Standardlibrary definiert.



  • Es ist eine Riesenunterschied ab man alles als Libs zu einer Sprache hinzufügen muss, oder ob alles in einer Sprache fest eingebaut ist und auch vom Compiler sicher gestellt wird, dass weder Anfänger noch Profis in der Hinsicht je eine Fehler machen können. Rust ist in meinen Augen aus den Unzulänglichkeiten von C++ entstanden und in diesen Bereichen von Natur aus besser. Ob es ankommt werden wir sehen. Auf jeden Fall ist es von Embedded bis zur Webapp einsetzbar und jedes Projekt das man mit C oder C++ machen kann ist auch für Rust geeignet.

    Hier wird behauptet C++ habe keine derartigen Unzulänglichkeiten, oder da muss der Programmierer halt aufpassen. Dieses Aufpassen wird schwieriger je mehr Leute an einem Projekt arbeiten und je größer das Projekt wird. Bei Rust ist es egal wie viele Leute daran arbeiten, ob es Profis oder Rookies sind und auch wenn das Projekt ein Windows oder Linux sein sollte. Eine bestimmte, sehr relevante, Art von Fehler kann nie auftreten. Wenn man solche Fehler vermutet, dann braucht man nur in den unsafe-Blöcken nach schauen und nicht im gesamten Projekt. Was meint ihr wie viel Arbeitszeit und Stress so eine Sprache spart und wie viel mehr Sicherheit sie mit Zero-Costs einem schenkt.

    Keine neue Sprache zuvor hat mich derart vom Hocker gerissen wie Rust. Die Sicherheit nur dem Entwickler zu überlassen ist wirklich sehr sehr dumm, aber es gingt bis jetzt nicht anderes C++ hat das vieles besser als C gemacht und Rust macht vieles besser als C++. Es gibt nun einmal auch in der IT eine Evolution und von zehn neuen Sprachen ist mal eine dabei, die dann die Herrschaft übernimmt, obwohl die C++ eh nur noch sehr wenig eingesetzt wird. Eigentlich nur in Programme die absolute Performance brauchen, bei allen anderen Projekten greift man sehr sehr gerne zu besseren Lösungen.



  • Realität schrieb:

    [...]obwohl die C++ eh nur noch sehr wenig eingesetzt wird.

    Interessant.



  • Was asfdlol?? Hast du noch nicht mitbekommen, daß C++ selbst im hpc längst nicht mehr stand der dinge ist!?



  • Swordfish schrieb:

    Was asfdlol?? Hast du noch nicht mitbekommen, daß C++ selbst im hpc längst nicht mehr stand der dinge ist!?

    Nur so aus Interesse - was ist denn dort so Stand der Dinge?



  • FORTRAN 77... :p



  • Swordfish schrieb:

    Was asfdlol?? Hast du noch nicht mitbekommen, daß C++ selbst im hpc längst nicht mehr stand der dinge ist!?

    Bisschen was habe ich letztens mitbekommen. In meinem Chip.de-Magazin stand, dass nun vor allem die NASA auf Java und Rust setzt. Stimmt das? 🙂
    Ich überlege mir derzeit auch zu wechseln, da mir in C++ immer wieder doofe Speicherfehler passieren. An dieser Knacknuss war ich gestern den ganzen Tag dran:

    int* Datas = new int(0);
    try
    {
    	std::cin >> *reinterpret_cast<int*>(&Datas);
    }
    catch(...)
    {
    	std::cerr << "Fehler aufgetreten, Programm wird terminiert!" << std::endl << std::endl;
    	delete Datas;
    	return -1;
    }
    f(*Datas);
    delete Datas;
    

    In Java oder in Rust wäre mir das nicht passiert...



  • asfdlol schrieb:

    int* Datas = new int(0);
    try
    {
    	std::cin >> *reinterpret_cast<int*>(&Datas);
    }
    catch(...)
    {
    	std::cerr << "Fehler aufgetreten, Programm wird terminiert!" << std::endl << std::endl;
    	delete Datas;
    	return -1;
    }
    f(*Datas);
    delete Datas;
    

    Zwei Fragen:
    1. Was war der Fehler? 🙂
    2. Wieso castest du überhaupt und wieso benutzt du ein & auf einen Pointer?
    3. Wieso hast du überhaupt ein new gemacht? Hättest du doch auch auf dem Stack anlegen können, oder?





  • Der Grund, weshalb rust erfolgreich sein wird, ist, dass genügend Leute an den Erfolg glauben. D. h., sie werden die Programmiersprache einfach nutzen. Es existiert ja schon jetzt ein brauchbares Buildsystem. Es fängt also schon mit der Tool-Chain an. Außerdem gibt es eine llvm-Integration. Und das Interesse hier im Forum ist auch ein Anzeichen dafür, dass manche C++ endlich abgelöst sehen wollen.



  • Also wird Rust so erfolgreich wie Prolog und Haskell? Wobei, die taugen als Lehrsprachen von daher werden sie durch Universitäten verbreitet, Rust taugt dafür eher schlecht.



  • Du scheinst es nicht verstanden zu haben. Rust taugt als C++ Ersatz. :p



  • Und du meinst man hat Lust auf eine neue Krankheit, die man mit sich herumschleppen muss? 😞



  • Du scheinst es nicht verstanden zu haben. Rust ist perfekt.

    Ok, sorry, der musste sein.


Anmelden zum Antworten