Cookies op Tweakers

Tweakers maakt gebruik van cookies, onder andere om de website te analyseren, het gebruiksgemak te vergroten en advertenties te tonen. Door gebruik te maken van deze website, of door op 'Ga verder' te klikken, geef je toestemming voor het gebruik van cookies. Wil je meer informatie over cookies en hoe ze worden gebruikt, bekijk dan ons cookiebeleid.

Meer informatie

Software-update: Rust 1.35.0

Rust is een programmeertaal bedacht door Graydon Hoare en oorspronkelijk ontwikkeld door Mozilla. Het is deels geïnspireerd op de programmeertaal C, maar kent syntactische en semantische verschillen. Het focust op veiligheid en beoogt moderne computersystemen efficiënter te benutten. Het wordt ingezet door onder ander Cloudflare, OVH, Mozilla, Deliveroo, Coursera, AppSignal en Threema. Versie 1.35.0 is onlangs uitgebracht met de volgende aankondiging:

Announcing Rust 1.35.0

The Rust team is happy to announce a new version of Rust, 1.35.0. Rust is a programming language that is empowering everyone to build reliable and efficient software. If you have a previous version of Rust installed via rustup, getting Rust 1.35.0 is as easy as:
$ rustup update stable
If you don't have it already, you can get rustup from the appropriate page on our website, and check out the detailed release notes for 1.35.0 on GitHub.

What's in 1.35.0 stable

The highlight of this release is the implementation of the FnOnce, FnMut, and Fn closure traits for Box<dyn FnOnce>, Box<dyn FnMut>, and Box<dyn Fn> respectively. Additionally, closures may now be coerced to unsafe function pointers. The dbg! macro introduced in Rust 1.32.0 can now also be called without arguments. Moreover, there were a number of standard library stabilizations. Read on for a few highlights, or see the detailed release notes for additional information.

Fn* closure traits implemented for Box<dyn Fn*>
In Rust 1.35.0, the FnOnce, FnMut, and the Fn traits are now implemented for Box<dyn FnOnce>, Box<dyn FnMut>, and Box<dyn Fn> respectively. Previously, if you wanted to call the function stored in a boxed closure, you had to use FnBox. This was because instances of Box<dyn FnOnce> and friends did not implement the respective Fn* traits. This also meant that it was not possible to pass boxed functions to code expecting an implementor of a Fn trait, and you had to create temporary closures to pass them down. This was ultimately due to a limitation in the compiler's ability to reason about such implementations, which has since been fixed with the introduction of unsized locals. With this release, you can now use boxed functions in places that expect items implementing a function trait.

The following code now works:
fn foo(x: Box<dyn Fn(u8) -> u8>) -> Vec<u8> {
vec![1, 2, 3, 4].into_iter().map(x).collect()
}


Furthermore, you can now directly call Box<dyn FnOnce> objects:
fn foo(x: Box<dyn FnOnce()>) {
x()
}


Coercing closures to unsafe fn pointers
Since Rust 1.19.0, it has been possible to coerce closures that do not capture from their environment into function pointers. For example, you may write:
fn twice(x: u8, f: fn(u8) -> u8) -> u8 {
f(f(x))
}

fn main() {
assert_eq!(42, twice(0, |x| x + 21));
}


This has however not extended to unsafe function pointers. With this release of Rust, you may now do so. For example:
/// The safety invariants are those of the `unsafe fn` pointer passed.
unsafe fn call_unsafe_fn_ptr(f: unsafe fn()) {
f()
}

fn main() {
// SAFETY: There are no invariants.
// The closure is statically prevented from doing unsafe things.
unsafe {
call_unsafe_fn_ptr(|| {
dbg!();
});
}
}


Calling dbg!() with no argument
For the benefit of all the occasional and frequent "print debuggers" out there, Rust 1.32.0 saw the release of the dbg! macro. To recap, the macro allows you to quickly inspect the value of some expression with context. For example, when running:
fn main() {
let mut x = 0;

if dbg!(x == 1) {
x += 1;
}

dbg!(x);
}


...you would see:
[src/main.rs:4] x == 1 = false
[src/main.rs:8] x = 0


As seen in the previous section, where the higher order function call_unsafe_fn_ptr is called, you may now also call dbg! without passing any arguments. This is useful when tracing what branches your application takes. For example, with:
fn main() {
let condition = true;

if condition {
dbg!();
}
}


...you would see:
src/main.rs:5]

Library stabilizations
In 1.35.0, a number of APIs have become stable. In addition, some implementations were added and other changes occured as well. See the detailed release notes for more details.

Copy the sign of a floating point number onto another
With this release, new methods copysign have been added to the floating point primitive types f32 and f64:
  • f32::copysign
  • f64::copysign
As the name suggests, you can use these to copy the sign of one number onto another. For example:
fn main() {
assert_eq!(3.5_f32.copysign(-0.42), -3.5);
}


Check whether a Range contains a value
Rust 1.35.0 contains a few freshly minted methods on the Range types:
  • Range::contains
  • RangeFrom::contains
  • RangeTo::contains
  • RangeInclusive::contains
  • RangeToInclusive::contains
With these, you can easily check whether a given value exists in a range. For example, you may write:
fn main() {
if (0..=10).contains(&5) {
println!("Five is included in zero to ten.");
}
}


Map and split a borrowed RefCell value in two
With Rust 1.35.0, you can now map and split the borrowed value of a RefCell into multiple borrows for different components of the borrowed data:
  • Ref::map_split
  • RefMut::map_split
Replace the value of a RefCell through a closure
This release introduces a convenience method replace_with on RefCell:
  • RefCell::replace_with
With it, you can more ergonomically map and replace the current value of the cell and get back the old value as a result.

Hash a pointer or reference by address, not value
In this release, we have introduced:
  • ptr::hash
This function takes a raw pointer and hashes it. Using ptr::hash, you can avoid hashing the pointed-to value of a reference and instead hash the address.

Copy the contents of an Option<&T>
From the very beginning with Rust 1.0.0, the methods Option::cloned for Option<&T> and Option<&mut T> have allowed you to clone the contents in case of Some(_). However, cloning can sometimes be an expensive operation and the methods opt.cloned() provided no hints to that effect.

With this release of Rust, we introduced:
  • Option::copied for both Option<&T> and Option<&mut T>
The functionality of opt.copied() is the same as for opt.cloned(). However, calling the method requires that T: Copy. Using this method, you can make sure that code stops compiling should T no longer implements Copy.

Changes in Clippy
In this release of Rust, Clippy (a collection of lints to catch common mistakes and improve your Rust code) added a new lint drop_bounds. This lint triggers when you add a bound T: Drop to a generic function. For example:
fn foo<T: Drop>(x: T) {}
Having a bound T: Drop is almost always a mistake as it excludes types, such as u8, which have trivial drop-glues. Moreover, T: Drop does not account for types like String not having interesting destructor behavior directly but rather as a result of embedding types, such as Vec<u8>, that do.

In addition to drop_bounds, this release of Clippy split the lintredundant_closure into redundant_closure and redundant_closure_for_method_calls. See the detailed release notes for Clippy for more details.

Changes in Cargo
See the detailed release notes for Cargo for more details.

Contributors to 1.35.0
Many people came together to create Rust 1.35.0. We couldn't have done it without all of you. Thanks!
Versienummer 1.35.0
Releasestatus Final
Website The Rust Programming Language Blog
Download https://www.rust-lang.org/install.html
Licentietype Voorwaarden (GNU/BSD/etc.)

Door Japke Rosink

Meukposter

Update-historie

Reacties (6)

Wijzig sortering
Mooie taal. Vooral het concept Ownership is erg mooi maar in het begin wel wennen.

Bij Java kun je met referenties strooien alsof het niks kost (maar dat doet het wel, want de garbage collector heeft er zijn handen vol aan). En daardoor krijg je ook van die lelijke oplossingen waarbij return values dmv aliasing worden teruggegeven. Bij Rust moet je veel beter nadenken over dit soort dingen en het dwingt je netter te programmeren. Wat zeker in grotere projecten erg fijn is en de kwaliteit ten goede zal komen (naast goede code reviews uiteraard).
Wat ze ook mooi hebben opgelost is dat je geen null pointer references meer kan gebruiken. Je wordt gedwongen je variabelen te declareren. Als iets optioneel moet zijn, kan je hiervoor een Option gebruiken, en dien je de wat-als-die-leeg-is conditie altijd af te handelen als je die gebruikt. Zo lossen ze het probleem van null pointer exceptions compile-time op. Volgens mij deed Scala dit ook alleen dat weet ik niet zeker meer.

Ownership is wel een hoofdbreker. Ik heb het boek gekocht en doorgenomen maar dat is inmiddels alweer een jaar geleden. Volgens mij kun je er wel goed in worden als je Rust vaak doet. Volgens mij is het ook bedoeld om de problemen die in C++ vaak voor te komen qua memory magement op te lossen, zonder dus de overhead van een garbage collector te hebben, en daarmee de snelheid van een low-level taal te behouden.
Nog indrukwekkender vind ik dat ze ook garanderen dat een lijst of ander object waar over geitereerd wordt niet gewijzigd kan worden. In Java kan dat een ConcurrentModificationException geven (of niet, afhankelijk van of Java er zin in heeft om je op je bug te wijzen die dag) en in C++ is dat bijna altijd een crash / security issue.

In Rust is het gewoon een compile-time error. Nice.

[Reactie gewijzigd door enzozus op 5 juni 2019 09:36]

Mee eens. Het dwingt je meer na te denken over het gebruik van het geheugen, en wanneer je iets daarin mag wijzigen of alleen lezen. Vooral dat dit eenvoudiger parallel te programmeren moet zijn maakt het een goede taal voor de toekomst. De leercurve is steil, "fighting the borrow checker" wordt het soms genoemd, maar ik vindt het de moeite waard. Om te leren raad ik aan op kleine opdrachtjes te maken, en die van anderen daarna in te zien, zie bijvoorbeeld:
https://exercism.io/tracks/rust
Zelf niet geprobeerd, maar zelfde idee:
https://github.com/rust-lang/rustlings/
Je hoeft met Java die garbage collector niet zoveel werk te geven natuurlijk. Ook in Java kun je héél netjes programmeren. Maar het hoeft niet/is minder nodig/wordt minder aangemoedigd.

Het jammere is dat daardoor mensen het minder netjes doen. Het grote nadeel van toegankelijke programmeertalen.

Op dit item kan niet meer gereageerd worden.


Apple iPhone 11 Nintendo Switch Lite LG OLED C9 Google Pixel 4 FIFA 20 Samsung Galaxy S10 Sony PlayStation 5 Apple

'14 '15 '16 '17 2018

Tweakers vormt samen met Hardware Info, AutoTrack, Gaspedaal.nl, Nationale Vacaturebank, Intermediair en Independer DPG Online Services B.V.
Alle rechten voorbehouden © 1998 - 2019 Hosting door True