-
Notifications
You must be signed in to change notification settings - Fork 14
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Support for optional fields in structs #19
Comments
There is no support for the field wrapped in I think the support you need depends on how you string use parse_display::*;
#[derive(Display, FromStr)]
#[display("{x?},{y?}")]
struct Point {
x: Option<u32>,
y: Option<u32>,
}
let pt = Point {
x: None,
y: Some(10),
};
assert_eq!(pt.to_string(), ",10"); We might as well make it so that #[derive(Display, FromStr)]
#[display("{x}{y}")]
struct PointEx {
#[display("x={};", option)]
x: Option<u32>,
#[display("y={};", option)]
y: Option<u32>,
}
let pt = PointEx {
x: None,
y: Some(10),
};
assert_eq!(pt.to_string(), "y=10;"); |
I was thinking more of something like this: #[derive(Display)]
#[display("Got these: {a}{b}{c}")]
struct Whatever {
#[display("a={}")]
a: u32,
#[display(", b={}")]
b: Option<u32>,
#[display(", c={}")]
c: Option<u32>,
d: Option<String>,
}
let pt = Whatever {
a: 1,
b: None,
c: Some(7),
d: ".".to_string(),
};
assert_eq!(pt.to_string(), "Got these: a=1, c=7."); This way I would be able e.g. to surround the value stored in It would be nice if Having dedicated support for |
I also think it would be more convenient to be able to handle fields of type The reason for using use parse_display::*;
#[derive(Display)]
#[display("{err1} {err2}")]
struct Errs {
#[display("err1={:?}")]
err1: Option<std::io::ErrorKind>,
#[display("err2={:?}", option)]
err2: Option<std::io::ErrorKind>,
}
let e = Errs {
err1: Some(std::io::ErrorKind::AddrInUse),
err2: Some(std::io::ErrorKind::BrokenPipe),
};
assert_eq!(e.to_string(), "err1=Some(AddrInUse) err2=BrokenPipe"); However, since the values wrapped in |
From the example that you provided I can see that there is a potential issue with combining the reasonable defaults for use parse_display::*;
#[derive(Display)]
#[display("{a} {b}")]
struct Errs {
#[display("a={:?}")]
a: Option<u32>,
#[display("b={}")]
b: Option<u32>,
}
let e = Errs {
a: Some(1),
b: Some(2),
};
assert_eq!(e.to_string(), "a=Some(1) b=2"); I think that personally I would not bother about using Furthermore, I think that it would be nice to provide an option to specify an alternative text in case there is use parse_display::*;
#[derive(Display)]
#[display("{a} {b}")]
struct Errs {
#[display("a={}")]
a: Option<u32>,
#[display("b={}", alt="b=nil")]
b: Option<u32>,
}
let e = Errs {
a: Some(1),
b: None,
};
assert_eq!(e.to_string(), "a=1 b=nil"); Perhaps that would address some of your concerns. |
If we infer how to handle For example, suppose we allow method calls with a format string(#11). #[derive(Display)]
#[display("{path}")]
struct Log {
#[display("path={.display()}")]
path: Option<std::path::PathBuf>,
}
let p = Log {
path: Some(std::path::PathBuf::from("/")),
};
assert_eq!(p.to_string(), "path=/"); In the example above, the But unlike To make the specification easier to understand, I think it would be better to determine the default behavior based on whether the field type is
I think so too. I believe that the recommended way should be short code, and the unrecommended way should be long code. use parse_display::*;
#[derive(Display)]
#[display("{a} {b} {c}")]
struct Errs {
#[display("a={:?}", nowrap)]
a: Option<u32>,
#[display("b={:?}")]
b: Option<u32>,
#[display("c={}")]
c: Option<u32>,
}
let e = Errs {
a: Some(1),
b: Some(2),
c: Some(3),
};
assert_eq!(e.to_string(), "a=Some(1) b=2 c=3"); |
That example of yours looks fine to me and looks intuitively with the simple assumption that by default Personally I am always for convention over configuration and for having reasonable defaults. That said, although I understand your fears, I think that it is better to have a slightly more complex implementation of the macro rather than require the users to explicitly inform the macro that each field that uses So at this point I would assume that And the below simple example should be possible too, right? use parse_display::*;
#[derive(Display)]
#[display("{a:?} {b:?} {c}")]
struct Errs {
#[display(nowrap)]
a: Option<u32>,
b: Option<u32>,
c: Option<u32>,
}
let e = Errs {
a: Some(1),
b: Some(2),
c: Some(3),
};
assert_eq!(e.to_string(), "Some(1) 2 3"); Personally I am not convinced to the name |
I think so too. However, I believe that users will be confused if there are similar but different conventions and default values. use parse_display::Display;
#[derive(Display)]
#[display("{b:?}")]
struct X {
b: Option<u32>,
}
let x = X { b: Some(2) };
assert_eq!(x.to_string(), "2"); Looking at rust-lang/rust#90473, it seems that the Rust compiler's let b: Option<u32> = Some(2);
assert_eq!(format!("{b:?}"), "Some(2)"); Thus, it looks strange to have different results with similar code. So, I came up with the following specification.
With this specification, your example would be written as follows. use parse_display::*;
#[derive(Display)]
#[display("{a:?} {b?:?} {c}")]
struct Errs {
a: Option<u32>,
b: Option<u32>,
c: Option<u32>,
}
let e = Errs {
a: Some(1),
b: Some(2),
c: Some(3),
};
assert_eq!(e.to_string(), "Some(1) 2 3");
Indeed, you are right. I also thought about If there is a more fit word, I would like to use that one. It could be |
Although I agree with where you come from with your approach in regards to code predictability, I cannot find such an issue here, as in the example that I provided a field was clearly marked with How is use parse_display::*;
#[derive(Display)]
#[display("{a:?} {b:?} {c}")]
struct Errs {
#[display(nowrap)]
a: Option<u32>,
b: Option<u32>,
c: Option<u32>,
}
let e = Errs {
a: Some(1),
b: Some(2),
c: Some(3),
};
assert_eq!(e.to_string(), "Some(1) 2 3"); which actually typically would be replaced with use parse_display::*;
#[derive(Display)]
#[display("{a} {b} {c}")]
struct Errs {
#[display("{:?}", nowrap)]
a: Option<u32>,
b: Option<u32>,
c: Option<u32>,
}
let e = Errs {
a: Some(1),
b: Some(2),
c: Some(3),
};
assert_eq!(e.to_string(), "Some(1) 2 3"); less readable and more confusing than use parse_display::*;
#[derive(Display)]
#[display("{a:?} {b:?} {c}")]
struct Errs {
a: Option<u32>,
#[display("{?:?}"]
b: Option<u32>,
c: Option<u32>,
}
let e = Errs {
a: Some(1),
b: Some(2),
c: Some(3),
};
assert_eq!(e.to_string(), "Some(1) 2 3"); or some other strange things one could write? Having that said, I remain with my opinion that by default |
It is not field #[derive(Display)]
#[display("{b:?}")]
struct Errs {
b: Option<u32>,
}
let b: Option<u32> = Some(2);
let x = Errs { b };
assert_eq!(format!("{b:?}"), "Some(2)");
assert_eq!(Errs { b }.to_string(), "Some(2)"); The goal of the proposal in #19 (comment) is to make this happen, while still being able to write like the second code example in #19 (comment). This proposal assumes that the following codes are all equivalent. #[derive(Display)]
#[display("{a} {b} {c}")]
struct Errs {
#[display("{:?}", nowrap)]
a: Option<u32>,
#[display("{:?}")]
b: Option<u32>,
c: Option<u32>,
} #[derive(Display)]
#[display("{a} {b} {c}")]
struct Errs {
#[display("{:?}", nowrap)]
a: Option<u32>,
#[display("{:?}")]
b: Option<u32>,
#[display("{}")]
c: Option<u32>,
} #[derive(Display)]
#[display("{a} {b} {c}")]
struct Errs {
#[display("{:?}", nowrap)]
a: Option<u32>,
#[display("{?:?}", nowrap)]
b: Option<u32>,
#[display("{?}", nowrap)]
c: Option<u32>,
} #[derive(Display)]
#[display("{a:?} {b?:?} {c?}")]
struct Errs {
a: Option<u32>,
b: Option<u32>,
c: Option<u32>,
} let e = Errs {
a: Some(1),
b: Some(2),
c: Some(3),
};
assert_eq!(e.to_string(), "Some(1) 2 3"); It might be a good idea to not implement |
I am having a hard time trying to use this library for structs that have fields of types that are wrapped in
Option
. I feel like this enum is too omnipresent not to deserve some kind of dedicated support. Is it there and I am just mising some docs?The text was updated successfully, but these errors were encountered: