Rust


Gå til bund
Gravatar #2 - Claus Jørgensen
1. maj 2020 19:09
Sproget har i hvertfald nogle nuancer. Men kompileren er ret så genial. Det er på niveau med C# (hvis ikke bedre) til at foreslå hvad du har gjort forkert i din kode, advare mod unwanted copies/clones, unsafe, etc.

Jeg har et repo hvor jeg laver samme program i forskellige sprog, og Rust var faktisk ret nemt (en del nemmere end C!), https://github.com/clausjoergensen/game_of_life/bl...
Gravatar #3 - Claus Jørgensen
1. maj 2020 19:16
Et eksempel på hvor kompileren imponerede mig.

I C (og alle andre sprog) skrev jeg følgende:

if ((x - 1) >= 0) {

I Rust bliver man advaret mod at x - 1 vil "wrap around". Hvis man f.eks. brugte unsigned integers kunne det jo lede til en side-effekt i C (jeg mener ikke C++ har overflow på uints?)

Modsat hvis man skriver:

if x >= 1
opnår man samme løsning uden et potential overflow.

Specifikt ser man følgende:

warning: comparison is useless due to type limits
--> game_of_life.rs:11:8
|
11 | if (x - 1) >= 0 {
| ^^^^^^^^^^^^

Og så en runtime fejl:

thread 'main' panicked at 'attempt to subtract with overflow', game_of_life.rs:11:8
Gravatar #4 - arne_v
1. maj 2020 23:41
#3

[dine eksempler ikke ikke helt ens da du har valgt unsigned i Rust og signed i C/C++]

Der er vel reelt to problem stillinger her:

A) test som altid er sandt (en unsigned variabel >= 0)

C og C++ : vi formoder at programmøren ved hvad han laver og returnerer true

Rust : vi informerer lige udvikleren om at der er noget mistænkeligt her

B) unsigned suktraktion der giver negativt resultat

C og C++ : per standard så laver vi udregninger på unsigned i modulus, så med 32 bit unsigned så giver 0U-1 altså 4294967295, og det er ikke vores skyld hvis programmøren ikke har læst C standarden og ved det

Rust : Houston we have a problem
Gravatar #5 - larsp
2. maj 2020 17:52
arne_v (4) skrev:
Rust : Houston we have a problem

Hvad med scenariet hvor man beregner differencen mellem to timer counts, der kan løbe over. F.eks. med en 8 bit counter: A = 50, B = 60, differencen er B - A = 10, nemt. Næste eksempel: A = 250, B = 4. Nu giver B - A reelt et negativt resultat, men det forventede 10 kommer alligevel ud i C (hvis ellers A og B er uint8_t).

Mon rust vil brokke sig over sådan et nummer?
Gravatar #6 - arne_v
2. maj 2020 19:05
#5

Ja.
Gravatar #7 - arne_v
2. maj 2020 19:30
#6

Det her panikker:


fn main() {
let a:u8 = 250;
let b:u8 = 4;
let c = b - a;
println!("{}", c);
}


Det her virker:


use std::num::Wrapping;

fn main() {
let a:u8 = 250;
let b:u8 = 4;
let c = Wrapping(b) - Wrapping(a);
println!("{}", c);
}


Og det er vel fair nok. Den første kode kunne være en fejl. I den anden kode er det ret klart at man ønsker wrap.
Gravatar #8 - larsp
3. maj 2020 04:58
#7 Blæret! Jo mere "skåret ud i pap" kode er, jo bedre.

... tager for givet at assembler output i sidste eksempel kun er en subtract og ikke har overhead pga. Wrapping(..) ?

... hvis den panikker i første eksempel, så er der jo et runtime overflow check. Reelt bør koden med wrapping ende med færre instruktioner ?
Gravatar #9 - arne_v
3. maj 2020 14:20
#8

Hvordan de to versioner udføres må afhænge af CPU arkitektur.

Men på x86-64 (og formentligt mange andre) vil substraction instruktion sætte et flag som koden så kan teste på. Så overhead vil være et test på et flag.
Gravatar #10 - arne_v
3. maj 2020 14:23
#8

Bemærk at muligheden for integer overflow check ikke er unik for Rust.

C# checker ikke som default. Men du kan enable det som en compiler option for hele koden eller for en lille del af af koden med:

checked
{
...
}
Gravatar #11 - arne_v
3. maj 2020 16:14
#10

Og Delphi/FPC vil også fange den hvis man bruger {$R+} (ikke {$Q+} som eller virker mere oplagt).
Gå til top

Opret dig som bruger i dag

Det er gratis, og du binder dig ikke til noget.

Når du er oprettet som bruger, får du adgang til en lang række af sidens andre muligheder, såsom at udforme siden efter eget ønske og deltage i diskussionerne.

Opret Bruger Login