I have something which I know is a tuple. How do I generically append a single value to the tuple?
let some_tuple: (i32, &str, bool) = (1, "Hello", true);
let with_world: (i32, &str, bool, &str) = some_tuple.append("World");
As a possible use-case, consider a parser combinator which takes a variadic number of parsers and runs each in sequence, producing a tuple of their attributes:
// Emulate variadic parameters:
macro_rules! seq {
($($parsers:expr),*) => {
move |input: &[u8]| {
let result = ();
let remaining = input;
$(
let (remaining, parser_result) = $parsers(remaining);
let result = result.append(parser_result);
)*
result
}
}
}
With tuple appending, seq!(a, b, c, d) can yield (A, B, C, D), rather than the ugly (((A, B), C), D).
As an alternative to a tuple, consider using an HList:
use frunk::hlist; // 0.3.0
fn main() {
let some_values = hlist![1, "Hello", true];
let with_world = some_values.prepend("World");
println!("{:?}", with_world);
}
There's no built-in way to do this, but we can implement it ourselves with a helper trait and a macro to implement that trait for tuples up to N arguments:
trait TupleAppend<T> {
type ResultType;
fn append(self, t: T) -> Self::ResultType;
}
impl<T> TupleAppend<T> for () {
type ResultType = (T,);
fn append(self, t: T) -> Self::ResultType {
(t,)
}
}
macro_rules! impl_tuple_append {
( () ) => {};
( ( $t0:ident $(, $types:ident)* ) ) => {
impl<$t0, $($types,)* T> TupleAppend<T> for ($t0, $($types,)*) {
// Trailing comma, just to be extra sure we are dealing
// with a tuple and not a parenthesized type/expr.
type ResultType = ($t0, $($types,)* T,);
fn append(self, t: T) -> Self::ResultType {
// Reuse the type identifiers to destructure ourselves:
let ($t0, $($types,)*) = self;
// Create a new tuple with the original elements, plus the new one:
($t0, $($types,)* t,)
}
}
// Recurse for one smaller size:
impl_tuple_append! { ($($types),*) }
};
}
impl_tuple_append! {
// Supports tuples up to size 10:
(_1, _2, _3, _4, _5, _6, _7, _8, _9, _10)
}
Playground
Related
In my simplified example I have an algorithm that takes two parameters t: T and transform_fn: fn(&str) -> T where T: TransformRes and trait TransformRes: 'static + Eq + Send {}
Stripped down to a minimum, usage works successfully as below:
struct TransformParameter<T: TransformRes> {
compare: T,
transform_fn: fn(&str) -> T,
}
// TransformParameter works for all types, that implement `Eq`
let t = TransformParameter { compare: transform_usize("5"), transform_fn: transform_usize };
assert_eq!(t.compare, (t.transform_fn)("5"));
let t = TransformParameter { compare: transform_identity("5"), transform_fn: transform_identity };
assert_eq!(t.compare, (t.transform_fn)("5"));
I want to enable a dynamic selection, like so
fn select_transform_fn<T: TransformRes>() -> fn(&str) -> T {
let cond = false;
if cond {
transform_usize
} else {
transform_identity
}
}
This doesn't compile of course and I understand why. Unfortunately, I can't think of a solution that enables me a dynamic selection of the transformation algorithm that preserves me the ability to pass generic functions to my struct TransformParameter.
How can I combine the API that I want with the ability for a dynamic selection of a generic function?
Full code (on Rust Playground):
// Result type of transformation functions.
trait TransformRes: 'static + Eq + Send {}
impl<T> TransformRes for T where T: 'static + Eq + Send {}
struct TransformParameter<T: TransformRes> {
compare: T,
transform_fn: fn(&str) -> T,
}
// Generic Transform Function 1
fn transform_usize(foo: &str) -> usize {
foo.parse::<usize>().unwrap()
}
// Generic Transform Function 2
fn transform_identity(foo: &str) -> String {
String::from(foo)
}
fn main() {
// generic functions: work
let t = TransformParameter { compare: transform_usize("5"), transform_fn: transform_usize };
assert_eq!(t.compare, (t.transform_fn)("5"));
let t = TransformParameter { compare: transform_identity("5"), transform_fn: transform_identity };
assert_eq!(t.compare, (t.transform_fn)("5"));
// generic function selection: doesn't compile.. how to do that?
let foo = select_transform_fn();
foo("foo")
}
fn select_transform_fn<T: TransformRes>() -> fn(&str) -> T {
let cond = false;
if cond {
transform_usize
} else {
transform_identity
}
}
Below is the example given by the mod documentation of syn::parse.
enum Item {
Struct(ItemStruct),
Enum(ItemEnum),
}
struct ItemStruct {
struct_token: Token![struct],
ident: Ident,
brace_token: token::Brace,
fields: Punctuated<Field, Token![,]>,
}
impl Parse for Item {
fn parse(input: ParseStream) -> Result<Self> {
let lookahead = input.lookahead1();
if lookahead.peek(Token![struct]) {
input.parse().map(Item::Struct) // <-- here
} else if lookahead.peek(Token![enum]) {
input.parse().map(Item::Enum) // <-- and here
} else {
Err(lookahead.error())
}
}
}
Is input.parse().map(Item::Struct) a valid normal Rust syntax (appears not as Item::Struct is not a function), or is it a kind of special syntax for proc_macro libs? If the latter is the case, is there a documentation of the proc_macro specific syntax rules?
This syntax is standard Rust syntax. You can use tuple struct or tuple struct-like enum variants as functions. See this small example:
enum Color {
Str(String),
Rgb(u8, u8, u8),
}
struct Foo(bool);
// Use as function pointers (type annotations not necessary)
let f: fn(String) -> Color = Color::Str;
let g: fn(u8, u8, u8) -> Color = Color::Rgb;
let h: fn(bool) -> Foo = Foo;
In the next example, those functions are directly passed to another function (like Option::map) (Playground):
// A function which takes a function
fn string_fn<O, F>(f: F) -> O
where
F: FnOnce(String) -> O,
{
f("peter".to_string())
}
string_fn(|s| println!("{}", s)); // using a clojure
string_fn(std::mem::drop); // using a function pointer
// Using the enum variant as function
let _: Color = string_fn(Color::Str);
You can find out more about this feature, in this chapter of the book.
I have a block of code where multiple optional variables need to be assigned at once. There is very little chance any of the values will be None, so individually handing each failed case isn't especially useful.
Currently I write the checks like this:
if let Some(a) = foo_a() {
if let Some(b) = foo_b() {
if let Some(c) = foo_c() {
if let Some(d) = foo_d() {
// code
}
}
}
}
It would be convenient if it was possible to group assignments. Without this, adding a new variable indents the block one level, making for noisy diffs and causes unnecessarily deep indentation:
if let Some(a) = foo_a() &&
let Some(b) = foo_b() &&
let Some(c) = foo_c() &&
let Some(d) = foo_d()
{
// code
}
Is there a way to assign multiple Options in one if statement?
Some details worth noting:
The first function that fails should short circuit and not call the others. Otherwise, it could be written like this:
if let (Some(a), Some(b), Some(c), Some(d)) = (foo_a(), foo_b(), foo_c(), foo_d()) {
// Code
}
Deep indentation could be avoided using a function, but I would prefer not to do this since you may not want to have the body in a different scope...
fn my_function(a: Foo, b: Foo, c: Foo, d: Foo) {
// code
}
if let Some(a) = foo_a() {
if let Some(b) = foo_b() {
if let Some(c) = foo_c() {
if let Some(d) = foo_d() {
my_function(a, b, c, d);
}
}
}
}
As #SplittyDev said, you can create a macro to get the functionality you want. Here is an alternate macro-based solution which also retains the short-circuiting behaviour:
macro_rules! iflet {
([$p:pat = $e:expr] $($rest:tt)*) => {
if let $p = $e {
iflet!($($rest)*);
}
};
($b:block) => {
$b
};
}
fn main() {
iflet!([Some(a) = foo_a()] [Some(b) = foo_b()] [Some(c) = foo_c()] {
println!("{} {} {}", a, b, c);
});
}
Playground
The standard library doesn't include that exact functionality, but the language allows you to create the desired behavior using a small macro.
Here's what I came up with:
macro_rules! all_or_nothing {
($($opt:expr),*) => {{
if false $(|| $opt.is_none())* {
None
} else {
Some(($($opt.unwrap(),)*))
}
}};
}
You can feed it all your options and get some tuple containing the unwrapped values if all values are Some, or None in the case that any of the options are None.
The following is a brief example on how to use it:
fn main() {
let foo = Some(0);
let bar = Some(1);
let baz = Some(2);
if let Some((a, b, c)) = all_or_nothing!(foo, bar, baz) {
println!("foo: {}; bar: {}; baz: {}", a, b, c);
} else {
panic!("Something was `None`!");
}
}
Here's a full test-suite for the macro: Rust Playground
My first inclination was to do something similar to swizard's answer, but to wrap it up in a trait to make the chaining cleaner. It's also a bit simpler without the need for extra function invocations.
It does have the downside of increasing the nesting of the tuples.
fn foo_a() -> Option<u8> {
println!("foo_a() invoked");
Some(1)
}
fn foo_b() -> Option<u8> {
println!("foo_b() invoked");
None
}
fn foo_c() -> Option<u8> {
println!("foo_c() invoked");
Some(3)
}
trait Thing<T> {
fn thing<F, U>(self, f: F) -> Option<(T, U)> where F: FnOnce() -> Option<U>;
}
impl<T> Thing<T> for Option<T> {
fn thing<F, U>(self, f: F) -> Option<(T, U)>
where F: FnOnce() -> Option<U>
{
self.and_then(|a| f().map(|b| (a, b)))
}
}
fn main() {
let x = foo_a()
.thing(foo_b)
.thing(foo_c);
match x {
Some(((a, b), c)) => println!("matched: a = {}, b = {}, c = {}", a, b, c),
None => println!("nothing matched"),
}
}
Honestly, someone should notice about Option being an applicative functor :)
The code will be quite ugly without currying support in Rust, but it works and it shouldn't make a noisy diff:
fn foo_a() -> Option<isize> {
println!("foo_a() invoked");
Some(1)
}
fn foo_b() -> Option<isize> {
println!("foo_b() invoked");
Some(2)
}
fn foo_c() -> Option<isize> {
println!("foo_c() invoked");
Some(3)
}
let x = Some(|v| v)
.and_then(|k| foo_a().map(|v| move |x| k((v, x))))
.and_then(|k| foo_b().map(|v| move |x| k((v, x))))
.and_then(|k| foo_c().map(|v| move |x| k((v, x))))
.map(|k| k(()));
match x {
Some((a, (b, (c, ())))) =>
println!("matched: a = {}, b = {}, c = {}", a, b, c),
None =>
println!("nothing matched"),
}
You can group the values using the '?' operator to return an Option of a tuple with the required values. If on of then is None, the group_options function will return None.
fn foo_a() -> Option<u8> {
println!("foo_a() invoked");
Some(1)
}
fn foo_b() -> Option<u8> {
println!("foo_b() invoked");
None
}
fn foo_c() -> Option<u8> {
println!("foo_c() invoked");
Some(3)
}
fn group_options() -> Option<(u8, u8, u8)> {
let a = foo_a()?;
let b = foo_b()?;
let c = foo_c()?;
Some((a, b, c))
}
fn main() {
if let Some((a, b, c)) = group_options() {
println!("{}", a);
println!("{}", b);
println!("{}", c);
}
}
This question already has answers here:
How do I stop iteration and return an error when Iterator::map returns a Result::Err?
(4 answers)
Closed 3 years ago.
I have code like this:
let things = vec![/* ...*/]; // e.g. Vec<String>
things
.map(|thing| {
let a = try!(do_stuff(thing));
Ok(other_stuff(a))
})
.filter(|thing_result| match *thing_result {
Err(e) => true,
Ok(a) => check(a),
})
.map(|thing_result| {
let a = try!(thing_result);
// do stuff
b
})
.collect::<Result<Vec<_>, _>>()
In terms of semantics, I want to stop processing after the first error.
The above code works, but it feels quite cumbersome. Is there a better way? I've looked through the docs for something like filter_if_ok, but I haven't found anything.
I am aware of collect::<Result<Vec<_>, _>>, and it works great. I'm specifically trying to eliminate the following boilerplate:
In the filter's closure, I have to use match on thing_result. I feel like this should just be a one-liner, e.g. .filter_if_ok(|thing| check(a)).
Every time I use map, I have to include an extra statement let a = try!(thing_result); in order to deal with the possibility of an Err. Again, I feel like this could be abstracted away into .map_if_ok(|thing| ...).
Is there another approach I can use to get this level of conciseness, or do I just need to tough it out?
There are lots of ways you could mean this.
If you just want to panic, use .map(|x| x.unwrap()).
If you want all results or a single error, collect into a Result<X<T>>:
let results: Result<Vec<i32>, _> = result_i32_iter.collect();
If you want everything except the errors, use .filter_map(|x| x.ok()) or .flat_map(|x| x).
If you want everything up to the first error, use .scan((), |_, x| x.ok()).
let results: Vec<i32> = result_i32_iter.scan((), |_, x| x.ok());
Note that these operations can be combined with earlier operations in many cases.
Since Rust 1.27, Iterator::try_for_each could be of interest:
An iterator method that applies a fallible function to each item in the iterator, stopping at the first error and returning that error.
This can also be thought of as the fallible form of for_each() or as the stateless version of try_fold().
You can implement these iterators yourself. See how filter and map are implemented in the standard library.
map_ok implementation:
#[derive(Clone)]
pub struct MapOkIterator<I, F> {
iter: I,
f: F,
}
impl<A, B, E, I, F> Iterator for MapOkIterator<I, F>
where
F: FnMut(A) -> B,
I: Iterator<Item = Result<A, E>>,
{
type Item = Result<B, E>;
#[inline]
fn next(&mut self) -> Option<Self::Item> {
self.iter.next().map(|x| x.map(&mut self.f))
}
}
pub trait MapOkTrait {
fn map_ok<F, A, B, E>(self, func: F) -> MapOkIterator<Self, F>
where
Self: Sized + Iterator<Item = Result<A, E>>,
F: FnMut(A) -> B,
{
MapOkIterator {
iter: self,
f: func,
}
}
}
impl<I, T, E> MapOkTrait for I
where
I: Sized + Iterator<Item = Result<T, E>>,
{
}
filter_ok is almost the same:
#[derive(Clone)]
pub struct FilterOkIterator<I, P> {
iter: I,
predicate: P,
}
impl<I, P, A, E> Iterator for FilterOkIterator<I, P>
where
P: FnMut(&A) -> bool,
I: Iterator<Item = Result<A, E>>,
{
type Item = Result<A, E>;
#[inline]
fn next(&mut self) -> Option<Result<A, E>> {
for x in self.iter.by_ref() {
match x {
Ok(xx) => if (self.predicate)(&xx) {
return Some(Ok(xx));
},
Err(_) => return Some(x),
}
}
None
}
}
pub trait FilterOkTrait {
fn filter_ok<P, A, E>(self, predicate: P) -> FilterOkIterator<Self, P>
where
Self: Sized + Iterator<Item = Result<A, E>>,
P: FnMut(&A) -> bool,
{
FilterOkIterator {
iter: self,
predicate: predicate,
}
}
}
impl<I, T, E> FilterOkTrait for I
where
I: Sized + Iterator<Item = Result<T, E>>,
{
}
Your code may look like this:
["1", "2", "3", "4"]
.iter()
.map(|x| x.parse::<u16>().map(|a| a + 10))
.filter_ok(|x| x % 2 == 0)
.map_ok(|x| x + 100)
.collect::<Result<Vec<_>, std::num::ParseIntError>>()
playground
filter_map can be used to reduce simple cases of mapping then filtering. In your example there is some logic to the filter so I don't think it simplifies things. I don't see any useful functions in the documentation for Result either unfortunately. I think your example is as idiomatic as it could get, but here are some small improvements:
let things = vec![...]; // e.g. Vec<String>
things.iter().map(|thing| {
// The ? operator can be used in place of try! in the nightly version of Rust
let a = do_stuff(thing)?;
Ok(other_stuff(a))
// The closure braces can be removed if the code is a single expression
}).filter(|thing_result| match *thing_result {
Err(e) => true,
Ok(a) => check(a),
}
).map(|thing_result| {
let a = thing_result?;
// do stuff
b
})
The ? operator can be less readable in some cases, so you might not want to use it.
If you are able to change the check function to return Some(x) instead of true, and None instead of false, you can use filter_map:
let bar = things.iter().filter_map(|thing| {
match do_stuff(thing) {
Err(e) => Some(Err(e)),
Ok(a) => {
let x = other_stuff(a);
if check_2(x) {
Some(Ok(x))
} else {
None
}
}
}
}).map(|thing_result| {
let a = try!(thing_result);
// do stuff
b
}).collect::<Result<Vec<_>, _>>();
You can get rid of the let a = try!(thing); by using a match in some cases as well. However, using filter_map here doesn't seem to help.
I want to cast a (u16, u16) to a (f32, f32). This is what I tried:
let tuple1 = (5u16, 8u16);
let tuple2 = tuple1 as (f32, f32);
Ideally, I would like to avoid writing
let tuple2 = (tuple1.0 as f32, tuple1.1 as f32);
There's no built-in way to do this, but one can do it with a macro:
macro_rules! tuple_as {
($t: expr, ($($ty: ident),*)) => {
{
let ($($ty,)*) = $t;
($($ty as $ty,)*)
}
}
}
fn main() {
let t: (u8, char, isize) = (97, 'a', -1);
let other = tuple_as!(t, (char, i32, i8));
println!("{:?}", other);
}
Prints ('a', 97, -1).
The macro only works for casting between types with names that are a single identifier (that's what the : ident refers to), since it reuses those names for binding to the elements of the source tuple to be able to cast them. All primitive types are valid single identifiers, so it works well for those.
No, you cannot. This is roughly equivalent to "can I cast all the fields in a struct to different types all at once?".
You can write a generic extension trait which can do this conversion for you, the only problem is that I don't believe there's any existing generic "conversion" trait which also has a u16 -> f32 implementation defined.
If you really want a function that does this, here is an as-minimal-as-I-could-make-it skeleton you can build on:
trait TupleCast<T> {
type Output;
fn tuple_cast(self) -> <Self as TupleCast<T>>::Output;
}
impl<T> TupleCast<T> for () {
type Output = ();
fn tuple_cast(self) -> <() as TupleCast<T>>::Output {
()
}
}
impl<S, T> TupleCast<T> for (S,) where S: CustomAs<T> {
type Output = (T,);
fn tuple_cast(self) -> <(S,) as TupleCast<T>>::Output {
(self.0.custom_as(),)
}
}
impl<S, T> TupleCast<T> for (S, S) where S: CustomAs<T> {
type Output = (T, T);
fn tuple_cast(self) -> <(S, S) as TupleCast<T>>::Output {
(self.0.custom_as(), self.1.custom_as())
}
}
// You would probably have more impls, up to some size limit.
// We can't use std::convert::From, because it isn't defined for the same
// basic types as the `as` operator is... which kinda sucks. So, we have
// to implement the desired conversions ourselves.
//
// Since this would be hideously tedious, we can use a macro to speed things
// up a little.
trait CustomAs<T> {
fn custom_as(self) -> T;
}
macro_rules! custom_as_impl {
($src:ty:) => {};
($src:ty: $dst:ty) => {
impl CustomAs<$dst> for $src {
fn custom_as(self) -> $dst {
self as $dst
}
}
};
($src:ty: $dst:ty, $($rest:ty),*) => {
custom_as_impl! { $src: $dst }
custom_as_impl! { $src: $($rest),* }
};
}
// You could obviously list others, or do manual impls.
custom_as_impl! { u16: u16, u32, u64, i32, i64, f32, f64 }
fn main() {
let x: (u16, u16) = (1, 2);
let y: (f32, f32) = x.tuple_cast();
println!("{:?}", y);
}
No,
there
is
not.
this version handles a few more cases Playground Example
original source: https://stackoverflow.com/a/29981602/5979634
because of matching rules, for single type casts just use as_tuple!(expr, T) or as_tuple!(expr, (T))
the rest works as in the original answer
macro_rules! tuple_as {
($t: expr, $ty: ident) => {{
let (a, b) = $t;
let a = a as $ty;
let b = b as $ty;
(a, b)
}};
($t: expr, ($ty: ident)) => {{
let (a, b) = $t;
let a = a as $ty;
let b = b as $ty;
(a, b)
}};
($t: expr, ($($ty: ident),*)) => {{
let ($($ty,)*) = $t;
($($ty as $ty,)*)
}}}