Flexible Input Parameters: From, AsRef

Flexible Input Parameters: From, AsRef

In this article, I’ll be covering two built-in traits that make your life in Rust easier:

  • AsRef
  • From

AsRef

Firstly, AsRef<T> is to specify the parameter as “anything that you can borrow type T from”. Take the following example:

fn take_str(st:String){
    println!("{}",st);
}
fn take_str_reference(st:&String){
    println!("{}",st);
}
fn take_str_literal(st:&str){
    println!("{}",st);
}        

Each takes a different type, String, &String, &str, respectively. When you look at the use case of the function, we don’t actually need full ownership of value. So the common denominator among them is we just need to borrow the value. The problem is, Rust allows putting input, the type of which is stated as specified in the function signature. Let’s look at the following example.

take_str("string".to_string()); // Ok
take_str_reference("string".to_string()); //Error!
take_str_literal("string".to_string())// Error!

take_str(&"string".to_string()); // Error
take_str_reference(&"string".to_string()); //OK
take_str_literal(&"string".to_string())// Error!

take_str("string"); // Error!
take_str_reference("string"); // Error!
take_str_literal("string")// Ok        

So, how can we impart some flexibility to the function? That’s what AsMut is for!

We change the function signature from specific to general, AsMut<str>.

fn take_str(st:impl AsRef<str> + std::fmt::Display){
    println!("{}",st.as_ref());
}        

Note that we put one more trait bound, std::fmt::Display to enable printing. This time, when you pass any string variants, String, &String, &str, Rust compiler is okay with them.

Wait, then, how can you get &str from String? It deserves its own writing but simply put, there is an interplay between AsRef and Deref.

From

Well, in a way, the use of From is somewhat similar to AsRef in that it enables converting a value from one to the other. The difference is that From and its blanket implementation, Into is used when you want to take ownership of the parameter. Let’s how it is used when you implement NewType Pattern.


#[derive(Debug)
struct VecWrapper<T>(Vec<T>); //new type pattern


impl<T> From<VecWrapper<T>> for Vec<T> {
		// But still, you want this to be treated as Vec of type T.
		// When it is passed as argument
? ? fn from(w:VecWrapper<T>)-> Vec<T>{?
? ? ? ? w.0
? ? }
}


fn function_taking_vec<T: std::fmt::Debug>(arr : impl Into<Vec<T>>){
? ? println!("{:?}",arr.into()); // into() is applied.
}


fn main(){
? ? let vc = VecWrapper(vec!["Migo".to_string()]);
? ? function_taking_vec(vc); // you simply pass VecWrapper, not Vec?
}]        

要查看或添加评论,请登录

Migo Lee的更多文章

  • Redis as distributed system

    Redis as distributed system

    Transaction handling with Multi Transactions are used to perfrom operations across multiple types or dataset. They're…

  • Raft - idempotency

    Raft - idempotency

    What would happen if the leader fails before they returns response to a client? The client may retry its request. But…

  • Raft - commitIndex and lastApplied

    Raft - commitIndex and lastApplied

    Read this post first if you haven't already. Changes in Raft Now, we learned that in Raft we expect two different…

  • Raft Leader Election and up-to-date leader guarantee

    Raft Leader Election and up-to-date leader guarantee

    Read this if you haven't already. Why Leader Election? In Raft, every write operation comes to the leader first.

  • Raft Replication

    Raft Replication

    Periodic heartbeat The leader sends periodic heartbeat messages approximately every 300–500 milliseconds. Each…

  • Case for layered architecture over hexagonal architecture

    Case for layered architecture over hexagonal architecture

    Why hexagonal in most of web applications? When building applications for web services, we tend to think less about…

  • Making Back Reference Using Weak Reference

    Making Back Reference Using Weak Reference

    Ownership - What’s the owner? This may sound weird but really, in Rust, when you declare ‘variable’ what it means is…

  • Retry Logic By Returning Consumed Argument On Error(And Never Type)

    Retry Logic By Returning Consumed Argument On Error(And Never Type)

    In Rust, a function may consume an argument like the following function: pub fn send(connection_uri: a…

  • Changing Enum In Place

    Changing Enum In Place

    When dealing with Enum, you may find it difficult to change values because of the borrow checking system in Rust…

  • Default trait

    Default trait

    In Rust, you cannot abstract away the implementation of a new() method which is just a convention for constructors in…

社区洞察

其他会员也浏览了