These are chat archives for rust-lang/rust

25th
Jul 2018
Ichoran
@Ichoran
Jul 25 2018 00:56
Is there some tutorial/information/something about using serde_json on JSON objects with duplicate keys?
Brandon Ros
@brandonros
Jul 25 2018 01:28
I have a program that processes messages coming in from a queue in a loop. To process a record consist of some light date/time/basic math logic, and a lot of API calls (HTTP JSON). Is this a good use case for futures + async I/O, or should I just do synchronous and spawn like... 30 threads?
trsh
@trsh
Jul 25 2018 07:42
How do I defined recursive types? let mut json_tree: BTreeMap<String, BTreeMap<String, BTreeMap<...>>> = BTreeMap::new();
It goes into infinity :D
Denis Lisov
@tanriol
Jul 25 2018 08:00
You need an intermediate type like struct Tree(BTreeMap<String, Tree>);, IIUC
Sylwester Rąpała
@xoac
Jul 25 2018 08:34

Hi, I would like to learn how to create macros in rust. I would like to create a macro that helps me creating ref methods on my struct.
let's say this is a body of a macro:

fn $parm _ref(&self) -> & $type {
   &self.$parm
}

what a $parm type should be? Since in a name I need a string that is connected with "_ref()" but in fn body this should be a filed of struct.

macro_rules! ref_methods {
    ($($parm:ident, $type:ty)) => {
    }  
}
And I have a second question is it possible to autodedect $type? so I just type a struct's filed name?
Michal 'vorner' Vaner
@vorner
Jul 25 2018 08:44
@xoac I think you want ident. There's (I think) a macro to concatenate identifiers. And there's no way to autodetect the type from macros-by-example (the ones you're using), but you could use procedural macros/procedural derive to do what you need with annotating the variables you want to share with the outer world.
Sylwester Rąpała
@xoac
Jul 25 2018 08:45
@vorner For now i want use just macros. I will learn in the future how to create custom derive or procedural macrs
Michal 'vorner' Vaner
@vorner
Jul 25 2018 08:46
Yep, I kind of guessed that ‒ just saying there are other possibilities. And there might even be crates for that ‒ if you really need the functionality and don't do it just to learn macros.
Sylwester Rąpała
@xoac
Jul 25 2018 08:48
Macro u mentioned is nightly only and it's looks like it can't be used in my contex https://doc.rust-lang.org/std/macro.concat_idents.html
Akos Vandra
@axos88
Jul 25 2018 08:54

Can I turn on a feature only if the toolchain is nightly, and just leave it off, if it’s not? Currently #![feature(specialization)] will fail the compiler if the toolchain is not nightly (it’s a library, which I would like to have extra features if the using application is compiled for nightly).

Of course the implementations taking care of that will also need to be gated, but that’s fine, it’s just a bunch of implementations for Debug, which are for convenience only:

I’d write something like this:

#[derive(Debug, Eq, PartialEq, Clone, Copy)]
pub enum Validation<T> {
    Ignored,
    Validate(T)
}

#[cfg(feature = "specialization")]
impl<T> Debug for Validation<T> {
    default fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match self {
            Validation::Ignored => write!(f, "Ignored"),
            Validation::Validate(_) => write!(f, "Validated using a value without Debug")
        }
    }
}

I would expect Validation<T> to implement Debug on nightly, and only Validation<T:Debug> on stable.

Sylwester Rąpała
@xoac
Jul 25 2018 08:56
@axos88 As far as I know there is no nightly feature so u need to specify that on your own
trsh
@trsh
Jul 25 2018 08:56
Ok tnx @tanriol
Btw I can't find any good examples, for how to create a Exprt in procedural Macro, depending on some input
Sylwester Rąpała
@xoac
Jul 25 2018 09:07
This what I am doing is probably not worth that work:
macro_rules! ref_method {
    ($parm:ident, $fn_name:ident, $type:ty) => {

        fn $fn_name(&self) -> &$type {
            &self.$parm
        }
    }
}
what a $parm type should?
Akos Vandra
@axos88
Jul 25 2018 12:06
@xoac but can I conditionally include #![feature(specialization)]?
tsoernes
@tsoernes
Jul 25 2018 12:36
Any way to do this with an if let?
if elem.1.is_some() {
            let mut tr = *elem.1.unwrap();
}
// type of elem.1: Option<Box<Tree<T>>>
Andrey Lesnikov
@ozkriff
Jul 25 2018 12:37
Something like if let Some(ref mut tr) = elem.1 { ... }?
Michal 'vorner' Vaner
@vorner
Jul 25 2018 12:37
@axos88 #[(cfg_attribute(feature = "my-feature", feature(specialization))] (or something like that ‒ typing from memory)
tsoernes
@tsoernes
Jul 25 2018 12:46
@ozkriff that gives me &mut std::boxed::Box<Tree<i32>>, not Tree<i32>
it does not seem like ref works for boxes
Michal 'vorner' Vaner
@vorner
Jul 25 2018 12:53
Maybe some .map in there somewhere
Denis Lisov
@tanriol
Jul 25 2018 13:00
@tsoernes Do you really want to take ownership here?
tsoernes
@tsoernes
Jul 25 2018 13:01
yep
Denis Lisov
@tanriol
Jul 25 2018 13:02
And to move the Tree out from the Box?
tsoernes
@tsoernes
Jul 25 2018 13:03
yep
At least I think so. This solution compiles and gives correct answers:
// Note: Your solution should have only one BST traversal and O(1) extra space complexity, since this is what you will be asked to accomplish in an interview.
// A tree is considered a binary search tree (BST) if for each of its nodes the following is true:
//    The left subtree of a node contains only nodes with keys less than the node's key.
//    The right subtree of a node contains only nodes with keys greater than the node's key.
//    Both the left and the right subtrees must also be binary search trees.
// Given a binary search tree t, find the kth smallest element in it.
//
// Definition for binary tree:
// struct Tree<T> {
//     value: T,
//     left: TreeNode<T>,
//     right: TreeNode<T>
// }
// impl<T> Tree<T> {
//     fn new(v : T) -> Tree<T> {
//         Tree { value: v, left: None, right: None }
//     }
// }
// type TreeNode<T> = Option<Box<Tree<T>>>;

fn kthSmallestInBST(t: TreeNode<i32>, k: i32) -> i32 {
    let kk = k as usize;
    let mut stack: Vec<(i32, TreeNode<i32>)> = Vec::new();
    let mut tr = *t.unwrap();
    stack.push((tr.value, tr.right));
    // Go to the minimum element
    while tr.left.is_some() {
        tr = *tr.left.unwrap();
        stack.push((tr.value, tr.right));
    }
    // In order traversal
    let mut popped = 0;
    while let Some(elem) = stack.pop() {
        popped += 1;
        if popped == k {
            return elem.0;
        }
        if elem.1.is_some() {
            let mut tr = *elem.1.unwrap();
            stack.push((tr.value, tr.right)); 
            while tr.left.is_some() {
               tr = *tr.left.unwrap();
               stack.push((tr.value, tr.right)); 
            }
        }
    }
    0
}
I don't know if its good rust code or not
Denis Lisov
@tanriol
Jul 25 2018 13:07
This function definitely should not take ownership of the tree. Do you really expect that you're asked to find the kth smallest value in the BST and drop all other values?
tsoernes
@tsoernes
Jul 25 2018 13:08
Well, not really, but the function signature declaration was not decided by me, instead given as a fixed template for an online exercise
which runs automatic tests on the function. That said I would be interested to know how to solve it without taking ownership
Denis Lisov
@tanriol
Jul 25 2018 13:12
Hmm. Is this some public site?
tsoernes
@tsoernes
Jul 25 2018 13:13
Yes. https://app.codesignal.com/ -> interview practice -> trees -> kthsmallstinbst
Although you might have to progress to unlock the exercise ..
tsoernes
@tsoernes
Jul 25 2018 13:18
If I have a Some<Box<i32>> then I own the value, but if I have a Box<Some<i32>> then I don't?
Denis Lisov
@tanriol
Jul 25 2018 13:18
...on the other hand, you won't be able to pass the requirements with a reference only, IIUC... by the way, your solution does not fit the requirements stated on top.
tsoernes
@tsoernes
Jul 25 2018 13:19
the space complexity requirement is not satisfied due to the stack; I have no idea how to fix that
Zakarum
@omni-viral
Jul 25 2018 13:21
Does anyone know some algorithm for 1D packing problem with set of object pairs that can overlap?
Michal 'vorner' Vaner
@vorner
Jul 25 2018 13:23
@tsoernes My whole impression from that exercise is that the author has no idea what they talk about. Or, alternatively, it's a catch and you should notice the fact you are allowed to deconstruct the tree and therefore you can abuse its own space during the traversal ‒ like keep rebuilding it during it. You could, for example, try to flatten the tree into a linked list using rotations or something like that. But for DFS traversal of a tree with O(1) space, you need parent pointers.
tsoernes
@tsoernes
Jul 25 2018 13:28
@vorner Apparantly, it is possible (in general, I don't know about in safe rust) to traverse it with O(1) space using a Morris inorder traversal: https://www.geeksforgeeks.org/inorder-tree-traversal-without-recursion-and-without-stack/
Michal 'vorner' Vaner
@vorner
Jul 25 2018 13:30
Yes, but it destroys the tree doing that ‒ which is what I was saying. Somehow abuse its own space to traverse it.
Hmm. They may even be returning it to the previous state. But it still feels like an abuse I wouldn't like to see in any production code.
tsoernes
@tsoernes
Jul 25 2018 13:34
The morris traversal apparantly returns the tree to its original state, but traverses it (at most) 3 times, which violates a problem constraint. But ignore that -- is there any way to make my solution (DFS traversal with stack) work with without taking ownership?
Michal 'vorner' Vaner
@vorner
Jul 25 2018 13:35
It should be. Just use references to the nodes.
tsoernes
@tsoernes
Jul 25 2018 13:38
Are not boxes already references? Instead of storing Option<Box<Tree<i32>>> in the stack, what should be there?
I've tried &Option<Box<Tree<i32>>> but get errors I can't figure out; maybe instead it should be Box<Option<Tree<i32>>>, but I don't know how to get a Box<Option<Tree<i32>>> from aOption<Box<Tree<i32>>>
Michal 'vorner' Vaner
@vorner
Jul 25 2018 13:55
Boxes are owning pointers. References = borrows. And you probably want something like &Tree<i32> or Option<&Tree<i32>>
Denis Lisov
@tanriol
Jul 25 2018 13:58
And the requirements also mention "only one BST traversal", which I believe to be not really possible (for an unbalanced tree with no right children, you'll have to do one full traversal to find the smallest element and then chase parent pointers (that you've hackishly put somewhere) to the element we need, which may easily be the biggest one, so one more traversal)
tsoernes
@tsoernes
Jul 25 2018 14:15
This gives right results (ignore the space complexity constraint), but can it be simplified/cleaned up?
struct Tree<T> {
    value: T,
    left: TreeNode<T>,
    right: TreeNode<T>,
}
impl<T> Tree<T> {
    fn new(v: T) -> Tree<T> {
        Tree {
            value: v,
            left: None,
            right: None,
        }
    }
}
type TreeNode<T> = Option<Box<Tree<T>>>;

fn kthSmallestInBST(t: TreeNode<i32>, k: i32) -> i32 {
    let kk = k as usize;
    kthSmallestInBST_(&t, kk)
}

fn kthSmallestInBST_(t: &TreeNode<i32>, k: usize) -> i32 {
    let mut stack: Vec<(i32, Option<&Box<Tree<i32>>>)> = Vec::new();
    let mut tr: &Tree<i32> = match t {
        Some(tr) => &*tr,
        None => panic!(""),
    };
    let tr_right = match tr.right {
        Some(ref trr) => Some(trr),
        None => None,
    };
    stack.push((tr.value, tr_right));
    // Go to the minimum element
    while let Some(ref trl) = tr.left {
        tr = trl;
        let tr_right = match tr.right {
            Some(ref trr) => Some(trr),
            None => None,
        };
        stack.push((tr.value, tr_right));
    }
    // In order traversal
    let mut popped = 0;
    while let Some(elem) = stack.pop() {
        popped += 1;
        if popped == k {
            return elem.0;
        }
        if elem.1.is_some() {
            let mut tr = elem.1.unwrap();
            let tr_right = match tr.right {
                Some(ref trr) => Some(trr),
                None => None,
            };
            stack.push((tr.value, tr_right));
            while let Some(ref trl) = tr.left {
                tr = trl;
                let tr_right = match tr.right {
                    Some(ref trr) => Some(trr),
                    None => None,
                };
                stack.push((tr.value, tr_right));
            }
        }
    }
    0
}

Particularly the

let tr_right = match tr.right {
        Some(ref trr) => Some(trr),
        None => None,
    };

Seems very verbose. Are we not just moving the reference from outside to inside the option?

Denis Lisov
@tanriol
Jul 25 2018 14:20
Option::as_ref?
tsoernes
@tsoernes
Jul 25 2018 14:24
Yes, found it. I think the docs are wrong though, which says Converts from Option<T> to Option<&T>. should probably be Converts from &Option<T> to Option<&T>. instead
Denis Lisov
@tanriol
Jul 25 2018 14:25
The Self for it is Option<T>
Ichoran
@Ichoran
Jul 25 2018 18:21
I have some JSON that can be edited by users and saved without an opportunity for extensive error-checking; it will be properly formatted JSON but otherwise may have problems like duplicate keys. serde_json simply throws away duplicates without a trace:
extern crate serde_json;

use serde_json::{Value, Error};

fn main() {
    let input = r#"{ "name": "John Doe", "name": true }"#;

    let v: Result<Value, Error> = serde_json::from_str(input);
    println!("{:?}", v);
}
gives
Ok(Object({"name": Bool(true)}))
Is there some standard way to deal with this and at least get an Error instead of just silently discarding data?
red75prime
@red75prime
Jul 25 2018 18:27
One and maybe the one solution is to use strongly typed deserialization https://play.rust-lang.org/?gist=b7e0dc292f7ea2e19d3eefa79780479a&version=stable&mode=debug&edition=2015
Ichoran
@Ichoran
Jul 25 2018 18:31
Unfortunately, that won't work, as the user is allowed to define arbitrary keys.
Ichoran
@Ichoran
Jul 25 2018 18:39
No, because they will duplicate their own keys and not realize it.
Because users are users and not computers :P
These are not even programmers; these are end-users interacting with a UI.
I'm very reluctant to change the data format (e.g. I could make everything be [["name", "John"], ["name", true]] and sort it out later) because I have four programming languages all interacting with this data.
red75prime
@red75prime
Jul 25 2018 18:41
Well, then removal of text editor field in UI, or a PR into serde_json are the options.
Ichoran
@Ichoran
Jul 25 2018 18:42
Is there a tutorial for writing, by hand, custom deserializers?
I couldn't find anything, but I'm happy to write my own as long as I can get my hands on the right stream of data.
Ichoran
@Ichoran
Jul 25 2018 18:43
Oh, huh. How did I not find that? Thanks!
I guess I could just deserialize the whole tree into a PermissiveValue enum and then impl TryFrom<PermissiveValue> for Value
Kaiyin Zhong
@kindlychung
Jul 25 2018 20:45
fn main() {
    let s1 = "aa";
    let s;
    {
        let s2 = "aaa";
        s = longest(&s1, &s2);
    }
    println!("{}", s);
}

fn longest<'a>(x: &'a str, y: &'a str) -> &'a str {
    if x.len() > y.len() {
        x
    } else {
        y
    }
}
How come this code compiles and runs?
red75prime
@red75prime
Jul 25 2018 20:47
Both str's have 'static lifetime.
Type of string literal is &'static str
Kaiyin Zhong
@kindlychung
Jul 25 2018 20:48
Yep.
Thanks.
Matthias Berndt
@mberndt123
Jul 25 2018 21:29
I don't get std::ptr::Unique. It seems to be exactly what I need, and yet when I try to use it, I'm told to use NonNull instead. How is that a replacement for Unique? It seems completely different.
Matthias Berndt
@mberndt123
Jul 25 2018 21:41
Also, how can I use an experimental feature? For this toy I'm messing around with I don't really care if it breaks at some point
Sylwester Rąpała
@xoac
Jul 25 2018 21:42
Is &Option<T> and Option<&T> the same?
Ichoran
@Ichoran
Jul 25 2018 21:44
No, they are as different as they look. One is an immutable borrow of an option that might own a T; the other might have immutably borrowed a T.
There are some cases where you could have your API use either, but the meaning isn't the same.
(Either way, you can only maybe get your T, and either way someone else is responsible for cleaning it up.)
Sylwester Rąpała
@xoac
Jul 25 2018 21:46

If I have a struct:

struct Test {
  param: Option<u32>,
}

How should I return reference? As Option<&u32> or &Option<u32>?

Ichoran
@Ichoran
Jul 25 2018 21:47
I would tend to use &Option<u32> because you just are referring to what's already there. But it depends on context.
red75prime
@red75prime
Jul 25 2018 21:48
OTOH, Option<&u32> has exactly the same size as &u32, non-nullable value optimization
Sylwester Rąpała
@xoac
Jul 25 2018 21:49
u32 is just example. Let's think it's &T
@Ichoran I did your version. And now I am in a little trouble
I have a parent parameter in my struct. (parent: Option<Rc<MyStruct>>)
Matthias Berndt
@mberndt123
Jul 25 2018 21:51
@xoac it depends on what you want to do with the reference. For instance, &mut Option<u32> will allow you to set param to None, while Option<&mut u32> will only allow you to change the value in the Option if there is one
Sylwester Rąpała
@xoac
Jul 25 2018 21:54
and now I want to call a function param_ref() like this:
fn parm_ref(&self) -> &Option<u32> {
  self.parm.as_ref().or( /*here check if parents has that parm value and if return it*/ )
}
but as_ref() return Option<&T>
Sylwester Rąpała
@xoac
Jul 25 2018 21:59
@mberndt123 You are right. I should answer that question. And I think I need return &mut
but if we consider immutable &Option<T> and Option<&T> there is no usable difference.. I guess.
Ichoran
@Ichoran
Jul 25 2018 22:02
Not semantically. The compiler has to care, and the performance characteristics might be different.
Sylwester Rąpała
@xoac
Jul 25 2018 22:03
I don't care about performance at this moment.
Matthias Berndt
@mberndt123
Jul 25 2018 22:04
@xoac I would start out with Option<&mut T> because it allows you to do less than &mut Option<T>. If it turns out you need the additional possibilities of the latter, you can change it later.
Sylwester Rąpała
@xoac
Jul 25 2018 22:09
I think example would be better than explaining my problem with my English
@mberndt123 Good point. But I need allow to change Some(T) to None. And I think metod_mut() would be a good place to do it
Matthias Berndt
@mberndt123
Jul 25 2018 22:11
if you need that, then you need &mut Option<T>
Sylwester Rąpała
@xoac
Jul 25 2018 22:12
Yes but I am not sure how to force and_then to return &Option<T>
Of coure I need it replace with sth else but I don't know with what :)
Ichoran
@Ichoran
Jul 25 2018 22:16
That won't work, because you're constructing a new Option and you want someone else to own it. So it needs to be Option<&T>

If, for instance, you change things to

    pub fn parm_with_parent_check_ref(&self) -> Option<u32> {
        self.parent.clone().and_then(|parent| *parent.parm_ref())
    }

then it compiles, at least. Whether it will keep doing so when you move to your real use-case, I'm not sure.

Sylwester Rąpała
@xoac
Jul 25 2018 22:21
You remove reference from return type
There will be no parm_with_parent_check_mut() function