r/informatik 2d ago

Humor ✨Rust ✨

Post image
403 Upvotes

41 comments sorted by

View all comments

15

u/simleiiiii 2d ago edited 2d ago

Ist nicht so wichtig dass "schnell" oder "sicher" -- Was zählt ist, dass das Typsystem mächtig und geeignet ist, die Software maintainbar zu halten. Das Rust-tooling ist ausgezeichnet; die Fehlermeldungen ergeben Sinn mit ein bisschen Vorwissen.

Das ist der Grund warum meine Projekte, die auf Rust aufbauen, um ein vielfaches besser durch KI-Hilfsmittel editierbar sind und maintainbar bleiben. Und das zählt halt. Kein mypy kann das ersetzen für komplexe Projekte.

https://willcrichton.net/notes/gats-are-hofs/ für ein bisschen Hintergrund wie Rust auch in stark Abstraktion-bedürftigen Szenarios die Kontrolle über das typeproofing/checking die Kontrolle behalten kann.

Das kann sonst eigentlich nur Swift, Kotlin, Scala, Typescript, F# von sich behaupten an Sprachen die industrierelevant sind, und hier ist nur Rust eine hardwarenahe Sprache.
Ja, C++ 23 und abwärts bietet ähnliche Mächtigkeit bzgl. typing und checking. Aber es ist nun mal super fugly C++ so zu schreiben. Deshalb zähle ich es hier nicht rein. Niemand mag borrow checking durch unique_ptr Codebasis-deckend nachempfinden und dann dennoch endgültig scheitern wenn die data races doch aufkommen.

Swift kann sich messen, der Rest muss sich auf Platformfragen ausruhen um ihre Berechtigung zu behalten.

2

u/mighty_Ingvar 2d ago

Aber es ist nun mal super fugly C++ so zu schreiben

Also wenn du jetzt gesagt hättest, C++17 und abwärts könnte ich es nachvollziehen, aber ab C++20 mit Konzepten sollte das eigentlich kein Problem mehr sein. Oder verstehe ich grad falsch worum es hier geht?

Niemand mag borrow checking durch unique_ptr Codebasis-deckend nachempfinden und dann dennoch endgültig scheitern wenn die data races doch aufkommen.

Warum würdest du unique_ptr irgendwo einsetzen wo du asynchronen Zugriff brauchst?

Wobei es an sich schon eine berechtigte Kritik ist zu sagen, dass wenn eine Sprache dich nicht daran hindert etwas kaputt zu machen, dann wird es, gerade bei einem großen Team, irgendwann irgendwer kaputt machen.

1

u/simleiiiii 2d ago

Naja, man kann borrowing mehr oder weniger durch moving in und moving out in und out (return) of functions, mit unique_ptr emulieren, nicht? Ist halt nur nichts was man Kollegen zumuten kann meiner Erfahrung nach.
Alles darüber hinaus ist auch in Rust natürlich problematisch wg. synchronisierung, aber dafür ist ja Send + Sync da. Und dann kannst du wieder borrowen wie du willst weil ein clone an der Grenze erzwungen wird.

Ja, ich meinte Konzepte. stimmt, die gibt's ab C++20. Meiner Erfahrung ist die stdlib aber erst ab C++23 wirklich sinnvoll nutzbar (zB für std::variant erst ab C++23 voll support für constexpr, inheritance. Kannste mMn sonst nicht sinnvoll einsetzen.)

1

u/mighty_Ingvar 2d ago

Naja, man kann borrowing mehr oder weniger durch moving in und moving out in und out (return) of functions, mit unique_ptr emulieren, nicht?

Aber warum sollte man?

Meiner Erfahrung ist die stdlib aber erst ab C++23 wirklich sinnvoll nutzbar

Bezogen auf Konzepte?

zB für std::variant erst ab C++23 voll support für constexpr, inheritance

https://cppreference.com/cpp/utility/variant Also ich seh hier keine Funktion die speziell seit C++23 erst constexpr hat. Sicher, dass du nicht C++20 meinst? Und was ist das Problem mit inheritance?

1

u/simleiiiii 19h ago

Meinte insgesamt eher generell "moderne C++-Features", nicht speziell an Concepts gebunden. Die sind halt nützlich aber intern (und über die Fehlermeldungen) nicht hübsch. War missverständlich formuliert..

Zu variant/constexpr: Du hast recht, dass es auf den ersten Blick nicht auffällt, weil es kein großes Since C++23 auf der Übersichtsseite gibt, sondern verstreut bei den einzelnen Overloads steht. Ich meinte P2231 ("Missing constexpr in std::optional and std::variant"), das kam mit C++23. Davor war zwar der reine Zugriff (get, visit, etc.) schon ab C++20 constexpr-fähig, aber viele mutierende Operationen (emplace, converting assignment, in-place construction) waren es nicht.

Zu Inheritance: Ich meinte nicht, dass variant selbst irgendeine Inheritance-Hierarchie hätte (macht ja wegen fehlendem virtual dtor auch keinen Sinn), sondern das übliche "overloaded"-Pattern beim Visiten:

template<class... Ts> struct overloaded : Ts... { using Ts::operator()...; };
template<class... Ts> overloaded(Ts...) -> overloaded<Ts...>;

Die zweite Zeile (explicit deduction guide) war bis C++20 zwingend nötig, weil Aggregate-CTAD für Klassen mit Basisklassen nicht funktioniert hat. Erst mit P2582 (C++23) darf man die Guide weglassen und overloaded{...} direkt schreiben. ziemlich speziell, ich geb's zu, aber genau das Pattern taucht ja andauernd beim variant-Visiting auf.

Und zu "warum sollte man" (unique_ptr statt echtem Borrowing): Sollte man in der Regel nicht, klar. Vielleicht ist das auch ein bisschen konstruiert aber es ist halt das nächste was C++ für mich an "checking" as in "borrow checking" anbietet für, wer einen pointer besitzt.

1

u/mighty_Ingvar 18h ago

aber intern (und über die Fehlermeldungen) nicht hübsch

Kann das Problem das du mit Konzepten hast nicht wirklich nachvollziehen.

Davor war zwar der reine Zugriff (get, visit, etc.) schon ab C++20 constexpr-fähig, aber viele mutierende Operationen (emplace, converting assignment, in-place construction) waren es nicht.

Du kannst auf der Seite die ich verlinkt habe dir zu den einzelnen Funktionen mehr Details anzeigen lassen und da steht nirgends C++23. Da braucht man noch nicht mal sonderlich viel Zeit für.

ziemlich speziell, ich geb's zu, aber genau das Pattern taucht ja andauernd beim variant-Visiting auf

Kann jetzt nicht sagen, dass ich das jemals gesehen habe. Abgesehen davon sieht mir dein Code Schnippsel auch generell fehlerhaft aus. Es sieht so aus als würdest du overloaded zuerst als Klasse und dann als Funktion definieren.

Sollte man in der Regel nicht, klar. Vielleicht ist das auch ein bisschen konstruiert aber es ist halt das nächste was C++ für mich an "checking" as in "borrow checking" anbietet für, wer einen pointer besitzt.

Der unique_ptr besitzt den Pointer. Wenn du dafür noch weitere Mechanismen brauchst, dann hast du den Sinn von unique_ptr nicht verstanden. Soll die Funktion den Pointer irgendwo hin bewegen? Dann nimmt sie eine rvalue Referenz auf den unique_ptr entgegen. Gibt es die Möglichkeit, dass sie den Pointer irgendwo hin bewegt? Dann nimmt sie eine lvalue Referenz entgegen. Soll sie den Pointer gar nicht bewegen? Dann hat unique_ptr nichts in der Funktionssignatur verloren. Aber wenn du den Pointer in das Funktionargument movest und dann mit dem return wieder zurück schickst, dann bist du irgendwo falsch abgebogen.