These are chat archives for rust-lang/rust

11th
Jun 2018
Michael Thomas
@Michaelt293
Jun 11 2018 01:03

I'm trying to understand how Rust handles non-annotated floating point numbers. In the rust book, it says "The default type is f64 because on modern CPUs it’s roughly the same speed as f32 but is capable of more precision.". However, the following code compiles -

    let a = 4.5;
    let b: f32 = 1.0;
    let c: f64 = 2.0;
    let test1 = a + b;

as does -

    let a = 4.5;
    let b: f32 = 1.0;
    let c: f64 = 2.0;
    // let test1 = a + b;
    let test2 = a + c;

But this doesn't-

    let a = 4.5;
    let b: f32 = 1.0;
    let c: f64 = 2.0;
    let test1 = a + b;
    let test2 = a + c;

So to me, it seems the type of a is something like A: Float (where a can be either f32 or f64, but not both). So what is the type of a?

Michael Thomas
@Michaelt293
Jun 11 2018 01:26
I think I understand, it defaults to f64, however, if it is used with a f32 (as in the first example), the type becomes f32. As far as I know, it is not possible to express in Rust the type of a variable as let a :: Fractional t => t; a = 3.14 (using Haskell as an example). In pseudo Rust, I think that would be let a<A: Float>: A = 3.14.
Dmitriy
@dpogretskiy
Jun 11 2018 07:53
It defaults to f64 only when you never use it, or it's some really weird case, otherwise it just infers the type out of first usage, which in your case decides whether it's f32 or f64, but it can't be both.
It's not tied to floats, but a general rule for all inferred types.
Dmitriy
@dpogretskiy
Jun 11 2018 08:11
@Michaelt293
use std::cmp::Eq;
use std::collections::HashMap;
use std::hash::Hash;

fn extend_from<A: Hash + Eq + Clone, B: Clone>(to: &mut HashMap<A, B>, from: &mut HashMap<A, B>) {
    to.extend(from.clone().into_iter());
}

fn extend_vec_from<A: Clone>(to: &mut Vec<A>, from: &mut Vec<A>) {
    to.extend(from.clone().into_iter())
}

fn main() {
    let mut a = (1..5).enumerate().collect();

    let mut b: HashMap<usize, usize> = HashMap::new();
    let mut c: Vec<(usize, usize)> = Vec::new();

    // extend_from(&mut b, &mut a);
    extend_vec_from(&mut c, &mut a);

    println!("{:?} {:?}", b, c);
}
this actually works the same way, only compiles if one of branches is active, any tho.
collect() has different meaning depending on awaited type, to be clear.
Michael Thomas
@Michaelt293
Jun 11 2018 12:43
@dpogretskiy thanks for your answer. Makes sense now.
trsh
@trsh
Jun 11 2018 14:25
What is best process for returning a future in Double loop?
for output in &node.outputs {
      for c in &output.connections {
        let c_node = nodes
          .get(&c.node.to_string())
          .expect("Unknown output connection node");

        self.xxx(c_node); // this needs to be a future, because it's async
    }
Without wait
Dmitriy
@dpogretskiy
Jun 11 2018 15:36
future::select_all can do the trick
futures::future::select_all(node.outputs.flat_map(|output| output.connections.map(|c| ...)));
trsh
@trsh
Jun 11 2018 15:50
@dpogretskiy The returned future will wait for any future within iter to be ready I wonder what they mean with any
If it would be written all it would be clear
I also need to execute them in correct order, one after another.. not all on once. As every xxx is dependent on previous :D
So I dont think this will fly
Dmitriy
@dpogretskiy
Jun 11 2018 16:02
sounds fishy, but select_ok should poll for any, while select_all for all, obviously
you could always try tho, or watch sources for more info
hmm, guess i'm wrong
Dmitriy
@dpogretskiy
Jun 11 2018 16:18
traditionally, such operation in other languages is expressed through fold and flat_map/and_then and usually yields a list of futures, it's not a list, but stucture is something like that, one depends on all the others, from head to tail, which will yield a HUGE struct in rust that also happens to be unsized :worried:
trsh
@trsh
Jun 11 2018 16:25
@dpogretskiy :/
Dmitriy
@dpogretskiy
Jun 11 2018 16:25
you can hack it through i beilieve, which is probably worth the effort
hm, select_all is tricky but does the trick actually
it returns results one by one when you poll them, with index and rest of the iter elements
i have no idea how to use it, but it's neat :laughing:
trsh
@trsh
Jun 11 2018 16:42
@dpogretskiy no examples, brhhh
Goodled somthing.. lets try
The select function runs two (or more in case of select_all) futures and returns the first one coming to completion. This is useful for implementing timeouts. Our example can simply be
trsh
@trsh
Jun 11 2018 16:47
Returns FIrst one
Docs suck
trsh
@trsh
Jun 11 2018 16:53
still select_all seems no to care about order
Dmitriy
@dpogretskiy
Jun 11 2018 17:27
hm, you can put all your futures into a Stream, and do something then
+fold
trsh
@trsh
Jun 11 2018 18:07
hmm
tnx, will loook into
trsh
@trsh
Jun 11 2018 18:28
@dpogretskiy but does loop_fn, dosn't fit the situation?
Dmitriy
@dpogretskiy
Jun 11 2018 18:36
i have no idea, but it doesn't seem so
it's more like unfold, apparently
trsh
@trsh
Jun 11 2018 18:41
@dpogretskiy what do u mean with that?
unfold
Dmitriy
@dpogretskiy
Jun 11 2018 18:42
it's a function that allows you to create sequences of any kind(streams, iterators, collections) out of one value that changes with each iteration
like fibbonacci sequence
trsh
@trsh
Jun 11 2018 18:43
hmmm. ok
Dmitriy
@dpogretskiy
Jun 11 2018 18:43
fibs = unfoldr (\(a,b) -> Just (a,(b,a+b))) (0,1)
regular haskell fun stuff
it's almost unreadable, without knowing what it does, but it exists :laughing:
Dmitriy
@dpogretskiy
Jun 11 2018 18:57
@trsh i mean, for your case loop_fn is probably what you need, to just iterate over stuff and do something
but you hardly can actually return something useful out of it