I'm new to rust. I need to get a list of files and directories in a folder, however I can't access the iteration object more than once.
Of course, this can be done using else, but I would like to know what to do in such a situation.
for d in fs::read_dir("./").unwrap() {
if d.unwrap().path().is_dir() {
continue;
} else if d.unwrap().path().is_file() { //except here
continue;
}
I'm new to rust. I need to get a list of files and directories in a folder, however I can't access the iteration object more than once.
You can understand why, and how to fix it, by looking at the documentation. Specifically the self types:
read_dir returns an iterator of Result<DirEntry>, so that's what d is.
Result::unwrap takes self, so it consumes the result itself, meaning after the first call to d.unwrap() there is no d anymore.
Your solutions then are:
since path, is_dir, and is_file all take &self as ShadowRanger notes you can just store the unwrapped DirEntry, or the paths
alternatively, you can use Result::as_ref to get a Result<&DirEntry>, which you can then unwrap to get an &DirEntry of which you can get the path, this only needs a &Result, so it does not consume the Result itself
Related
Sample code :
use serde_json::{json, Value};
fn main() {
let a: Rc<RefCell<Value>> = Rc::new(RefCell::new(json!({"a": "value"})));
let v: Rc<RefCell<Vec<Value>>> = Rc::new(RefCell::new(vec![]));
// How to push a into v, but keep `a` and `v` for future uses
}
I want to push Value a into vector v (link pointer), but still be able to use a later on.
I've tried the following:
1.
v.borrow_mut().push(*a.borrow_mut());
This does not work, as Value does not implement Copy trait, thus could not be dereferenced
2.
v.borrow_mut().push(RefCell::take(&a));
This works, however a has now lost the contents. I do understand that there should only be one owner, but I'm not sure how to achieve what I need.
The Why
I have a Value which I need to modify depending on some other data which is in a tree structure. I want to recursively walk through that other data tree, and pass along this Value to be modified.
In my function, I have this Value signature as Rc<RefCell<Value>>, and depending on the case I sometimes need to add nested properties, so I may need to add a property containing a vector with a new json!({}), and pass it as a new Rc<RefCell<Value>> to sub-iterations to append data to this specific subtree.
So, if you have any advice - maybe I need to change the recursive function's signature to have this data as Rc<RefCell<&Value>> instead, to have only one owner ? That seems like an awful lot of all sorts of references stacked upon one another, not sure which is the good way
Edit1: Updated sample to include Rc<RefCell<_>>
When implementing a custom NSMergePolicy, there are 3 functions available to overload:
final class MyMergePolicy: NSMergePolicy {
override func resolve(mergeConflicts list: [Any]) throws {
// ...
try super.resolve(mergeConflicts: list)
}
override func resolve(optimisticLockingConflicts list: [NSMergeConflict]) throws {
// ...
try super.resolve(optimisticLockingConflicts: list)
}
override func resolve(constraintConflicts list: [NSConstraintConflict]) throws {
// ...
try super.resolve(constraintConflicts: list)
}
}
Documentation for all 3 is exactly the same, it says: "Resolves the conflicts in a given list.", and I can't seem to find much information online.
What's the difference between these functions? What are the appropriate use cases for each of them?
The documentation kind of sucks here but you can get a partial explanation by looking at the arguments the functions receive.
resolve(optimisticLockingConflicts list: [NSMergeConflict]): Gets a list of one or more NSMergeConflict. This is what you'll usually hear about as a merge conflict, when the same underlying instance is modified on more than one managed object context.
resolve(constraintConflicts list: [NSConstraintConflict]): Gets a list of one or more NSConstraintConflict. This happens if you have uniqueness constraints on an entity but you try to insert an instance with a duplicate value.
The odd one out is resolve(mergeConflicts list: [Any]). This one is basically a leftover from the days before uniqueness constraints existed. It gets called for both types of conflict described above-- but only if you don't implement the more-specific function. So for example if you have a constraint conflict, resolve(constraintConflicts:...) gets called if you implemented it. If you didn't implement it, the context tries to fall back on resolve(mergeConflicts list: [Any]) instead. The same process applies for merge conflicts-- the context uses one function if it exists, and can fall back on the other. Don't implement this function, use one of the other two.
For both conflict types, the arguments give you details on the conflict, including the objects with the conflict and the details of the conflict. You can resolve them however you like.
Question is general, no particular example.
If we have a function that returns a closure and closure itself returns some captured variable, does that variable type have to implement Copy˙trait?
From documentation:
https://doc.rust-lang.org/rust-by-example/fn/closures/output_parameters.html
fn create_fn() -> impl Fn() {
let text = "Fn".to_owned();
move || println!("This is a: {}", text)
}
this works, but for some types this solution give error. For example, if a text would be of type Option<T> it returns error saying something like:
`move occurs because `text` has type `std::option::Option<Box<dyn Something>>`, which does not implement the `Copy` trait
captured by this `Fn` closure`
One solution to solve the error is either to change closure trait to FnOnce but that introduces restriction that closure can be called only once.
But, if we want to call it multiple times, does that necessarily means that text must implement Copy trait?
I thought that move keyword does exactly that but i'm obviously wrong so if someone could explain details about how this moving captured variables actually works?
No, the type must not necessarily implement Copy. The thing is, when you have a Fn, it must be callable several times. If you actually move out something, then it's not going to work unless you're not actually moving it but just copying it (thus the error). But, the important thing is, you're not necessarily moving something out. You could also, for instance, create it on the fly (well, technically speaking, you'd still be moving it out, but maybe the example will help).
fn create_fn() -> impl Fn() -> String {
let text = "something";
move || text.to_string()
}
(see the playground)
Note that, here, String does not implement Copy (and it could also not implement Clone). What makes it work is that this function can be called over and over again, because each time it won't move out something it will need in a future call (here, by creating a brand new String to be given out).
But, if you're moving out a captured variable, you won't be able to do that twice. In that specific case, it would have to implement Copy (or just Clone and then you'd have to .clone() it).
I'm using the cursive_table_view crate, and the table has a set_on_submit method to which you pass a closure to be executed when the user press over a selected row in the table. The signature of said method is:
pub fn set_on_submit<F>(&mut self, cb: F)
where
F: Fn(&mut Cursive, usize, usize) + 'static,
Inside the closure, I'm trying to use something that actually comes as a parameter in the function that contains this code. I simply declare that parameter as &'static, and that's all good and expected. Now of course, I've just moved the problem to the caller of my function.
fn my_function(param: &'static MyType) {
let table = TableView::new();
table.set_on_sumbit(|cur, row, index| {
do_something_with(param);
}
}
Eventually I get to a point where I have to declare my variable as static to pass it as a parameter to that function, but because I need to modify this variable before the call (and after declaration), it needs to be static mutable. Now the problem is, when I try to modify the variable, the compiler says that I can only do that with unsafe.
I believe I understand the why of everything above. The closure is going to be called upon some event in the UI, so it makes sense that this lives for as long as the entire program.
I've tried several options with Rc and read a ton about lifetimes and even threads and messages, but I felt I was blindly trying things without really understanding at some point. Where I'm at now is that I believe I understand, but I'm uncomfortable with having to go the unsafe route suggestion.
Is it avoidable? Is my pattern wrong to begin with?
I didn't want to add more code to keep the explanation agnostic to everything else, but of course I'm happy to edit if more code helps understand the issue. Also, I don't really need to modify the struct any longer by the time I've passed the reference to the closure, in case that helps find a solution down that path.
Think of references as mostly (excluding &'static and a few other cases) being for temporary things, especially temporary things that live only as long as a stack frame. Therefore, don't try to use references for things like user interface callbacks.
Here's how to use std::rc::Rc instead, which ensures that the data lives as long as needed.
use std::rc::Rc;
fn my_function(param: Rc<MyType>) { // changed parameter type
let table = TableView::new();
table.set_on_submit(|cur, row, index| {
do_something_with(¶m); // & enables conversion to &MyType
}
}
Now, in order to use this, you need to arrange so your data is owned by the Rc. It is not possible to have the above sort of callback and also have let data = MyType {...} directly, because the data must be owned by the Rc. (However, if useful, you can initialize it and then later put it in the Rc.)
fn main() {
// Wrap it as soon as you construct it.
// (Or at least before you start using callbacks.)
let my_app_data = Rc::new(MyType {
// whatever fields or constructor...
});
// Call the function. `.clone()` here makes a copy of the `Rc` refcounted pointer,
// not the underlying data.
my_function(my_app_data.clone());
}
If your program uses threads, then you must use the thread-safe reference counter std::sync::Arc instead of Rc.
If you want to modify the data while the callback exists — whether in a callback or elsewhere — you need to also use RefCell (or thread-safe std::sync::Mutex / RwLock) inside the Rc, which adds a few complications.
Assume we have a struct capable of self-mutation that has to happen as part of a background operation:
struct Thing {
var something = 0
mutating func operation(block: () -> Void) {
// Start some background operation
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0)) {
// Mutate self upon background task completion
self.something += 1
block()
}
}
}
Now, when I use such a struct in context:
var myThing = Thing()
myThing.operation {
println(myThing.something)
}
The println gives me 0, as if myThing was never mutated. Printing self.something from within the dispatch_async obviously yields 1.
How do I work around this issue, preferably without having to pass the updated struct's self in the operation competition block and overriding the original variable in the main context?
// Ew
var myThing = Thing()
myThing.operation {
(mutatedThing) in
myThing = mutatedThing
println(myThing.something)
}
I'm adding a second answer because my first answer addressed a different point.
I have just encountered this difficulty myself in circumstances almost identical to yours.
After working and working and working to try to find out what was going on, and fix it, I realized that the problem was, basically, using a value type where a reference type should be used.
The closure seems to create a duplicate of the struct and operate on that, leaving the original untouched--which is more in line with the behavior of a value type.
On the other hand, the desired behavior is for the actions performed in the closure to be retained by the environment outside the closure--in other words two different contexts (inside the closure and out of it) need to refer to the same objects--which is more in line with the behavior of a reference type.
Long story short, I changed the struct to a class. The problem vanished, no other code needed.
I have seen this exact problem many times, but without more detail I can't say if it was happening for the same reason that you are having it.
It drove me crazy until I realized that the dispatched operation was taking place at an illogical time, i.e. usually before the current time. In the dispatch block's frame of reference, it correctly updated the variable, which is why it prints out correctly from inside the block. But in the "real world", for some reason, the dispatch is considered to have never happened, and the value change is discarded. Or perhaps it's because the mutation implicitly creates a new struct and because it was "time travelling" the reference to it never updated. Can't say.
In my case, the problem went away once I correctly scheduled the dispatch. I hope that helps!