{"action":"created","issue":{"url":"https://api.github.com/repos/rust-lang/rfcs/issues/1801","repository_url":"https://api.github.com/repos/rust-lang/rfcs","labels_url":"https://api.github.com/repos/rust-lang/rfcs/issues/1801/labels{/name}","comments_url":"https://api.github.com/repos/rust-lang/rfcs/issues/1801/comments","events_url":"https://api.github.com/repos/rust-lang/rfcs/issues/1801/events","html_url":"https://github.com/rust-lang/rfcs/issues/1801","id":191816865,"number":1801,"title":"Add `find_map` to the Iterator trait","user":{"login":"Cobrand","id":8882127,"avatar_url":"https://avatars.githubusercontent.com/u/8882127?v=3","gravatar_id":"","url":"https://api.github.com/users/Cobrand","html_url":"https://github.com/Cobrand","followers_url":"https://api.github.com/users/Cobrand/followers","following_url":"https://api.github.com/users/Cobrand/following{/other_user}","gists_url":"https://api.github.com/users/Cobrand/gists{/gist_id}","starred_url":"https://api.github.com/users/Cobrand/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/Cobrand/subscriptions","organizations_url":"https://api.github.com/users/Cobrand/orgs","repos_url":"https://api.github.com/users/Cobrand/repos","events_url":"https://api.github.com/users/Cobrand/events{/privacy}","received_events_url":"https://api.github.com/users/Cobrand/received_events","type":"User","site_admin":false},"labels":[{"id":211667901,"url":"https://api.github.com/repos/rust-lang/rfcs/labels/T-libs","name":"T-libs","color":"bfd4f2","default":false}],"state":"open","locked":false,"assignee":null,"assignees":[],"milestone":null,"comments":0,"created_at":"2016-11-26T17:27:58Z","updated_at":"2016-11-29T04:54:44Z","closed_at":null,"body":"This is a very simple proposition to add a `find_map` trait method to the `Iterator` trait.\r\nIt would look like this : \r\n```\r\nfn find_map<B, P>(&mut self, predicate: P) -> Option<B> where P: FnMut(&Self::Item) -> Option<B>;\r\n```\r\n\r\nCurrently to reproduce similar behavior, one would have to use a combination of `filter_map` and `next`. It is obvious for the Rust connoisseur that is aware that an Iterator is lazy and will not do anything unless consumed, but it much less obvious for the standard programmer that doesn't think this way yet.\r\n\r\nLet's take an example : \r\n\r\n```rust\r\n#[derive(Debug,Copy,Clone)]\r\nenum Flavor {\r\n    Chocolate,\r\n    Strawberry,\r\n    Cherry\r\n}\r\n\r\n#[derive(Debug,Copy,Clone)]\r\nenum Dessert {\r\n    Banana,\r\n    Pudding,\r\n    Cake(Flavor)\r\n}\r\n\r\nfn main() {\r\n    let desserts_of_the_week = vec![\r\n        Dessert::Banana,\r\n        Dessert::Cake(Flavor::Chocolate),\r\n        Dessert::Pudding,\r\n        Dessert::Pudding,\r\n        Dessert::Pudding,\r\n    ];\r\n}\r\n```\r\nIf I want to have the \"flavor of the cake of the week\", as an `Option<Flavor>`, a non-newbie Rust user will use this :\r\n```rust\r\nlet cake_of_the_week : Option<Flavor> = desserts_of_the_week.iter().filter_map(|dessert|{\r\n        match dessert {\r\n            &Dessert::Cake(ref flavor) => Some(flavor.clone()),\r\n            _ => None\r\n        }\r\n    }).next();\r\n```\r\n\r\nHowever a new user will be tempted to do something like this :\r\n```rust\r\nlet cake_of_the_week : Option<Flavor> = desserts_of_the_week.iter().find(|dessert|{\r\n        match dessert {\r\n            &&Dessert::Cake(_) => true,\r\n            _ => false\r\n        }\r\n    }).map(|dessert|{\r\n        match dessert {\r\n            &Dessert::Cake(ref flavor) => flavor.clone(),\r\n            _ => unreachable!()\r\n        }\r\n    });\r\n```\r\n\r\nThat is why I propose to add a `find_map` method to the Iterator trait, which would\r\n* Reduce a little bit your code and increase readability (in the case of `filter_map(...).next()`\r\n* Avoid new users to code in a non-idiomatic way\r\n\r\nIt would then look like this : \r\n```rust\r\nlet cake_of_the_week : Option<Flavor> = desserts_of_the_week.iter().find_map(|dessert|{\r\n        match dessert {\r\n            &Dessert::Cake(ref flavor) => Some(flavor.clone()),\r\n            _ => None\r\n        }\r\n    });\r\n```\r\n\r\nThere aren't that much advantages, but I still do think it's worth the while to add such a method.\r\n\r\nMaybe this has been discussed before, in that case I'd appreciate a link to some discussion related to this topic, because I could not find anything.\r\n\r\nThoughts ?"},"comment":{"url":"https://api.github.com/repos/rust-lang/rfcs/issues/comments/263476121","html_url":"https://github.com/rust-lang/rfcs/issues/1801#issuecomment-263476121","issue_url":"https://api.github.com/repos/rust-lang/rfcs/issues/1801","id":263476121,"user":{"login":"bluss","id":3209739,"avatar_url":"https://avatars.githubusercontent.com/u/3209739?v=3","gravatar_id":"","url":"https://api.github.com/users/bluss","html_url":"https://github.com/bluss","followers_url":"https://api.github.com/users/bluss/followers","following_url":"https://api.github.com/users/bluss/following{/other_user}","gists_url":"https://api.github.com/users/bluss/gists{/gist_id}","starred_url":"https://api.github.com/users/bluss/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/bluss/subscriptions","organizations_url":"https://api.github.com/users/bluss/orgs","repos_url":"https://api.github.com/users/bluss/repos","events_url":"https://api.github.com/users/bluss/events{/privacy}","received_events_url":"https://api.github.com/users/bluss/received_events","type":"User","site_admin":false},"created_at":"2016-11-29T04:54:44Z","updated_at":"2016-11-29T04:54:44Z","body":"The closure should get the iterator element by value. In that shape find_map is a good generalization of find, all, any, position etc, so it is a candidate for being the basis method of all of those (similar to [this draft plan](https://github.com/bluss/rfcs/blob/composable-internal-iteration/text/0000-composable-internal-iteration.md), and similar to [`search_while` here](https://github.com/rust-lang/rust/pull/37972) (internal method))."}}
{"actor":{"display_login":"bluss"}}