These are chat archives for rust-lang/rust

20th
Jul 2018
Kiara Rusavi
@rusavi
Jul 20 2018 01:00
how can i increment across threads?
tsoernes
@tsoernes
Jul 20 2018 02:02
Any tips on this?
let mut reachable: HashMap<i32, HashSet<i32>> = ..
let mut k_reach: HashSet<i32> = 
let i = ..
k_reach = reachable.get(&i).unwrap().clone().union(&k_reach).collect();
a collection of type `std::collections::HashSet<i32>` cannot be built from an iterator over elements of type `&i32`
Dmitriy
@dpogretskiy
Jul 20 2018 06:15
@tsoernes you trying to put references to integers into set
you can map(|a| a.clone()) them for example
bunch of stuff really
Kelly Thomas Kline
@kellytk
Jul 20 2018 06:28
I have a syntax question; at https://github.com/DenisKolodin/yew/blob/82b0b588bf09d9b8899c5f77bd9995f2df5d702b/src/services/websocket.rs#L53 what does <WebSocketStatus> signify? IIUC Callback is a function. Is WebSocketStatus the function's return value?
trsh
@trsh
Jul 20 2018 06:41
wtf? -> expected enum serde_json::value::Value, found enum serde_json::Value ?
:D
Akos Vandra
@axos88
Jul 20 2018 06:46
Given an Arc<Option<T>> can I return an Arc<T>, if the option is Some?
Dmitriy
@dpogretskiy
Jul 20 2018 06:49
not really
only if you clone T
Dmitriy
@dpogretskiy
Jul 20 2018 06:59
use std::ops::Deref;
use std::sync::Arc;

fn rewrap<T: Clone>(data: Arc<Option<T>>) -> Result<Arc<T>, ()> {
    match data.deref() {
        Some(d) => Ok(Arc::new(d.clone())),
        None => Err(()),
    }
}

fn main() {
    let foo = Arc::new(Some(vec![1, 2, 3]));
    let arc2 = rewrap(foo.clone());

    println!("{:?}, {:?}", foo, arc2);
}
Akos Vandra
@axos88
Jul 20 2018 07:00
right, that’s what i want to avoid :|
Dmitriy
@dpogretskiy
Jul 20 2018 07:01
then you have 2 arcs that point to same memory
use after free, here we go :)
well, there is something that may work
Akos Vandra
@axos88
Jul 20 2018 07:02
What would be a better option to store the result for a computation cache / memoiziation that could be used from multiple threads?
Dmitriy
@dpogretskiy
Jul 20 2018 07:03
Arc is fine, but it's not mutable
then you need to put into multiple threads somehow
Akos Vandra
@axos88
Jul 20 2018 07:04
Meaning I would have a struct Cache(T) and I would like to call a Cache.fetch( || { expensive_operation_future }) that would memoize the value
Dmitriy
@dpogretskiy
Jul 20 2018 07:04
so it should be lazy, but globally available?
Akos Vandra
@axos88
Jul 20 2018 07:04
yeah
:)
Dmitriy
@dpogretskiy
Jul 20 2018 07:05
and do some IO on the way in, i presume?
Akos Vandra
@axos88
Jul 20 2018 07:06
exactly, it’s fetching with a future, from a HttpRequest
:D
Michal 'vorner' Vaner
@vorner
Jul 20 2018 07:06
@axos88 (shameless ads for my crate) https://docs.rs/arc-swap/0.2.0/arc_swap/?
Ah, you'd still have to do something about the future…
Akos Vandra
@axos88
Jul 20 2018 07:06
This is my current approach
    pub fn fetch_jwks(&self) -> impl Future<Item=JWKSet<Empty>, Error=Error> {
        FutOk(unimplemented!())
    }

    pub fn jwks(&mut self) -> Box<Future<Item=Arc<JWKSet<Empty>>, Error=Error>> {
        match self.jwks {
            Some(ref data) => Box::new(FutOk(data.clone())),
            None => {
                let jwks = self.fetch_jwks();

                let mut cache = self.jwks.clone();

                Box::new(jwks.map(move |r| {
                    cache.get_or_insert(r);
                    self.jwks.clone();
                }))
            }
        }
    }
   jwks: Arc<Option<JWKSet<Empty>>>,
ofc it doesn’t work, but you probably get the idea what I want to achieve
Dmitriy
@dpogretskiy
Jul 20 2018 07:09
well, accessing something that is explicitly synchronized, like Mutex is gonna slow everything quite a bit
Akos Vandra
@axos88
Jul 20 2018 07:09
well it should only be written once, and readlocks are fast, aren’t they?
Dmitriy
@dpogretskiy
Jul 20 2018 07:10
if it's mutex, it's one user at a time, Arc is faster tho
but it's create once
Akos Vandra
@axos88
Jul 20 2018 07:10
I already thought using RWLock
Michal 'vorner' Vaner
@vorner
Jul 20 2018 07:11
That crate I've shown is basically a crossbreed of Arc and AtomicPtr
Akos Vandra
@axos88
Jul 20 2018 07:13
I’ll check that out
trsh
@trsh
Jul 20 2018 08:52
Hi. How could I convert std::vec::Vec<std::boxed::Box<SomeErrTypeThatHasToStringMethod>> to Vec<String> ?
CrLF0710
@crlf0710
Jul 20 2018 08:53
.into_iter().map(<do convert here>).collect()
Dmitriy
@dpogretskiy
Jul 20 2018 08:53
@trsh .into_iter().map(|a| a.to_string()).collect() ?
trsh
@trsh
Jul 20 2018 08:56
But how to I loose The BOX?
that I have to iter, is clear
Ok, this worked
let str_errors = validation_state.errors.into_iter().map(|x| {
      (*x).to_string()
    }).collect::<Vec<_>>();
tsoernes
@tsoernes
Jul 20 2018 13:54
@dpogretskiy you mentioned there where other ways to fix the problem below besides cloning elements inside a map. Which? And why does not clone work below?
let mut reachable: HashMap<i32, HashSet<i32>> = ..
let mut k_reach: HashSet<i32> = 
let i = ..
k_reach = reachable.get(&i).unwrap().clone().union(&k_reach).collect();
a collection of type `std::collections::HashSet<i32>` cannot be built from an iterator over elements of type `&i32`
Dmitriy
@dpogretskiy
Jul 20 2018 13:56
k_reach = reachable.get(&i).unwrap().union(&k_reach).iter().map(|a| a.clone()).collect(); should work
union returns an iter right?
tsoernes
@tsoernes
Jul 20 2018 13:56
yes
Brandon Ros
@brandonros
Jul 20 2018 13:56
How does one call std::task::Executor::spawn_obj from main()?
Dmitriy
@dpogretskiy
Jul 20 2018 13:56
then you clone elements of an iter
not element you get, since it doesn't do anything really
tsoernes
@tsoernes
Jul 20 2018 14:02
That seems to work. Why are the elements of the iterator of type &i32 instead of i32? I though the return type of reachable.get(&i).unwrap().clone() would be HashSet<i32>
Dmitriy
@dpogretskiy
Jul 20 2018 14:02
yup, but then you union it
there it's borrowed again
and &k_reach is always borrowed
and after all, iter's lend you items almost always
it's not particularly useful in case of primitives as &i32 is twice as big as i32 itself, but it is what it is
into_iter() works, but it's nowhere to use in your case
tsoernes
@tsoernes
Jul 20 2018 14:05
is that stuff fixed by the compiler?
like fusion
Dmitriy
@dpogretskiy
Jul 20 2018 14:06
not compiler, just library
iter's are that way
you can make your own implementations for such iters if you really want to :)
tsoernes
@tsoernes
Jul 20 2018 14:20
Any idea how to pop from hashset?
fn pop<K: Eq + Hash>(hset: &mut HashSet<K>) -> K {
   let i = hset.iter().next().unwrap().clone(); 
   hset.remove(i);
   *i
   // cannot move out of borrowed content
   // cannot borrow `*hset` as mutable because it is also borrowed as immutable 
}
Lyle Mantooth
@IslandUsurper
Jul 20 2018 14:32
@tsoernes, use hset.take(i) instead, which should return Some(i).
And then you can probably get rid of the clone because take() takes a reference.
tsoernes
@tsoernes
Jul 20 2018 14:33
@IslandUsurper that removes 1 error, but i still get cannot borrow*hsetas mutable because it is also borrowed as immutable
Lyle Mantooth
@IslandUsurper
Jul 20 2018 14:34
OK, you'll probably still need the clone
let i = { hset.iter().next().unwrap().clone() };
hset.take(i).unwrap()
The braces should keep the scope of the borrow contained. I think.
(I suspect NLL would let you do this already, but on stable you have to play games.)
tsoernes
@tsoernes
Jul 20 2018 14:37
same error :/
Lyle Mantooth
@IslandUsurper
Jul 20 2018 14:43
@tsoernes how about this?
fn pop<K: Eq+Hash>(hset: &mut HashSet<K>) -> K {
    let tmp = hset.drain();
    let ret = tmp.next().expect("empty set");
    *hset = tmp.collect();
    ret
}
I would return an Option<K>, though, and just let ret = tmp.next();
red75prime
@red75prime
Jul 20 2018 14:48
drain() borrows hset.
The problem isn't solvable without either K: Clone, or HashBuilder: Default, or unsafe
tsoernes
@tsoernes
Jul 20 2018 14:56
k clone is fine
Lyle Mantooth
@IslandUsurper
Jul 20 2018 14:57
fn pop<K: Eq+Hash+Clone>(hset: &mut HashSet<K>) -> Option<K> {
    let i = {hset.iter().next().unwrap().clone()};
    hset.take(&i)
}
tsoernes
@tsoernes
Jul 20 2018 14:58
The braces as not necessary.
red75prime
@red75prime
Jul 20 2018 14:58
if let Some(k) = hset.iter().next().cloned() {
    hset.take(&k)
} else {
    None
}
Lyle Mantooth
@IslandUsurper
Jul 20 2018 14:58
take() returns an Option already
red75prime
@red75prime
Jul 20 2018 14:58
unwrap will panic on empty set
tsoernes
@tsoernes
Jul 20 2018 14:58
Why is the error "// cannot borrow *hset as mutable because it is also borrowed as immutable" instead of "K does not implement Clone" or something to that extend?
Lyle Mantooth
@IslandUsurper
Jul 20 2018 14:59
Mm, good point.
tsoernes
@tsoernes
Jul 20 2018 15:00
And why does not the .clone() function call yield an error when the Clone is not included in function sig?
red75prime
@red75prime
Jul 20 2018 15:01
It does create compiler error. Everything the compiler knows about K is that it implements Eq and Hash
Ichoran
@Ichoran
Jul 20 2018 15:03
You can clone a reference. That's probably what was going on in places where it worked and seemed to be a clone of K.
tsoernes
@tsoernes
Jul 20 2018 15:12
There are many online coding challenges/puzzles, like hackerrank and codesignal, which have automated tests that check your solution, some of which support Rust. Are there any offline? That is, does anyone know of a repo with challenges/tasks and corresponding checks?
and another question; what's the difference between clone() and cloned() in the two code snippets form @IslandUsurper and @red75prime above?
Lyle Mantooth
@IslandUsurper
Jul 20 2018 15:15
Option::cloned() gives you Some(inner.clone()) or None. It's better than unwrap().clone() because it won't panic on None.
Though the Option needs to contain a reference for it to work.
tsoernes
@tsoernes
Jul 20 2018 15:24
when does clone() clone the reference instead of the value?
trsh
@trsh
Jul 20 2018 15:29
How can I check, pragmatically if a struct has a certain field, and if it odes, assign it? Or it's not Rust thing?
Dmitriy
@dpogretskiy
Jul 20 2018 15:31
you make this struct a HashMap instead, and use entry api :)
maybe Any will work, but i never used it, so don't even know what it does.
red75prime
@red75prime
Jul 20 2018 15:32
@trsh It is for dynamically typed languages or languages with runtime reflection. In Rust you can create a trait and implement it for required structures.
Ichoran
@Ichoran
Jul 20 2018 15:33
@tsoernes - I am not 100% sure how the type inference interacts with auto-dereferencing there, TBH.
red75prime
@red75prime
Jul 20 2018 15:33
Other solutions are possible, of course.
red75prime
@red75prime
Jul 20 2018 15:42
@tsoernes a bit of dot magic is involved. let a = 1; let b = Clone::clone(a); doesn't compile. But let b = a.clone() works. . (dot operator) can implicitly take reference if it is required. So a.clone() and (&a).clone() do the same thing, they call Clone::clone(&a). You need (&&a).clone() to clone reference.
Ichoran
@Ichoran
Jul 20 2018 15:52

Yes, it's the extent of the magic that I'm not totally clear on either.

fn test<K>(k: K) {
    let q = &k;
    let kk = k.clone();   // Nope
    let qq = q.clone();
    let x: K = q.clone(); // Nope
}

fn test2<K: Clone>(k: K) {
    let q = &k;
    let kk = k.clone();
    let qq = q.clone();
    let x: K = q.clone();
}

In test one, qq only works if it's the reference, not K, which is being cloned. So it's certainly fine to clone a reference. But I'm less clear about what's going on with qq and x in test2, as there are multiple ways it could work.

tsoernes
@tsoernes
Jul 20 2018 15:53
are qq in test1 and test2 the same type?
Ichoran
@Ichoran
Jul 20 2018 15:56
I'm also not sure how to test that. Deref magic plus type inference has thus far defeated my attempts to find out.
But I haven't tried very hard.
James McCoy
@jamessan
Jul 20 2018 16:58
@tsoernes Have you looked at exercism.io? You need to be online to get a exercise, but the exercise comes with its own set of tests, so you do your local development to solve it and run the included tests. Once you've finished it, you can submit it and get another one
tsoernes
@tsoernes
Jul 20 2018 17:19
@jamessan I want local tests to avoid copying and pasting the code from editor to browser every time you want to run the tests (or just get input data)
James McCoy
@jamessan
Jul 20 2018 17:19
Yes, they are local
Akos Vandra
@axos88
Jul 20 2018 17:19
has anyone experienced that all compiler output is reported twice in IntelliJ?
tsoernes
@tsoernes
Jul 20 2018 17:19
it does look like it should be possible with exercism though, as they have a github repo https://github.com/exercism/rust/tree/master/exercises
thank you
Kelly Thomas Kline
@kellytk
Jul 20 2018 22:58
In Foo::<Bar>::new(); what is Bar to Foo?
Robin Miller
@grenewode
Jul 20 2018 23:00
@k0pernicus Bar is a generic parameter to Foo.
So for example, if you want a vector of u32, you can say Vec::<u32>::new()
The reason you usually see Vec::new() is that the Rust compiler is often smart enough to deduce the generic parameter from context.
Kelly Thomas Kline
@kellytk
Jul 20 2018 23:04
Is ::<Bar> the turbofish?
Robin Miller
@grenewode
Jul 20 2018 23:04
Yeah
Kelly Thomas Kline
@kellytk
Jul 20 2018 23:05
Thank you
Robin Miller
@grenewode
Jul 20 2018 23:06
Kelly Thomas Kline
@kellytk
Jul 20 2018 23:09
+1