Method to wrap value in Ok - rust

I want to wrap value in Ok like this
12.ok()
Am I able to do this or I can only use Ok(12)?

I would strongly recommend against this. Result is a very well known type in the Rust ecosystem with a lot of conventions, idioms and patterns. This is decidedly not one of them and will be confusing for anyone who comes across it, especially because Result::ok already is a method. So this is doubly terrible.
Just because you can do something, doesn't mean you should.
That warning said, you could do this:
trait Okable<Err> {
fn ok(self) -> Result<Self, Err> where Self: Sized {
Ok(self)
}
}
impl<T, Err> Okable<Err> for T {}
fn main() {
let _x: Result<_, ()> = 12.ok();
}

Related

How can I communicate whether side effects have been successful or not?

With the Rust project I am working on I would like to keep the code as clean as I can but was having issues with side effects - more specifically how to communicate whether they have been successful or not. Assume we have this enum and struct (the struct may contain more members not relevant to my question):
enum Value{
Mutable(i32),
Constant(i32),
}
struct SomeStruct {
// --snip--
value: Value
}
I would like to have a function to change value:
impl SomeStruct {
fn change_value(&mut self, new_value: i32) {
match self.value {
Value::Mutable(_) => self.value = Value::Mutable(new_value),
Value::Constant(_) => (), /* meeeep! do not do this :( */
}
}
}
I am now unsure how to cleanly handle the case where value is Value::Constant.
From what I've learned in C or C++ you would just return a bool and return true when value was successfully changed or false when it wasn't. This does not feel satisfying as the function signature alone would not make it clear what the bool was for. Also, it would make it optional for the caller of change_value to just ignore the return value and not handle the case where the side effect did not actually happen. I could, of course, adjust the function name to something like try_changing_value but that feels more like a band-aid than actually fixing the issue.
The only alternative I know would be to approach it more "functionally":
fn change_value(some_struct: SomeStruct, new_value: i32) -> Option<SomeStruct> {
match self.value {
Value::Mutable(_) => {
let mut new_struct = /* copy other members */;
new_struct.value = Value::Mutable(new_value);
Some(new_struct)
},
Value::Constant(_) => None,
}
}
However, I imagine if SomeStruct is expensive to copy this is not very efficient. Is there another way to do this?
Finally, to give some more context as to how I got here: My actual code is about solving a sudoku and I modelled a sudoku's cell as either having a given (Value::Constant) value or a guessed (Value::Mutable) value. The "given" values are the once you get at the start of the puzzle and the "guessed" values are the once you fill in yourself. This means changing "given" values should not be allowed. If modelling it this way is the actual issue, I would love to hear your suggestions on how to do it differently!
The general pattern to indicate whether something was successful or not is to use Result:
struct CannotChangeValue;
impl SomeStruct {
fn change_value(&mut self, new_value: i32) -> Result<(), CannotChangeValue> {
match self.value {
Value::Mutable(_) => {
self.value = Value::Mutable(new_value);
Ok(())
}
Value::Constant(_) => Err(CannotChangeValue),
}
}
}
That way the caller can use the existing methods, syntax, and other patterns to decide how to deal with it. Like ignore it, log it, propagate it, do something else, etc. And the compiler will warn that the caller will need to do something with the result (even if that something is to explicitly ignore it).
If the API is designed to let callers determine exactly how to mutate the value, then you may want to return Option<&mut i32> instead to indicate: "I may or may not have a value that you can mutate, here it is." This also has a wealth of methods and tools available to handle it.
I think that Result fits your use-case better, but it just depends on the flexibility and level of abstraction that you're after.
For the sake of completeness with kmdreko's answer, this is the way you would implement a mut-ref-getter, which IMO is the simpler and more flexible approach:
enum Value {
Mutable(i32),
Constant(i32),
}
impl Value {
pub fn get_mut(&mut self) -> Option<&mut i32> {
match self {
Value::Mutable(ref mut v) => Some(v),
Value::Constant(_) => None,
}
}
}
Unlike the Result approach, this forces the caller to consider that setting the value may not be possible. (Granted, Result is a must_use type, so they'd get a warning if discarding it.)
You can write a proxy method on SomeStruct that forwards the invocation to this method:
impl SomeStruct {
pub fn get_mut_value(&mut self) -> Option<&mut i32> {
self.value.get_mut()
}
}

Is there any way to implement Into<&str> or From<T> for &str?

Was writing some code in Rust trying to define a CLI, using the (otherwise pretty great) crate clap, and run into a rather critical issue. Methods of App accept an Into<&'help str>, and i've been unable to find a way to implement this trait.
Indeed from what i understand, it is absolutely unimplementable:
struct JustWorkDamnIt {
string: String
}
impl From<JustWorkDamnIt> for &str {
fn from(arg: JustWorkDamnIt) -> Self {
return arg.string.as_str()
}
}
...which yields:
error[E0515]: cannot return value referencing local data `arg.string`
--> src/cmd/interactive.rs:25:16
|
25 | return arg.string.as_str()
| ----------^^^^^^^^^
| |
| returns a value referencing data owned by the current function
| `arg.string` is borrowed here
Interestingly enough, however, returning a literal compiles just fine (which i reckon is why clap doesn't mind using this trait). Presumably that's because the literal is compiled to some static region of memory and therefore isn't owned by the function:
impl From<JustWorkDamnIt> for &str {
fn from(arg: JustWorkDamnIt) -> Self {
return "literal"
}
}
But, i mean, surely there's a way to implement this trait and return dynamic strings? Maybe some clever use of Box<> or something, idk. I believe i've tried all the things i could think of.
And if there isn't a way, then this seems like a pretty glaring flaw for Rust - traits which can be declared and used in function headers, but cannot be actually implemented meaningfully (there's not much of a point in returning a literal). If this turns out to be the case i'll create an issue on the rust-lang repository for this flow, but first i wanted to sanity-check my findings here.
UPD: Thanks for the comments, made me think more in-depth about this issue.
The problem has to do with lifetimes, it seems. I apologize for not showing the entire code, i thought the snippets i shared would describe the problem sufficiently, but in hindsight it does make sense that the context would be important with Rust's lifetimes at play.
I did find a "solution" for this particular instance of the problem. Since the code in question will only run once per executable start, i can just Box::leak the &'static str and call it a day. Still, i would like to figure out if there's a more general solution which could be used for often-created dynamic strings.
impl Cmd for InteractiveCmd {
fn build_args_parser<'a, 'b>(&'b self, builder: App<'a>) -> App<'a> {
// leak() works here but i'm curious if there's a better way
let staticStr : &'static str = Box::leak(Box::from(format!("Interactive {} shell", APPNAME).as_str()));
let rv = builder
// pub fn about<S: Into<&'b str>>(mut self, about: S) -> Self
.about(staticStr)
.version("0.1");
return rv;
}
}
fn main() {
let interactive = InteractiveCmd::new();
let mut app = App::new(APPNAME)
.version(APPVER)
.author(AUTHORS)
.subcommand(interactive.build_args_parser(App::new("interactive")));
}
Currently i am faced with 2 points of confusion here:
Why is there no impl From<String> for &str? The compiler claims that one exists for impl From<String> for &mut str, and i'm not seeing the importance of mut here.
...and if there is a good reason to not impl From<String> for &str, would it make sense to somehow discourage the usage of Into<&str> in the public APIs of libraries?
Or maybe the issue is with my build_args_parser function and it's just not an option to offload the work to it as far as Rust is concerned?
Seems like you're trying to convert a String into a &'a str. You can do it like this:
use clap::App;
fn main() {
let s = format!("Interactive {} shell", "Testing");
let app = App::new("Testing")
.about(&*s); // or `.about(s.as_str());` it's the same
}
Here's the signature of the function that we want to call:
pub fn about<S: Into<&'b str>>(self, about: S) -> Self
So the about parameter must implement trait Into<&'b str>. According to std::convert::Into, we know that &'b str does implement trait Into<&'b str>. So now we just need a way to convert String into &'b str. The std::string::String tell us that there are two ways: use either s.as_str() or &*s.

How to fix unused lifetime?

While trying to create a simple webserver in Rocket, I ran into the problem that I wanted to redirect or send html data, depending on certain conditions as follows:
#[post("/test/<some_string>")]
// This doesn't work Redirect and Html are different types.
pub fn test(some_string: String) -> _ {
if validate(some_string) {
Redirect("/dashboard")
} else {
content::Html("<h1>Hello World</h1>")
}
}
This clearly doesn't work as Html and Redirect are clearly different types. Then I tried to create an enum with different responder types so I could use different responder types in the same function, this resulted in the following code:
pub enum TwoResponders<'r, T: Responder<'r>, V: Responder<'r>> {
ResponderOne(T),
ResponderTwo(V),
}
impl<'r, T: Responder<'r>, V: Responder<'r>> Responder<'r> for TwoResponders<'r, T, V> {
fn respond_to(self, request: &Request) -> response::Result<'r> {
match self {
TwoResponders::ResponderOne(responder) => responder.respond_to(request),
TwoResponders::ResponderTwo(responder) => responder.respond_to(request),
}
}
}
This however, didn't work either, because now the Rust compiler complains that the lifetime 'r is unused in the struct TwoResponders. I would think this is not the case as it is used in defining the traits T and V need to have, the Rust compiler thinks differently however, and it has the final word as always.
I was thinking of adding a PhantomData however that seemed like an incredibly ugly solution for something which shouldn't be this difficult to my knowledge.
Is there a better way to fix this?
In cases like this, where the generic type bounds require some otherwise unused type parameter or lifetime and adding PhantomData makes things unnecessarily ugly, I find it cleanest to just remove the type bounds entirely from the type itself, and only keep them on the impl block:
pub enum TwoResponders<T, V> {
ResponderOne(T),
ResponderTwo(V),
}
impl<'r, T: Responder<'r>, V: Responder<'r>> Responder<'r> for TwoResponders<T, V> {
fn respond_to(self, request: &Request) -> response::Result<'r> {
match self {
TwoResponders::ResponderOne(responder) => responder.respond_to(request),
TwoResponders::ResponderTwo(responder) => responder.respond_to(request),
}
}
}

How to idiomatically convert from Option<T> to Result<T, ()>?

I'm a Rust newbie! What's the best way to convert from an Option<T> to a Result<T, ()>?
The TryFrom trait seems prevalent and returns a Result. The popular num_traits' NumCast has many conversions but they all return an Option<T>. Similarly, as do the NonZero* constructors such as NonZeroI32 in the Rust Standard Library. I then noticed that NumCast implements a from() that returns an Option<T> so I was thinking that maybe it had a non-standard way of doing things in general but then I saw the NonZero* implementations and questioned that idea.
Regardless, converting from Options to Results seem frequent and I haven't found a neat way to do yet. E.g.:
/// Add common conversion from an i32 to a non-zero i32.
impl TryFrom<Container<i32>> for Container<NonZeroI32> {
type Error = ();
fn try_from(container: Container<i32>) -> Result<Self, ()> {
// NonZeroI32::new() returns an Option not a Result. Try a helper.
Ok(Self(option_to_result(NonZeroI32::new(container.0))?))
}
}
/// Helper function to convert from an Option to a Result (both types are
/// foreign and so is From).
fn option_to_result<T>(option: Option<T>) -> Result<T, ()> {
if let Some(some) = option {
Ok(some)
} else {
Err(())
}
}
/// Add another common conversion from an i32 to an i16.
impl TryFrom<Container<i32>> for Container<i16> {
type Error = ();
fn try_from(container: Container<i32>) -> Result<Self, ()> {
// NumCast::from() also returns an Option not a Result. Try map_or() instead
// of the helper.
Ok(Self(NumCast::from(container.0).map_or(Err(()), |x| Ok(x))?))
}
}
(Above examples in the Rust Playground.)
These NumCast, NonZero*, and TryFrom conversions seem common enough but my approach feels clumsy as though I'm pitting the Option and Result types against each other. I struggle with these conversions and also miss the fundamental point of the Option type given Result<T,()> feels similar.
So, what's the idiomatic way to convert an Option<T> to Result<T,()> in Rust 2018?
Option has the ok_or method, usable for exactly this (well, for more wide case, in fact, but your request fits here too):
fn option_to_result<T>(option: Option<T>) -> Result<T, ()> {
option.ok_or(())
}
Modified playground

Is it idiomatic to use `impl<T> From<T> for Option<T>` in argument position?

This trait is implemented since 1.12.0:
impl<T> From<T> for Option<T> {
fn from(val: T) -> Option<T> {
Some(val)
}
}
How idiomatic is this as an argument? Consider this example:
fn do_things(parameters: &Foo, optional_argument: impl Into<Option<Duration>>) {
let optional_argument = optional_argument.into();
// use it...
}
If you see the documentation, it's (more or less) clear (if you know, that this trait is implemented). But if you see the code, you may be confused:
do_things(params, Duration::from_millis(100));
Is this fine to use or should it be avoided?
This pattern is uncommon, but reasonably easy to understand. If it's convenient in the context of your library's usage, it should be OK.
I think it's more common to have do_stuff and do_stuff_with_timeout functions.

Resources