|
|
Subscribe / Log in / New account

Ushering out strlcpy()

Ushering out strlcpy()

Posted Aug 25, 2022 20:31 UTC (Thu) by tialaramex (subscriber, #21167)
In reply to: Ushering out strlcpy() by NYKevin
Parent article: Ushering out strlcpy()

> it's a method rather than a free function

This won't be obvious to non-Rust people, and might not even be immediately obvious to new Rust programmers, but, in a sense all Rust's functions are/ can be written as free functions.

Here's some idiomatic Rust using a method call:

let mut news = "Linux Weekly News".to_owned();
news.replace_range(..5, "FreeBSD");

But while it isn't idiomatic in this case, you could also just write:

String::replace_range(&mut news, ..5, "FreeBSD");

As well as moving news to be the first parameter, we also need to write &mut to show that we want to pass the mutable reference, not move news itself into the replace_range function as a parameter. The method call sugar does that work for us by examining the signature of the String::replace_range function and seeing how the self parameter is used.

It really is just sugar, the code emitted will be identical (modulo perturbing an optimiser somewhere).

This is also how Rust resolves ambiguities. If Goose implements both AirlinePassenger and Bird but both traits define a fly() method, that's no problem in Rust, I can write:

if goose.is_wealthy() { AirlinePassenger::fly(&goose); } else { Bird::fly(&goose); }

In contexts where the code knows about Bird but not AirlinePassenger, goose.fly() is unambiguous and does what you expect, and likewise vice versa.


to post comments

Ushering out strlcpy()

Posted Aug 26, 2022 7:56 UTC (Fri) by nyanpasu64 (guest, #135579) [Link]

I thought that method calls on &[mut] dyn T variables (trait object references, fat pointers) couldn't be rewritten as free function calls, since you're calling a function pointer stored behind the fat pointer itself, and I thought free function calls are statically resolved. But it turns out that `Trait::func(obj)` can actually invoke a dynamic dispatch, if `obj` is a trait object fat pointer.

Ushering out strlcpy()

Posted Aug 28, 2022 23:45 UTC (Sun) by KJ7RRV (subscriber, #153595) [Link] (2 responses)

Is this the Rust equivalent of str.strip(" string with padding ") as opposed to (" string with padding ").strip() in Python?

Ushering out strlcpy()

Posted Aug 30, 2022 17:10 UTC (Tue) by tialaramex (subscriber, #21167) [Link] (1 responses)

I have used Python but I'm definitely not an expert so the rest of this may be wrong, especially in subtle ways.

It's very similar, however whereas self in Python is just a convention, self in Rust is a keyword, using it signals that you mean for this function to be a method, and so the type is implied. Not all functions implemented for a type in Rust have to be methods. Consider these two functions in the implementation of Goose:

fn is_wealthy(&self) -> bool { self.net_worth > 1000 }

fn is_healthy(goose: &Self) -> bool { self.hit_points > 90 }

The is_wealthy function can be used as a method, the self keyword means if I have a Goose named jimmy I can write:

if jimmy.is_wealthy() { println!("Swimming in money"); } else { println!("Aww, poor Jimmy"); }
OR
if Goose::is_wealthy(&jimmy) { println!("Swimming in money"); } else { println!("Aww, poor Jimmy"); }

But the is_healthy function is not a method, it's only an associated function. That capitalized word "Self" is also a keyword, but it just means "my type" and so we could have written Goose instead. So I always need to write:

if Goose::is_healthy(&jimmy) { println!("Feeling good"); } else { println!("Jimmy needs a goose doctor"); }

I believe this distinction does not exist in Python. The reason it is used in Rust is that sometimes a type exists mostly as a "pass through" for some other type, and so by having only associated functions instead of methods it is hidden from accidental method invocations. For example Rc and Arc are smart pointers offering reference counting, but they sport associated functions not methods, so that you need to say e.g. Rc::downgrade(&thing) and thus if thing.downgrade() already means something else the reference counted type doesn't get in your way.

Ushering out strlcpy()

Posted Aug 30, 2022 17:12 UTC (Tue) by tialaramex (subscriber, #21167) [Link]

Gah, I should always check these compile before hitting submit.

fn is_healthy(goose: &Self) -> bool { goose.hit_points > 90 }

There is no "self" parameter on is_healthy because it isn't a method, and so the version I wrote above can't work since it refers to a self variable which doesn't exist.


Copyright © 2025, Eklektix, Inc.
Comments and public postings are copyrighted by their creators.
Linux is a registered trademark of Linus Torvalds