These are chat archives for rust-lang/rust

22nd
Jan 2018
Hans W. Uhlig
@huhlig
Jan 22 2018 02:05
hmm... silly question... when declaring an external crate is it possible to make #[macro_use] conditional to tests only while still using the crate?
Ryan
@rnleach
Jan 22 2018 02:23
@huhlig try cfg_attr, with the test feature. Same as you would for a module or function.
Hans W. Uhlig
@huhlig
Jan 22 2018 02:28

[cfg(feature = "macro_use")]

like that...
wow... didn't mean to bold
Ryan
@rnleach
Jan 22 2018 02:30
#[cfg_attr(test, macro_use)] 
extern crate my_crate;
Hans W. Uhlig
@huhlig
Jan 22 2018 02:30
ahh ok
hmm, this is a new error
C:/Users/huhlig/.cargo/bin/cargo.exe test --lib -- --nocapture
    Finished dev [unoptimized + debuginfo] target(s) in 0.0 secs
     Running target\debug\deps\blockchain_rs-346b88c48ef961a2.exe

running 1 test
error: test failed, to rerun pass '--lib'
Ryan
@rnleach
Jan 22 2018 02:34
Never seen that one before.
Kelly Thomas Kline
@kellytk
Jan 22 2018 08:38
If your goal was to write an interactive text-based terminal such as psql, which Rust crates would you look to for its basic infrastructure? (a prompt string, input history that may be keyed through, etc)
Michal 'vorner' Vaner
@vorner
Jan 22 2018 08:41
Isn't there a binding to readline somewhere?
Kelly Thomas Kline
@kellytk
Jan 22 2018 09:15
There may be, although I would prefer an exclusively-Rust dependency tree if feasible
nimtiazm
@nimtiazm
Jan 22 2018 09:44
clap
Denis Lisov
@tanriol
Jan 22 2018 09:46
Michal 'vorner' Vaner
@vorner
Jan 22 2018 10:25
@kellytk Is there an actual pragmatic reason for that, or just because it is nicer? I mean, there are some good battle-tested libraries not written in Rust and while it might make sense replacing them in the long run, concentrating on the missing parts is probably more useful.
Kelly Thomas Kline
@kellytk
Jan 22 2018 10:35
@vorner I suspect more correct code can be written with Rust making me more comfortable with external code
Thanks @nimtiazm @tanriol
Michal 'vorner' Vaner
@vorner
Jan 22 2018 11:33
@kellytk If it was code of the same age, then you'd be probably right. But readline is old and doesn't suffer from like these baby-illness bugs.
Kelly Thomas Kline
@kellytk
Jan 22 2018 11:44
@vorner I use linenoise on the C side but your point remains and it's a fair one, thanks
Patrick Elsen
@xfbs
Jan 22 2018 12:24
Okay so I'm trying to write a generic function that takes two arguments (of type LHS and RHS), which are both numeric but can be of different types. I want the return type of the function to be either RHS or LHS, depending on which type is bigger — how do I do this without having to explicitly denote the types? What I have right now is something like this: https://gist.github.com/ac152997e17242b81daf32dbeae49950
But basically I want to be able to call maximum(12u8, 12345u16) and have rustc infer that the return type should be u16. Is there a way to do this?
Diggory Blake
@Diggsey
Jan 22 2018 12:28
@xfbs you could add a trait LargerInt { type Result; }, and then implement it for tuples of the form (<int>, <int>)
fn maximum<LHS, RHS>(lhs: LHS, rhs: RHS) -> <(LHS, RHS) as LargerInt>::Result where (LHS, RHS): LargerInt
red75prime
@red75prime
Jan 22 2018 12:34
It would be useful to add fn maximum(self) -> Self::Output; member to LargerInt, otherwise there's no way to implement the free function maximum.
Denis Lisov
@tanriol
Jan 22 2018 12:39
@red75prime Why no way to implement?
red75prime
@red75prime
Jan 22 2018 12:45
Good catch. I seem to retain pre-Rust 1.5.0 impression of very limited support for integer conversions.
Patrick Elsen
@xfbs
Jan 22 2018 15:30
How do I know what the type of a closure is? The manual just tells me to Box<> the closure up, but that's not what I'm trying to do here. What do I have to change?
impl IntoIterator for Sieve {
    type Item = u64;
    type IntoIter = FilterMap<Enumerate<IntoIter<bool>>, &'static Fn(&(usize, bool)) -> bool>;

    fn into_iter(self) -> Self::IntoIter {
        self.state
            .into_iter()
            .enumerate()
            .filter_map(|&(pos, prim)| if prim { Some(pos as u64) } else { None})
    }
}
Relevant section in the manual: https://doc.rust-lang.org/1.0.0/book/closures.html
Steve Klabnik
@steveklabnik
Jan 22 2018 15:31
that's the 1.0 docs! :)
nothing should be wrong per se
but just saying
so
the issue here is
you cannot name a closure's type
Patrick Elsen
@xfbs
Jan 22 2018 15:31
I totally blame that on google, was the first result :smile:
Steve Klabnik
@steveklabnik
Jan 22 2018 15:31
which means, as the error says, you have to box it and use a trait object, at the moment
in future Rust, there'll be more options
Patrick Elsen
@xfbs
Jan 22 2018 15:32
Can I use a boxed version with FilterMap? Or do I just have to implement my own Iterator struct?
Steve Klabnik
@steveklabnik
Jan 22 2018 15:33
if you can give me a playpen that shows just your error, i can show you
Zakarum
@omni-viral
Jan 22 2018 15:33
@xfbs you can do FilterMap<..., Box<FnMut(...) -> ...>
Steve Klabnik
@steveklabnik
Jan 22 2018 15:33
but it'd be Box<Iterator<Item=something>>
basically
Zakarum
@omni-viral
Jan 22 2018 15:34
Or how @steveklabnik suggest
There is another option to avoid heap allocation
use fn(&(usize, bool)) -> bool type
Using an fn implies that I just declare a normal function instead of a closure right?
note that i removed your extra import of FnMut too
Patrick Elsen
@xfbs
Jan 22 2018 15:39
Okay whoa, that is a LOT cleaner!
Jonas Platte
@jplatte
Jan 22 2018 15:40
@xfbs Since a few releases, closures that don't capture anything can be converted implicitly into the respective fn() type
Steve Klabnik
@steveklabnik
Jan 22 2018 15:40
:)
Patrick Elsen
@xfbs
Jan 22 2018 16:49
Is there something like a fold_map in rust, which similar to fold has a memo that gets passed around, but instead of fold yielding only at the very end, it yields after every iteration? Something like this:
assert_eq!((1..10).fold_map(0u32, |memo, cur| memo + cur).collect::<Vec<u32>>(), vec![1, 3, 6, 10, 14, 19, 25, 32, 40, 49]);
Oh wait, I think scan() is what I'm looking for
Patrick Elsen
@xfbs
Jan 22 2018 18:19
Is there a way to unflatten iterators over tuples of (u32, u32)?
Zakarum
@omni-viral
Jan 22 2018 18:23
What does "unflatten" means?
"Unzipping" maybe?
Patrick Elsen
@xfbs
Jan 22 2018 18:24
Like if you have an iterator with the elements [(1, 2), (3, 4), (5, 6), (7, 8)], I'd like to turn that into [1, 2, 3, 4, 5, 6, 7, 8]. I guess you could call that unzip :)
Jonas Platte
@jplatte
Jan 22 2018 18:25
@xfbs I'd call that flatten
and you can do it with flat_map
Patrick Elsen
@xfbs
Jan 22 2018 18:26
I tried, but how? Tuples don't implement .iter(), do they?
Jonas Platte
@jplatte
Jan 22 2018 18:26
Nope, first thing I can think of is convert to vector
as arrays unfortunately don't implement IntoIter either
.flat_map(|(a, b)| vec![a, b]) should work
Zakarum
@omni-viral
Jan 22 2018 18:28
once(a).chain(once(b)) will avoid allocations
Jonas Platte
@jplatte
Jan 22 2018 18:28
Huh. Didn't know about once
Zakarum
@omni-viral
Jan 22 2018 18:28
Some will do the same
Jonas Platte
@jplatte
Jan 22 2018 18:29
Well, roughly
Zakarum
@omni-viral
Jan 22 2018 18:29
Why "roughly"?
Jonas Platte
@jplatte
Jan 22 2018 18:29
For Option, you'd have to call into_iter manually here
Zakarum
@omni-viral
Jan 22 2018 18:30
Not at all
Jonas Platte
@jplatte
Jan 22 2018 18:30
huh?
Patrick Elsen
@xfbs
Jan 22 2018 18:30
use std::iter::once;

fn main() {
    let _: u32 = (1u32..10)
        .map(|n| (n, n))
        .flat_map(|(a, b)| once(a).chain(once(b)))
        .sum();
}
can confirm, vec![a, b] and once(a).chain(once(b)) both work :)
Zakarum
@omni-viral
Jan 22 2018 18:30
flat_map will do it for you
Jonas Platte
@jplatte
Jan 22 2018 18:30
before .chain?
Zakarum
@omni-viral
Jan 22 2018 18:30
Ah. Ofc
Silly me
You're right
blankhart
@blankhart
Jan 22 2018 19:44
i have a question about implementing a trait over another trait, specifically Iterator
if i try the naive thing like this:
impl<T: DateLike> Iterator for T {
  type Item = Self;

  fn next(&mut self) -> Option<Self::Item> {
    *self = self.succ();
    Some(*self)
  }

}
i get error messages like this
error[E0119]: conflicting implementations of trait `std::iter::Iterator` for type `&mut _`:
   --> src/date/date.rs:251:1
    |
251 | impl<T: DateLike> Iterator for T {
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
    = note: conflicting implementation in crate `core`:
            - impl<'a, I> std::iter::Iterator for &'a mut I
              where I: std::iter::Iterator, I: ?Sized;
    = note: downstream crates may implement trait `date::date::DateLike` for type `&mut _`

error[E0210]: type parameter `T` must be used as the type parameter for some local type (e.g. `MyStruct<T>`); only traits defined in the current crate can be implemented for a type parameter
   --> src/date/date.rs:251:1
    |
251 | / impl<T: DateLike> Iterator for T {
252 | |   type Item = Self;
253 | |
254 | |   fn next(&mut self) -> Option<Self::Item> {
...   |
258 | |
259 | | }
    | |_^

error: aborting due to 2 previous errors
however, the standard implementation of IntoIterator over Iterator seems to me pretty similar - see https://doc.rust-lang.org/src/core/iter/traits.rs.html#250
is there trait bound syntax to make clear that Tcan't be a reference? or do i have to use a macro and then specify the DateLike structs that i want to implement Iterator
Denis Lisov
@tanriol
Jan 22 2018 19:57
Is the DateLike trait public?
blankhart
@blankhart
Jan 22 2018 19:57
oh nevermind sorry i see the orphan rules. right there in the error
yeah
this is https://doc.rust-lang.org/error-index.html#E0210 which i need to spend time with but seems intended to enforce a kind of typeclass coherence
i guess it just means that if i want an Iterator implementation for 5 different DateLike structs a macro is the way to go
blankhart
@blankhart
Jan 22 2018 20:13
this worked. if there is a more standard way to do the same thing without macros i'd be interested
macro_rules! datelike_iterator {
  ($($a:ident)*) => ($(
    impl Iterator for $a {
      type Item = $a;
      fn next(&mut self) -> Option<Self::Item> {
        *self = self.succ();
        Some(*self)
      }
    }
  )*)
}

datelike_iterator! { Date SerialDate }
Denis Lisov
@tanriol
Jan 22 2018 20:14
Separate iterator types?
blankhart
@blankhart
Jan 22 2018 20:15
that seemed undesirable since i wanted the iterator behavior to be specified by the typeclass behavior (DateLike) rather than potentially to depend on the representation as data
i guess i haven't really accomplished that this way, though, other than by tying the Iterator implementation for these particular types to the DateLike method
Denis Lisov
@tanriol
Jan 22 2018 20:19
I'd look into something like a wrapper type
struct DateIterator<T: DateLike>(T);
impl<T> Iterator for DateIterator<T> { ... }
blankhart
@blankhart
Jan 22 2018 20:23
oh i see now. there is no way to enforce a rule that an Iterator for a type with a DateLike instance conforms to the desired DateLike behavior, but i can guarantee that a DateIteratorwill. and maybe that is better from a design perspective because it decouples Iterator (as such) from DateLike.
at the cost maybe of adding a method iter() to DateLike to return a DateIterator
blankhart
@blankhart
Jan 22 2018 20:30
thank you @tanriol that worked and i think is strictly an improvement
Patrick Elsen
@xfbs
Jan 22 2018 20:39
What is the syntax for casting a variable of type T into f64 in generic code?
Sergey Noskov
@Albibek
Jan 22 2018 20:41
@xfbs Into<f64> should fit well, I think
Patrick Elsen
@xfbs
Jan 22 2018 20:43
How do I use it? Into<f64>::into(43u8) for example?