-
Notifications
You must be signed in to change notification settings - Fork 13k
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
Tracking Issue for bool_to_option #80967
Comments
I personally like Otherwise, |
I'm in favor of deprecating
|
That wouldn't necessarily have the same semantics. |
So instead of |
The following two versions are not strictly identical indeed: #![feature(bool_to_option)]
fn create_value() -> u32 {
println!("creating");
16
}
fn main() {
let cond = false;
println!("{:?}", cond.then_some(create_value()));
println!("----");
println!("{:?}", cond.then(|| create_value())); // or cond.then(create_value)
} prints
So it's not just a matter of syntax. Not sure whether this particular behaviour of |
With
how do I rewrite this example using
gives an error that a closure should return either a I can think of an extracting the closure expression into a variable:
But in my opinion the first example with |
If you use fn f() -> Option<usize> {
let x: Vec<u32> = Some(vec![])?;
true.then(|| x.len())
} |
If you insist on eagerly evaluating the value inside the option, you can also make use of #![feature(bool_to_option)]
fn create_value() -> u32 {
println!("creating");
16
}
fn main() {
let cond = false;
println!("{:?}", cond.then_some(create_value()));
println!("----");
println!("{:?}", Some(create_value()).filter(|_| cond));
} fn f() -> Option<usize> {
let x: Option<Vec<u32>> = Some(vec![]);
Some(x?.len()).filter(|_| true)
} |
@slerpyyy Well, this does work, but it becomes really hard to read IMO. I would argue that this being the only workaround to "eager evaluation" would be a good reason to actually include Note that I'm still unsure whether "eager evaluation" is useful anyway, has anyone ever needed this? To summarize my understanding of the advantage of
|
I prefer to use |
You're right, this is a function that users want and there is no reason not to add it to the std. I'm still annoyed that after more than a year of discussion about what we want to call these two functions in the original issue, we went with the only combination of names I actively dislike. Yet, I see how having this function with a somewhat unfortunate name is still better than not having this functionality at all. |
With regards to naming, I personally think
|
I think it's fair to say that few people are happy with the names as they stand, but there was no general consensus, and we'd rather have the feature than not :) |
I would have preferred (written as value / closure)
but we went with
|
|
@SoniEx2 How does |
nah it's just a reference to that ship having sailed ^^ |
(side note: |
(I also proposed the names |
I usually prefer starting a statement with the variable which is being assigned, checked, or iterated on. This can increase readability, once you get used to it. I have to say that I even prefer Therefore, the following combination of methods for
(disclaimer: I have my roots in Smalltalk, where |
@thedrow that wouldn't be unambiguous in all cases. What if you wanted to obtain |
If I understand what you said correctly, you were suggesting that |
|
This requires replacing pub fn then<T, F>(self, f: F) -> Option<T> where
F: FnOnce() -> T, with pub fn then<T, R>(self, f: R) -> Option<T> where
R: ResolveTo<T>, But with impls of This is a breaking change and also in my opinion undesirable (explicit typing is often easier to work with). I honestly am in favour of |
It would be possible with overlapping traits. |
@SoniEx2 if you are referring to https://rust-lang.github.io/rfcs/1268-allow-overlapping-impls-on-marker-traits.html, this is not applicable since the pub trait ResolveTo<T> {
fn resolve(self) -> T;
} |
nah, we mean our rejected proposal for marking traits as overlapping, and having both preferred and overlapping impls of those traits. you can then explicitly choose impls in the overlapping case, or default to the preferred impls only. you'd write // uhh not sure how you'd make an overlapping trait "sealed".
pub overlapping trait ResolveTo<T> {
fn resolve(self) -> T;
}
overlapping impl<T> ResolveTo<T> for T {
fn resolve(self) -> T {
self
}
}
impl<T, F> ResolveTo<T> for F where F: FnOnce() -> T {
fn resolve(self) -> T {
self()
}
} and then calls would be one of these: b.then(|| bar): Option<Bar>;
b.then::<fn() -> Bar>(|| bar): Option<Bar>;
b.then::<_: (overlapping impl<T> ResolveTo<T> for T)>(|| bar): Option<fn() -> Bar>;
b.then::<_: (overlapping impl<T> ResolveTo<T> for T)>(bar): Option<Bar>; // with future possibility of not requiring the <_: (overlapping impl)> syntax if Bar just so happens to not implement FnOnce() -> T. |
so python has this convention of (we know this is mostly silly but, eh, might as well put it out there y'know?) |
FWIW, I discovered this method today because I did I guess it's too late to rename the methods. I can't think of a name which doesn't involve renaming |
The final comment period, with a disposition to merge, as per the review above, is now complete. As the automated representative of the governance process, I would like to thank the author for their work and everyone else who contributed. This will be merged soon. |
So, I ran into this issue when refactoring some code from the rust book as a learning exercise: pub fn new(value: i32) -> Guess {
if value >= 1 && value <= 100 {
Guess { value }
} else {
panic!("Guess value must be between 1 and 100, but received {}", value)
}
}
pub fn new(value: i32) -> Guess {
match value >= 1 && value <= 100 {
true => Guess { value },
false => panic!("Guess value must be between 1 and 100, but received {}", value),
}
pub fn new(value: i32) -> Guess {
(value >= 1 && value <= 100).then_some(Guess { value }).expect("Guess value must be between 1 and 100.")
} Only downside was expect doesn't accept multiple arguments for the panic! macro. (yes, I know I can use format!().as_str()) |
We'd like to suggest renaming // previously
if x {
y()
} else {
y();
z
}
// now
x.then_some({
y() // NOTE: y() eagerly evaluated! do not use .then()!
}).unwrap_or(z) Even if it's not named to be similar to (This is actually real code! It's really useful for filtering return values of callbacks!) Well, the real code looks more like this: let suppress_eat = ...;
...
(!suppress_eat).then_some({
cb(&mut ph, word)
}).unwrap_or(EAT_NONE) so uh... maybe |
…=m-ou-se Stabilize `bool::then_some` FCP completed in rust-lang#80967
Looks like this got stabilized in #96628, can that be added to the OP under "Stabilization PR"? |
Stabilize `bool::then_some` FCP completed in rust-lang/rust#80967
…e library feature 'bool_to_option I have found a compile error in my windows serve 2020. This is it's details: error[E0658]: use of unstable library feature 'bool_to_option' --> common\src\refcount.rs:47:63 | 47 | .fetch_update(AcqRel, Acquire, |prev| (prev != 0).then_some(prev + 1)) | ^^^^^^^^^ | = note: see issue #80967 <rust-lang/rust#80967> for more information For more information about this error, try `rustc --explain E0658`. error: could not compile `rustpython-common` due to previous error warning: build failed, waiting for other jobs to finish... error: build failed
Feature gate:
#![feature(bool_to_option)]
This is a tracking issue for
bool::then_some
, a value-receiver version ofbool::then
, split off from #64260.Public API
Steps / History
bool
toOption<T>
#64255bool::then_some
#96628Unresolved Questions
bool::then
. There was discussion in about this Tracking issue forbool::then_some
#64260The text was updated successfully, but these errors were encountered: