Yalu X. schrieb:> @privatfrickler:>> Die deutsche Übersetzung des Rust-Handbuchs ist uralt. Nimm besser> dieses hier>> https://doc.rust-lang.org/book/2018-edition/>> oder – falls dir das ebenfalls nicht zusagt – such dir eins von hier> aus, das besser deinem Geschmack entspricht:>> https://hackr.io/tutorials/learn-rust
@Yalu
Danke für deinen Hinweis. Werde mir das mit etwas Abstand nochmals
genauer betrachten. Ich bin gar nicht so extrem pingelig wie es
vielleicht den Anschein weckt. Ich merke halt sehr schnell ob ein Text
mich motiviert oder aber wie bei dem Geschwafel in mir das völlige
Gegenteil bewirkt.
Hallo,
Privatfrickler schrieb:> "let y = &x[0];">> y sei nun das erste Element des Vektors x ?
ja, aber viel weitreichender, als man sich so denkt? Denn, wenn ich das
richtig sehe, kann man jetzt in x[0] nicht mehr schreiben?
vlg
Timm
Timm R. schrieb:> ja, aber viel weitreichender, als man sich so denkt? Denn, wenn ich das> richtig sehe, kann man jetzt in x[0] nicht mehr schreiben?
Es geht sogar noch weiter: Du kannst in keins der Elemente von x
schreiben.
1
fn main() {
2
let mut x = vec!["Hallo", "Welt"];
3
let y = &x[0];
4
5
x[0] = "Hello";
6
x[1] = "World";
7
8
println!("{:?}", x);
9
}
1
error[E0502]: cannot borrow `x` as mutable because it is also borrowed as immutable
2
--> src/main.rs:5:5
3
|
4
3 | let y = &x[0];
5
| - immutable borrow occurs here
6
4 |
7
5 | x[0] = "Hello";
8
| ^ mutable borrow occurs here
9
...
10
9 | }
11
| - immutable borrow ends here
12
13
error[E0502]: cannot borrow `x` as mutable because it is also borrowed as immutable
14
--> src/main.rs:6:5
15
|
16
3 | let y = &x[0];
17
| - immutable borrow occurs here
18
...
19
6 | x[1] = "World";
20
| ^ mutable borrow occurs here
21
...
22
9 | }
23
| - immutable borrow ends here
24
25
error: aborting due to 2 previous errors
26
27
For more information about this error, try `rustc --explain E0502`.
Was du aber machen kannst: Mittels shadowing ein neues x anlegen.
Hmm,
gut, in C++ kann man einen std::vector gar nicht mit einem structured
binding verarzten, in sofern ...
Aber andererseits? Wegen einem Binding gleich das ganze Objekt
blockieren?
Ich glaube, das gefällt mir nicht.
vlg
Timm
Hallo Alex,
Alex G. schrieb:> Timm R. schrieb:>> Könnte sich denn vielleicht einer der Rust-kundigen und C++-kundigen>> erbarmen, mal ein minimales Beispiel mit c++ Pointer-Katastrophe zu>> zeigen und wie es in Rust besser läuft? Das wäre doch sicher für mehrere>> Rist-Unkundige interessant und erhellend? Mir fehlt da einfach die>> Vorstellungskraft.>> Hmm, du hättest bei meinem Vortrag vor ein paar Wochen über Rust dabei> sein sollen.> Dafür habe ich den Heartbleed Bug in C++ nachprogrammiert - und dann> versucht ihn auch unter Rust zu programmieren (ohne Unsafe).
also, erstmal danke für das instruktive Programm. Ja, das ist ein
Beispiel für einen echten Sicherheitsgewinn. Ich möchte aber doch
anmerken, m.h. tat das ja schon, wenn auch etwas stoffelig, dass das
kein C++ ist.
Vielmehr wird ziemlich klar, dass auch in diesem Fall richtiges C++ das
Problem schon gelöst hätte.
Yalus Beispiel ist zwar valide. Aber auch da bin ich unschlüssig, ob
den Tausch Brauchbarkeit der Features gegen eine bedingt relevante
Sicherheit profitabel finde.
vlg
Timm
Rust ist ganz klar einschränkend - bietet aber wiederum Strukturen um
solche Einschränkungen ganz kontrolliert wieder aufzuheben.
Z.B. die CELL Datenstruktur.
Auch wenn ich hiermit meinen Realnamen preisgebe - hier habe ich einen
Blogeintrag über Rust und RustBelt geschrieben:
https://blog.mi.hdm-stuttgart.de/index.php/2018/07/23/rust-safety-during-and-after-programming/
Das enthält auch eine zusammenhängende Ausführung des Grundgedanken
dieser Sprache mit Beispielen,
Timm R. schrieb:> Wegen einem Binding gleich das ganze Objekt> blockieren?>> Ich glaube, das gefällt mir nicht.
Es ist ja nicht (vollstaendig) blockiert. Lesen kannst du noch ohne
Probleme.
1
fn main() {
2
let mut x = vec!["Hallo", "Welt"];
3
let y = &x[0];
4
5
println!("x: `{:?}`", x);
6
println!("y: `{:?}`", y);
7
}
1
x: `["Hallo", "Welt"]`
2
y: `"Hallo"`
Ja, das Ownershipkonzept erfordert etwas umdenken, verglichen mit C und
C++. Aber das Umdenken zahlt sich aus.
Kaj schrieb:> Timm R. schrieb:>> Wegen einem Binding gleich das ganze Objekt>> blockieren?>>>> Ich glaube, das gefällt mir nicht.> Es ist ja nicht (vollstaendig) blockiert. Lesen kannst du noch ohne> Probleme.
Als weiterfuehrung zu meiner vorherigen Antwort:
Timm R. schrieb:> gut, in C++ kann man einen std::vector gar nicht mit einem structured> binding verarzten, in sofern ...>> Aber andererseits? Wegen einem Binding gleich das ganze Objekt> blockieren?>> Ich glaube, das gefällt mir nicht.
Spiel einfach mal ein bisschen mit Rust. Theoretisch kannst du Rust
'einfach' als C/C++ mit invertierten Regeln betrachten (grob gesagt).
==================================================
Beispiel 1, C/C++:
1
voidfoo(void)
2
{
3
//...
4
}
Diese Funktion ist praktisch fuer jede andere Uebersetzungseinheit
sichtbar, da sie nicht static ist (ja, es muss noch die .h-Datei
eingebunden werden, ich weiss).
Beispiel 1, Rust:
1
fn foo() {
2
//...
3
}
Diese Funktion ist nur innerhalb der Datei in der sie steht, sichtbar,
da sie nicht explizit sichtbar gemacht wurde. Soll sie auch in anderen
Uebersetzungseinheit sichtbar sein, dann muss das so aussehen:
1
pub fn foo() {
2
//...
3
}
C und C++: Sichtbarkeit muss explizit eingeschraenkt werden.
Rust: Sichtbarkeit muss explizit ausgeweitet werden.
==================================================
Beispiel 2, C/C++:
1
intmain(void)
2
{
3
inta=0;
4
// ...
5
return0;
6
}
Die Variable a kann beschrieben werden, da sie nicht const ist.
Beispiel 2, Rust:
1
fn main()
2
{
3
let a: i32 = 0;
4
// ...
5
return 0;
6
}
Die Variable a ist read-only (aber nicht const(!)), da sie nicht mut
ist. Das heisst: man kann a mittels shadowing ueberdecken. Das geht bei
einer Konstanten nicht.
1
fn main() {
2
const A:i32 = 42;
3
let A: i32 = 43;
4
}
5
6
error[E0005]: refutable pattern in local binding: `_` not covered
7
--> src/main.rs:3:9
8
|
9
3 | let A: i32 = 43;
10
| ^ interpreted as a constant pattern, not new variable
1
fn main() {
2
const A:i32 = 42;
3
let mut A: i32 = 44;
4
}
5
6
error[E0530]: let bindings cannot shadow constants
7
--> src/main.rs:3:13
8
|
9
2 | const A:i32 = 42;
10
| ----------------- a constant `A` is defined here
11
3 | let mut A: i32 = 44;
12
| ^ cannot be named the same as a constant
C und C++: Schreibrechte muessen explizit entzogen werden.
Rust: Schreibrechte muessen explizit erteilt werden.
==================================================
Und so zieht es sich immer weiter. Wenn du es eben so betrachtest, dass
Rust "nur ein invertiertes C/C++" ist, dann duerfte es dir leichter
fallen die Sprache zu verstehen. So geht es zumindestens mir. Und genau
durch diese 'Invertierung' erreicht Rust schon eine hoehere Sicherheit.
Gruesse
Hallo Karl,
ja das ist soweit sehr interessant und hilfreich. Auch die Logik
verstehe ich: der unaufmerksame Tipper tippt per default maximale
Sicherheit.
Das gefällt mir auch sehr gut.
Borrowing als Alternative zu RAII erscheint mir allerdings wie die
Therapie von Kopfschmerz durch Dekaputation. Da bin ich mir nicht
sicher, ob das rockt.
Was ja sehr heiß sein soll ist die concurrency bei Rust. Vielleicht
hilft da das Borrowing auch?
In c++ ist das Thema ja jetzt mit C++17 und später überhaupt erst auf
dem Tapet.
Viele liebe Grüße
timm
Timm R. schrieb:> Was ja sehr heiß sein soll ist die concurrency bei Rust. Vielleicht> hilft da das Borrowing auch?
Ja, das Ownership-System wurde eben wegen den Gefahren von nebenläufigen
Code entworfen. In Rust ist es ebenso, dass ein Objekt entweder
immutable ist, dann können mehrere darauf zugreifen, oder es ist mutable
aber nur der Besitzer hat Schreibzugriff. Das Ownership-System
garantiert das und deshalb können auch keine Raceconditions in Plain
Rust auftreten. Natürlich lässt sich das mithilfe von unsafe umgehen,
damit man trotzdem Semaphore und Co. in Rust umsetzen kann.
Durch das Ownership-System hat Rust definitiv ein nützliches
Alleinstellungsmerkmal.
Kaj G. schrieb:> Using Message Passing to Transfer Data Between Threads
Das ist übrigens ganz generell ein Entwurfsmuster das es auch in andern
Sprachen sehr entspannt und angstfrei macht mit vielen Threads zu
arbeiten ohne in die Bredouille zu kommen. Alles was man braucht ist
eine threadsichere Queue.
RalfW schrieb im Beitrag #5520008:
> Warum tut man sich das freiwillig an?
Einmal hätte doch gereicht.
Also, WARUM ?
Es ist vielen C-Programmierern seit geraumer Zeit klar, daß die Sprache
C für die heutigen Bedürfnisse nicht mehr wirklich ausreicht und daß sie
nicht mehr renovierungsfähig ist. Sie ist dafür bereits seit langem zu
verkalkt.
Deshalb sinnieren viele C-Programmierer seit ebenso geraumer Zeit über
neue Sprachentwürfe nach, mit denen sie all die uralten Geburtsfehler
von C endlich hinter sich lassen können.
Dummerweise haben eben gerade die Programmierer, denen eine Nachfolge
für C durchaus am Herzen liegt, "ihr" C so tief verinnerlicht, daß sie
unfreiwillig bei jedem neuen Versuch einer neuen Programmiersprache
sofort wieder in ihre eingefahrenen Denk-Gleise zurückfallen.
Deswegen kommt bei jeder neu erfundenen Programmiersprache im Grunde
wieder nur C heraus, bloß hie und da mit irgendwelchen zusätzlichen
Kringeln versehen, die die praktische Anwendung regelmäßig verhindern.
Kurzum, die Leute kommen einfach nicht aus ihrem Tunnelblick heraus,
egal wie sie es anstellen.
Das ist das Tragische daran.
W.S.
W.S. schrieb:> Deswegen kommt bei jeder neu erfundenen Programmiersprache im Grunde> wieder nur C heraus, bloß hie und da mit irgendwelchen zusätzlichen> Kringeln versehen, die die praktische Anwendung regelmäßig verhindern.
Mein Gott, wie kann man nur so wenig Ahnung haben und trotzdem so
penetrant sein. Aber mach nur, mach dich weiter lächerlich, das steht
dir so gut. ;)
Zu glauben Rust wäre wie C, weil es syntaktische Ähnlichkeiten hat,
großartig. Das in etwa das Niveau von Moby...
Alex G. schrieb:> Du willst aber damit hoffentlich nicht ausdrücken dass das auch für Rust> gelten würde, oder?
Doch, leider. Ist mir auch so ziemlich als erstes aufgefallen:
Diese unsäglichen geschweiften Klammern zum Einfassen einer Funktion
oder Anweisung. Gleichzeitig benutzen sie es noch als Platzhalter.
Das C-typische = für Zuweisungen, == für Vergleiche. Ahhh. Nach zig
Jahren if x = y sollte man es doch mal verstanden haben, dass das
Bullshit ist.
Vielleicht könnte Rust das bessere C sein, aber es ist halt doch zuviel
C.
Karl K. schrieb:> Diese unsäglichen geschweiften Klammern zum Einfassen einer Funktion> oder Anweisung. Gleichzeitig benutzen sie es noch als Platzhalter.
Siehe hier:
TriHexagon schrieb:> Zu glauben Rust wäre wie C, weil es syntaktische Ähnlichkeiten hat,> großartig. Das in etwa das Niveau von Moby...Karl K. schrieb:> Das C-typische = für Zuweisungen, == für Vergleiche. Ahhh. Nach zig> Jahren if x = y sollte man es doch mal verstanden haben, dass das> Bullshit ist.
Da ist in Python oder Haskell auch so. Ist deswegen Python==Haskell==C?
Nein. Und auch Rust ist – bis auf diese beiden minimalen syntaktischen
Ähnlichenkeiten – völlig verschieden von C.
Karl K. schrieb:> Nach zig> Jahren if x = y sollte man es doch mal verstanden haben
Was faselst Du? Hast Du auch mal ausprobiert was Du da frech gelogen
unterstellst oder schwallst Du einfach nur so aus Langeweile dumm daher
damit irgendwas gesagt ist, ganz egal was?
Karl K. schrieb:> Alex G. schrieb:>> Du willst aber damit hoffentlich nicht ausdrücken dass das auch für Rust>> gelten würde, oder?>> Doch, leider. Ist mir auch so ziemlich als erstes aufgefallen:>> Diese unsäglichen geschweiften Klammern zum Einfassen einer Funktion> oder Anweisung. Gleichzeitig benutzen sie es noch als Platzhalter.>> Das C-typische = für Zuweisungen, == für Vergleiche. Ahhh. Nach zig> Jahren if x = y sollte man es doch mal verstanden haben, dass das> Bullshit ist.>> Vielleicht könnte Rust das bessere C sein, aber es ist halt doch zuviel> C.
Bei der Zuweisung gebe ich dir recht, da wäre ein := besser. Aber immer
noch besser als = == === in JavaScript ;-)
Die {} finde ich zum Einfassen von Blöcken nach wie vor besser leserlich
als das unsägliche Einrücken in Python. Einmal die Quelle mit den
falschen Einstellungen im Editor geladen und schon verhagelt es einem
die Funktion des Programms. Da ist mir eine Sprache mit geschweiften
Klammern lieber. Der Compiler weiß dann auch was zu tun ist, wenn
irgendwelche Whitespaces durch andere ersetzt/optimiert wurden.
Auf Rust bin ich erst durch diesen Thread aufmerksam geworden und habe
mich am Wochenende genauer damit beschäftigt. Bis jetzt finde ich die
Sprache sehr interessant. Ich programmiere seit über 20 Jahren im
embedded Bereich in C (nicht nur Projekte bei welchen zwei LEDs blinken
;-)) und sehne mich nach einer Sprache, welche ähnlich für die
Systemprogrammierung geeignet ist, mich vor Memory-Leaks, übergelaufenen
Arrays etc. bewahrt, nativ und nicht in einer VM ausgeführt wird und
keinen riesigen Overhead besitzt (z.B. Garbage Collector, fettes
Exception-Handling ... hat hier schon jemand C++ unter den Rock geschaut
... brrrr). Rust hat mich positiv überrascht, sogar Inline-Assembler ist
möglich.
Gruß
{}
W.S. schrieb:> die die praktische Anwendung regelmäßig verhindern.
Dann zeig doch bitte die "Kringel" die die Anwendung von Rust
verhindern.
W.S. schrieb:> Kurzum, die Leute kommen einfach nicht aus ihrem Tunnelblick heraus,> egal wie sie es anstellen.
Sagt ja der richtige...
Karl K. schrieb:> Vielleicht könnte Rust das bessere C sein, aber es ist halt doch zuviel> C.
Doof nur das Rust nicht viel mit C gemein hat, ausser etwas Syntax.
Karl K. schrieb:> Das C-typische = für Zuweisungen, == für Vergleiche. Ahhh. Nach zig> Jahren if x = y sollte man es doch mal verstanden haben, dass das> Bullshit ist.
Auch du hast dich null mit Rust beschaeftigt.
1. Das was du da schreibst compiliert in Rust gar nicht.
1
fn main() {
2
let mut x = 5;
3
let mut y = 7;
4
5
if x = y {
6
// ...
7
}
8
}
9
10
error[E0308]: mismatched types
11
--> src/main.rs:5:8
12
|
13
5 | if x = y {
14
| ^^^^^
15
| |
16
| expected bool, found ()
17
| help: try comparing for equality: `x == y`
18
|
19
= note: expected type `bool`
20
found type `()`
Wer glaubt, dass nur an den Typen von x und y liegt:
1
fn main() {
2
let x = true;
3
let y = false;
4
5
if x = y {
6
// ...
7
}
8
}
9
10
error[E0308]: mismatched types
11
--> src/main.rs:5:8
12
|
13
5 | if x = y {
14
| ^^^^^
15
| |
16
| expected bool, found ()
17
| help: try comparing for equality: `x == y`
18
|
19
= note: expected type `bool`
20
found type `()`
Eine Zuweisung liefert keinen bool.
2. In Rust muessen alle Ausdruecke bei einem if ein bool liefern, und
nicht etwas, das wie ein bool interpretiert werden koennte.
Was in C/C++ geht
Karl K. schrieb:> Diese unsäglichen geschweiften Klammern zum Einfassen einer Funktion> oder Anweisung. Gleichzeitig benutzen sie es noch als Platzhalter.
Wo ist denn das Problem? Weil man statt geschweiften Klammern alles mit
begin und end zu bombt? Ohne Syntax-Highlighting ist die Lesbarkeit mit
begin/end allerdings schlecht. Passiert wenn man den Code mit cat oder
diff ausgibt.
Karl K. schrieb:> Das C-typische = für Zuweisungen, == für Vergleiche. Ahhh. Nach zig> Jahren if x = y sollte man es doch mal verstanden haben, dass das> Bullshit ist.
Ist kein Bullshit, weil man damit elegant gleichzeitig Zuweisen und
Vergleichen kann. Gerade in Schleifenköpfe ist das praktisch.
Karl K. schrieb:> Vielleicht könnte Rust das bessere C sein, aber es ist halt doch zuviel> C.
Das ist reine Geschmacksache. Ich bevorzuge den Stil von C, aber
deswegen Kotze ich mich bei VHDL doch nicht aus... . Daran bemisst sich
ganz sicher nicht die Qualität von Rust, auch wenn es sich ein paar
Ewiggestrigene wünschen, die immer noch um Pascal trauern.
TriHexagon schrieb:> Karl K. schrieb:>> Das C-typische = für Zuweisungen, == für Vergleiche. Ahhh. Nach zig>> Jahren if x = y sollte man es doch mal verstanden haben, dass das>> Bullshit ist.>> Ist kein Bullshit, weil man damit elegant gleichzeitig Zuweisen und> Vergleichen kann. Gerade in Schleifenköpfe ist das praktisch.
Und das ist in Rust nicht einmal möglich, wie Kaj G. schon zeigte.
x = y = z;
hätte auch keinen Sinn, selbst wenn es gehen würde wenn man bedenkt was
der = Operator macht, je nachdem ob z copy ist oder nicht. Deshalb
braucht keiner sowas wie das was da oben steht und käme auch nie auf die
Idee sowas zu schreiben oder haben zu wollen.
Deshalb evaluiert eine Zuweisung immer zu (). Und () ist nicht bool.
Also hat Rust auch dieses Problem elegant über die Bande gespielt allein
mit dem Typsystem nachhaltig aus der Welt geschafft ohne irgendwelche
altgewohnte Syntax ändern zu müssen.
brackets schrieb:> Die {} finde ich zum Einfassen von Blöcken nach wie vor besser leserlich> als das unsägliche Einrücken in Python.
Wer sagt denn das es das Einrücken sein muß. Es gibt auch andere
Möglichkeiten Blöcke zusammenzufassen bzw. zu kennzeichnen.
Es soll ja Programmiersprachen geben die den Anfang und das Ende eines
Blockes im Klartext hinschreiben. Das empfinde ich als sehr angenehm,
weil gut lesbar ist. Wenn dann noch dazu sinnvoll eingerückt wird ist es
eigentlich optimal lesbar.
Ich kann auch mit der geschweiften Klammer leben - ist allemal besser
als das Einrückungsprinzip in Python. Einen Vorteil hat allerdings das
Pythonverfahren: Es zwingt zu einem sauberen Aufschreiben des
Quelltextes.
TriHexagon schrieb:> weil man damit elegant gleichzeitig Zuweisen und> Vergleichen kann. Gerade in Schleifenköpfe ist das praktisch.
Das ist eine ganz böse Falle, weil das auch mal richtig nach hinten los
gehen kann.
Im Übrigen ist dieses Verhalten nicht vom verwendeten
Zuweisungs-/Vergleichsoperator abhängig. Das könnte man mit jeder
beliebigen Zuweisungs-/Vergleichsoperatorkombination realisieren, weil
das letztendlich vom Compiler abhängt. Es hat aber schon gute Gründe,
das es Compiler gibt die so etwas nicht zu lassen. Zuweisen ist halt
etwas anderes als Vergleichen.
Karl K. schrieb:> Ja ok, ich sehe schon, Rust hat hier genauso arschlöchrige Fanboys wie> C. Damit ist die Diskussion hinfällig.
Sich zuerst überheblich an solchen Kleinigkeiten aufhängen, dann sich
eine blutige Nasse holen und gleich beleidigt abhauen. So ist recht.
Aber gut, eigentlich sollte es darum gar nicht gehen. Ich habe vor einem
Jahr einen einfachen Assembler in Rust geschrieben. Und muss sagen, dass
mir Rust sehr gut gefällt. Natürlich muss man sich ein bisschen mehr
Gedanken durch das Ownership-System machen, man wird aber belohnt. Ich
hatte allerdings noch nicht die Möglichkeit ein komplexeres Programm zu
schreiben mit vielen Datenstrukturen. Da wäre interessant wie gut das
geht.
Auch gefällt mir die Fehlerbehandlung in Rust durch nullable-Types mit
Verzicht auf Exceptions. Durchs Patternmatching lässt sich das auch
relativ elegant behandeln. Überhaupt sind diese mächtigen Enums wirklich
genial.
Wollte mir in nächster Zeit mal mit Rust auf einem ARM Cortex
beschäftigen, da sehe ich wirklich Potential.
Was hier im Forum ja auch ganz gerne an C/C++ bemaengelt wird: die
Endlosschleife.
In C/C++:
1
while(1){
2
3
}
4
5
for(;;){
6
7
}
Da wird ja auch gerne gemotzt, dass man das doch besser mit goto (oder
sonst wie) machen sollte, weil alles andere ja eine zweckentfremdung der
Schleife waere...
Auch das macht Rust ganz einfach:
Wie goto, nur deutlich weniger fehleranfaellig.
Was ich ebefalls schoen finde:
1
fn main() {
2
let cond = true;
3
4
let x = if cond {
5
5
6
} else {
7
6
8
};
9
}
In C/C++ muss man dazu x erstmal anlege und laesst es uninitialisiert
oder belegt es erstmal mit einen dummy Wert, der dann wieder
ueberschrieben werden muss.
Auf uninitialisierte Variablen kann in Rust nicht lesend zugegriffen
werden:
1
fn main() {
2
let x: i32;
3
let y = x;
4
}
5
6
error[E0381]: use of possibly uninitialized variable: `x`
7
--> src/main.rs:4:9
8
|
9
4 | let y = x;
10
| ^ use of possibly uninitialized `x`
Boom: Wieder ein typisches Problem von C und C++ einfach so aus dem Weg
geraeumt.
Wer hier immernoch die Meinung vertritt, das Rust wie C ist, der moege
doch bitte die Klappe halten. Ihr muesst es nicht nutzen, aber lasst uns
doch unseren Spass an dieser Sprache. Nicht jeder moechte stehen
bleiben, und Sprachen mit Konzepten (bzw. eher ohne Konzepten) von vor
ueber 20 Jahren nutzen.
Rust unterstuetzt den Entwickler besser als die meisten anderen Sprachen
(besonders besser als C und C++), um fehlerfreien/fehlerarmen Code zu
schreiben. Und der Entwickler muss sich weniger Gedanken um Dinge wie
undefined behavior machen, und kann sich mehr auf die eigentliche
Aufgabe konzentrieren, ohne dabei auf die Performance von C/C++
verzichten zu muessen.
TriHexagon schrieb:> Ich> hatte allerdings noch nicht die Möglichkeit ein komplexeres Programm zu> schreiben mit vielen Datenstrukturen. Da wäre interessant wie gut das> geht.
Wenn du ein grosses Projekt suchst, das in Rust geschrieben wird:
Sequoia-PGP
https://sequoia-pgp.org/
Zeno schrieb:> TriHexagon schrieb:>> weil man damit elegant gleichzeitig Zuweisen und>> Vergleichen kann. Gerade in Schleifenköpfe ist das praktisch.>> Das ist eine ganz böse Falle, weil das auch mal richtig nach hinten los> gehen kann.> Im Übrigen ist dieses Verhalten nicht vom verwendeten> Zuweisungs-/Vergleichsoperator abhängig. Das könnte man mit jeder> beliebigen Zuweisungs-/Vergleichsoperatorkombination realisieren, weil> das letztendlich vom Compiler abhängt. Es hat aber schon gute Gründe,> das es Compiler gibt die so etwas nicht zu lassen. Zuweisen ist halt> etwas anderes als Vergleichen.
Da hast du recht und ich kann total verstehen, dass man das verbieten
sollte. Aber die damalige Designentscheidung ist allerdings zumindest
nachvollziehbar und kein "Bullshit", auch wenns zu einem weiteren
Fallstrick führt.
Karl K. schrieb:> Ja ok, ich sehe schon, Rust hat hier genauso arschlöchrige> Fanboys wie C. Damit ist die Diskussion hinfällig.
Welche Sprache wäre denn deiner Meinung nach ein würdiger Nachfolger von
C? Jetzt sag aber bitte nicht C++ oder Assembler.
Apropos Enums:
Option und Result, wer fühlt sich bei diesen beiden Enums nicht sofort
an Haskell's Maybe und Either Monaden erinnert?
Auch das Auspacken in einem Pattern-Matching Konstrukt funktioniert
genauso, ein Datentyp der mehrere "Formen" mit komplett
unterschiedlichen Strukturen und Inhalten annehmen kann [wie ein union
aber doch wieder irgendwie ganz anders, mächtiger und sicherer], zum
Beispiel der Typ std::net::IpAddr ist ein Enum das entweder V4 oder V6
sein kann und je nachdem komplett unterschiedliche Datenfelder hat,
jedoch ist es vollkommen unmöglich Code zu schreiben der versehentlich
auf die jeweils falschen Felder zugreift wenn man gerade ein Exemplar
der einen oder der anderen Sorte vorliegen hat. Mit der selben Kraft des
Enums kann man versehentliche Nullpointer-Dereferenzierung unmöglich
machen.
Ich glaube die Enums wurden in diesem Thread noch nicht ausreichend
gewürdigt, ich finde dieses Konzept mindestens genauso genial wie das
Ownership-System (wenngleich es auch schon etwas älter ist und in
anderen Sprachen ebenfalls vorkommt), allein die Enums und das
Pattern-Matching machen die Sprache schon extrem mächtig und nützlich.
Irgendjemand hat auch mal Rust als Einstiegsdroge für Haskell
bezeichnet, ich weiß zu wenig über Haskell um das kommentieren zu können
aber mein Bauch sagt mir daß da zumindest teilweise was dran sein
könnte.
S. R. schrieb:> Welche Sprache wäre denn deiner Meinung nach ein würdiger Nachfolger von> C? Jetzt sag aber bitte nicht C++ oder Assembler.
Wer sagt, dass c einen Nachfolger hat oder braucht? Und wenn es einen
braucht, was spricht gegen c++?
Kaj G. schrieb:> Wie goto, nur deutlich weniger fehleranfaellig.
Warum ist es weniger fehleranfällig? Wenn man goto nur in dieser
Situation einsetzt, ist es das gleiche (das label steht an einer anderen
Stelle).
Kaj G. schrieb:> Was ich ebefalls schoen finde:fn main() {
1
let cond = true;
2
3
let x = if cond {
4
5
5
} else {
6
6
7
};
8
}
> In C/C++ muss man dazu x erstmal anlege und laesst es uninitialisiert> oder belegt es erstmal mit einen dummy Wert, der dann wieder> ueberschrieben werden muss.
Ja, in einigen Fällen kann man so ohne uninitialisierte Variable
auskommen, wo man sie in c++ nicht vermeiden kann. In den meisten Fällen
kann man uninitialisierte Variablen aber leicht umgehen. Für dein
Beispiel sieht das dann so aus:
1
autox=6;
2
if(cond){
3
x=5;
4
}
Der Compiler erzeugt vermutlich identischen Code. Bei komplizierternen
Fällen sollte man sich fragen, warum es so kompliziert ist und es
vereinfachen.
Dein Beispiel ist meiner Meinung nach ziemlich schlecht lesbar. Eine
Variablen wird über 5 Zeilen initialisiert. Ich muss 5 Zeilen lesen bis
ich weiß, welchen Wert und Typ x hat. If als Ausdruck mit Wert, macht
die Definition der Sprache vllt. einfacher und eleganter, aber für mich
nicht leichter lesbar. Genauso unübersichtlich sind Funktionen mit
Rückgabewert aber ohne return.
Kaj G. schrieb:> Boom: Wieder ein typisches Problem von C und C++ einfach so aus dem Weg> geraeumt.
Ich kann mich nicht daran erinnern, dass das für mich in c oder c++ im
letzten Jahrzehnt ein Problem gewesen ist. Nachdem ich den Fehler ein
paar mal gemacht habe, habe ich mir ganz schnell angewöhnt Variablen zu
initialisieren und Klassen so du designen, dass sie nur initialisiert
existieren können. Davon abgesehen warnt mich mein Compiler vor
uninitialiserten Variablen (bzw die ide während ich tippe).
Kaj G. schrieb:> use of possibly uninitialized `x`
Vor allem dieses "possibly" stört mich. Ich habe häufiger Variablen, bei
denen der Compiler nicht wissen kann, ob sie initialisiert sind oder
nicht. Und nein, es ist kein Sicherheitsrisiko, wenn man es sorgfältig
macht.