Skip to content
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

Converting types with an expression (not a statement) #12482

Closed
Valloric opened this issue Feb 23, 2014 · 3 comments
Closed

Converting types with an expression (not a statement) #12482

Valloric opened this issue Feb 23, 2014 · 3 comments

Comments

@Valloric
Copy link
Contributor

Here's example code showing ideal code I'd like to write:

fn example( pattern: &str ) {
  match pattern.split( '*' ).collect() {
    [head, tail] => println!( "{:?} {:?}", head, tail ),
    _ => ()
  };
}

and here's the code Rust forces me to write:

fn example( pattern: &str ) {
  let items: ~[&str] = pattern.split( '*' ).collect();
  let items_ref: &[&str] = items;
  match items_ref {
    [head, tail] => println!( "{:?} {:?}", head, tail ),
    _ => ()
  };
}

Notice the useless items and items_ref vars. They only exist to placate the compiler. I understand that pattern.split( '*' ).collect() returns a std::iter::FromIterator<&str> and that conversions need to happen, but I'm currently forced to use vars to achieve this. The as keyword for casting only works with primitive numeric types or pointers, so I know of no way to get a ~[&str] out of pattern.split( '*' ).collect() (and then a &[&str] out of that) with an expression.

The match makes this a very pathological example, but here's something more common:

fn takes_ref_vec( items: &[int] ) {
  println!( "{:?}", items )
}

#[test]
fn takes_ref_vec_tests() {
  // Doesn't compile!
  takes_ref_vec( [1, 2, 3].iter().map( |&x| x ).collect() ) 

  // Infinite sadness...
  let useless: ~[int] = [1, 2, 3].iter().map( |&x| x ).collect();
  takes_ref_vec( useless );
}

I know I'm unlikely to convince the Rust devs to accept implicit casts, but could we make explicit casts possible with an expression? Something like as for numeric types? Having to introduce a new variable name only for the sake of a cast is not very user-friendly and only leads to boilerplate code. Also, being forced to use a statement to cast a type feels quite un-functional and needlessly breaks my expression chains.

I'm a complete Rust newbie, so apologies if I'm missing some obvious solution to the above problems.

This is all using the latest Rust nightly.

@Valloric
Copy link
Contributor Author

...and I just realized that takes_ref_vec( [1, 2, 3].iter().map( |&x| x ).collect() ) can be rewritten as takes_ref_vec( [1, 2, 3].iter().map( |&x| x ).to_owned_vec() ) and that works. Similar for the first example.

Ok, so my examples are crap, but (I think) my point still stands.

@huonw
Copy link
Member

huonw commented Feb 23, 2014

The items_ref variable can be replaced by just match items.as_slice() { ... }, and you can give a type hint with .collect::<~[&str]>(), i.e.

match pattern.split( '*' ).collect::<~[&str]>().as_slice() {
    [head, tail] => println!( "{:?} {:?}", head, tail ),
    _ => ()
};

works for me.

There are some other proposals/issues that make this nicer:

As such, I'm closing this as a dupe (particularly of #10502).

(Also, note that your first example would be better achieved with:

let mut iter = pattern.split('*');
match (iter.next(), iter.next(), iter.next()) {
    // exactly 2 elements
    (Some(head), Some(tail), None) => { ... }
    _ => {}
}

as this saves the vector allocation (which can be arbitrarily large, since a string can contain as many *s as it wants).)

@huonw huonw closed this as completed Feb 23, 2014
@Valloric
Copy link
Contributor Author

As such, I'm closing this as a dupe (particularly of #10502).

Freaking hell, I searched and searched and couldn't find any relevant issue. Sigh... sorry I missed it. It's exactly what I was talking about. #9508 also looks great, I'll subscribe to that as well.

The items_ref variable can be replaced by just match items.as_slice() { ... }, and you can give a type hint with .collect::<~[&str]>()

Ah... that's a bit beyond my current Rust knowledge level. Thanks for pointing it out.

matthiaskrgr pushed a commit to matthiaskrgr/rust that referenced this issue Mar 21, 2024
fix [`dbg_macro`] FN when dbg is inside some complex macros

fixes: rust-lang#12131

It appears that [`root_macro_call_first_node`] only detects `println!` in the following example:
```rust
println!("{:?}", dbg!(s));
```
---

changelog: fix [`dbg_macro`] FN when `dbg` is inside some complex macros

(re-opening b'cuz bors doesn't like my previous one)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants