Vec with interior mutability - iterator

I have a struct AppData with contains a Vec<Box<Updatable>> called objects, which contains structs that implement a trait Updatable with the following function:
fn update(&mut self, data: &mut AppData) {
//default implementation accesses and mutates AppData, including the internal `objects` Vec and possibly also objects inside it
}
The AppData struct is stored in a field data in a struct App with the following function:
pub fn update(&mut self) {
for d in self.data.objects.iter(){
d.update(&mut self.data);
}
}
I cannot do this beacuse Box<T> is immutable. So I tried using indexers instead:
for i in 0..self.data.objects.len() {
let ref mut d = self.data.objects[i];
d.update(&mut self.data);
}
But then I get
cannot borrow self.data as mutable more than once at a time
So what do I do? I could probably get it to compile using combinations of RefCell etc but I'm not sure it would be idiomatic Rust. A few alternatives:
Cloning the Vec and iterating over the clone instead. But I ran into trouble because Updateable does not implement Sized.
Using RefCell instead of Box. I'm not sure I should need it since I'm not storing the references to the Vec inside the Updatables but that might not make a difference? I suppose RefCell is supposed to be used over Rc in this scenario because I want mutable references? Also this does not solve my problem because I still need to take ownership of self.data somehow, right?
Taking ownership of self.data after deconstructing self and then placing it back into self after we are done with it. How do I do that?
Thanks in advance!

You can use iter_mut() instead of iter() to get the same result as your indexer-based solution:
pub fn update(&mut self) {
for d in self.data.objects.iter_mut() {
d.update(&mut self.data);
}
}
(Yes, "same result" means we still get "cannot borrow self.data as mutable more than once at a time".)
There are a couple of soundness issues in your program. First, by passing a &mut AppData to Updatable::update(), the implementation of update() could destroy self by removing the corresponding item from objects! (It doesn't matter if AppData doesn't actually provide a method to do that.)
Additionally, Updatable::update() could invalidate the iterator in App::update() by adding any item to or removing any item from objects. Switching to an indexer-based loop only makes the problem worse, because your program might compile, but it will be buggy!
In order to ensure that your Updatable remains alive for the duration of the update() call, you need to wrap it in some other smart pointer. For example, you could wrap it in an Rc instead of a Box. As Rc doesn't let you take a mutable borrow to its contents, you may want to combine this with RefCell, like so:
struct AppData {
objects: Vec<Rc<RefCell<Updatable>>>,
}
We can do the same for the whole Vec:
struct AppData {
objects: Rc<RefCell<Vec<Rc<RefCell<Updatable>>>>>,
}
However, that comes with a restriction: while you're iterating on objects in App::update(), you will not be able to mutate objects from implementations of Updatable::update(). If you try to do so, your program will panic, because you can't have more than one active mutable borrow on the same RefCell.
If you need to be able to mutate objects from implementations of Updatable::update(), then you probably want App::update() to iterate on whatever objects contained when you start the loop. The simple solution to this is to clone the Vec just before the loop (we don't need Rc<RefCell<Vec<...>>> for this).
However, cloning a Vec every time (even when not necessary) might be expensive, so you may want to avoid doing so when it's not needed. Instead of cloning the Vec systematically, we can wrap the Vec in an Rc (but no RefCell this time!), then clone the Rc before borrowing the vector in App::update(). In AppData, methods that want to mutate objects would use Rc::make_mut to clone the Vec (if necessary!) and obtain a mutable reference. If the mutation occurs while App::update() is active, this will clone the Vec, which leaves the original Vec alone so the iteration can continue. However, if there are no actives clones of the Rc, then this will not do a clone, it'll just give you a mutable reference to the Vec, because it's safe to do so.

Box<T> is not intrinsically immutable. It plays by the same rules of inherited mutability as most other types. Your problem is a combination of different issues. First, .iter() gives an iterator over (immutable) references. So even if you didn't need to borrow self.data mutably while iterating over it, you'll get an error for that. If you want to iterate over mutable references, just do for d in &mut self.data.objects { ... } instead of the indexing dance.
Second, as you noticed, there is an issue with borrowing self.data while iterating over it. This is a potential issue in your design. For example, what should happen if update removes an object from the objects vector?
There is no easy one-size-fits-all solution to this. Maybe RefCell<Box<Trait>> will help, maybe it would be terrible design. Maybe update doesn't need the objects part of self.data and you can swap it out while iterating, which would prevent mutable aliasing. Maybe it's best to scrap the trait and pursue a wholly different design (it looks like you're trying to apply textbook OOP design which in my experience rarely works well in Rust).

Related

What is the biggest advantage of using pointers in ObjectiveC

I realize 99% of you think "what the h***…" But please help me to get my head around the this concept of using pointers. I'm sure my specific question would help lots of newbies.
I understand what pointers ARE and that they are a reference to an adress in memory and that by using the (*) operator you can get the value in that address.
Let's say:
int counter = 10;
int *somePointer = &counter;
Now I have the address in memory of counter, and I can indirectly point to its value by doing this:
int x = *somePointer;
Which makes x = 10, right?
But this is the most basic example, and for this case I could use int x = counter; and get that value, so please explain why pointers really are such an important thing in Objective-C and some other languages... in what case would only a pointer make sense?
Appreciate it.
Objective-C has pointers because it is an evolution of C, which used pointers extensively. The advantage of a pointer in an object-oriented language like Objective-C is that after you create an object, you can pass around a pointer to the object instead of passing around the object itself. In other words, if you have some object that takes up a large amount of storage space, passing around a pointer is a lot more memory-efficient than passing around a copy of the object itself. This may not be noticeable in simple cases when you’re only dealing with primitive types like ints, but when you start dealing with more complex objects the memory and time savings are enormous.
More importantly, pointers make it much easier for different parts of your code to talk to each other. If variables could only be passed to functions “by value” instead of “by reference” (which is what happens when you use pointers), then functions could never alter their inputs. They could only change the state of your program by either returning a value or by changing a global variable—the overuse of which generally leads to sloppy, unorganized code.
Here’s a concrete example. Suppose you have an Objective-C method that will parse a JSON string and return an NSDictionary:
+ (NSDictionary *)parseJsonString:(NSString *)json
error:(NSError **)error;
The method will do the parsing and return an NSDictionary if everything goes okay. But what if there’s some problem with the input string? We want a way to indicate to the user (or at least to the programmer) what happened, so we have a pointer to a pointer to an NSError, which will contain that information. If our method fails (probably returning nil), we can dereference the error parameter to see what went wrong. What we’ve effectively done is to give our method two different kinds of return values: usually, it will return an NSDictionary, but it could also return an NSError.
If you want to read more about this, you may have better luck searching for “pointers in C” rather than “pointers in Objective-C”; pointers are of course used extensively in Objective-C, but all of the underlying machinery is identical to that of C itself.
What is the biggest advantage of using pointers in ObjectiveC
I'd say the biggest advantage is that you can use Objective-C at all - all Objective-C objects are pointers are accessed using pointers (the compiler and the runtime won't let you create objects statically), so you wouldn't get any further without them...
Item:
What if I told you to write me a program that would maintain a set of counters, but the number of counters would be entered by the user when he started the program. We code this with an array of integers allocated on the heap.
int *counters = malloc(numOfCounters * sizeof(int));
Malloc works with memory directly, so it by nature returns a pointer. All Objective-C objects are heap-allocated with malloc, so these are always pointers.
Item:
What if I told you to write me a function that read a file, and then ran another function when it was done. However, this other function was unknown and would be added by other people, people I didn't even know.
For this we have the "callback". You'd write a function that looked like this:
int ReadAndCallBack(FILE *fileToRead, int numBytes, int whence, void(*callback)(char *));
That last argument is a pointer to a function. When someone calls the function you've written, they do something like this:
void MyDataFunction(char *dataToProcess);
ReadAndCallBack(myFile, 1024, 0, MyDataFunction);
Item:
Passing a pointer as a function argument is the most common way of returning multiple values from a function. In the Carbon libraries on OSX, almost all of the library functions return an error status, which poses a problem if a library function has to return something useful to the programmer. So you pass the address where you'd like the function to hand information back to you...
int size = 0;
int error = GetFileSize(afilePath,&size);
If the function call returns an error, it is in error, if there was no error, error will probably be zero and size will contain what we need.
The biggest advantage of pointers in Objective-C, or in any language with dynamic allocation, is that your program can handle more items than the names that you invent in your source code.

An Array of Blocks?

This seems like a very strange interaction to me but at the same time it not only works but throws no warnings or errors in the process. Just looking to get some better understanding of blocks in general and why something like this could be right or wrong.
Is there any reason why something like this shouldn't be done?
NSArray *array = [NSArray arrayWithObjects:^{NSLog(#"Block 1");}, ^{NSLog(#"Block 2");}, ^{NSLog(#"Block 3");}, nil];
for (id block in array) {
[block invoke];
}
Putting Blocks into NSArrays is fine; they're objects. In fact, they inherit from NSObject.
You do need to copy, them, however. Those Blocks are created on the stack and need to be moved to the heap in order to live past the end of the current method. If you're using ARC, this is easy:
NSArray *array = [NSArray arrayWithObjects:[^{NSLog(#"Block 1");} copy], ...
Under MRR, you need to balance that copy, so you have two unpleasant options: use temps, or enumerate the array right after creating it and send release to all its members.
Sending invoke, on the other hand, isn't completely kosher, because that's a private method. The only fully-API-compliant way to invoke a Block is with function-call syntax:
typedef GenericBlock dispatch_block_t;
for( GenericBlock block in array ){
block();
}
Sure, that's fine. Why wouldn't it be fine?
In languages like JavaScript this technique is commonplace when registering event handlers.
object.clickHandlers.push(function() { doStuff() });
object.clickHandlers.push(function() { doMoreStuff() });
I see no reason that similar techniques couldn't be used with ObjC blocks, as they are real objects.
The more interesting question to me though, is if this pattern is the best choice for whatever your goal is. Which you haven't really told us.
Blocks in Objective-C are "first-class citizen" objects. Whatever you can do to a regular object, be it passing as a parameter, storing in an array or a dictionary, and so on, you can do it to block objects as well.
For example, an array of block objects may be useful to encode a sequence of actions that is not known at compile time; a dictionary of block objects keyed by strings could be useful in implementing a scripting language, and so on.
The best way to call a block retrieved from a collection is casting it to its proper type, and using the regular block invocation syntax on it.

Lua metatable class destructor

I have the following Lua metatable class, how can I add a destructor to it so when a certain condition arrives it will destruct the created object and set it's value to nil?
-------------------------------------------------
-- Arrow class
-------------------------------------------------
local arrow = {}
local arrow_mt = { __index = arrow } -- metatable
function arrow.new(x, y) -- constructor
local newArrow = {
position = { x = x, y = y }
}
return setmetatable( newArrow, arrow_mt )
end
function arrow:remove()
-- remove the object here
-- self = nil dosent work
end
As Nicol said, once a variable gets a reference to your object, the object itself cannot control the variable (i.e. set it's value to nil). Actually, this is a good thing - imagine someone somewhere saved a reference to you object to a local variable. Suddenly at an unknown moment, it becomes an nil reference (because it is destroyed somewhere else), and any further access to it results in an error.
That's a bummer, I need the object destroyed right away.
Do you really need to destroy the object? Why? Isn't the Lua garbage collector doing it's job correctly? Isn't there another way to design the relationship between the objects?
For example, in the simplest case, you can force a garbage collection through collectgarbage("collect"). A garbage collection will clean all objects, that have no strong references to them. If you really want variables to disappear, keep them in a weak table. Of course, Lua will do the garbage collection automatically while you allocate objects (unless you stop it). You can also modify the speed of garbage collection.
You can't. Lua isn't C/C++; it uses garbage collection. You therefore have to rely on garbage collection; the user of your object has control over when it goes away. It is up to them to discard their references to it when they're done with it.
So while you can have an explicit "new" (though you shouldn't call it that), you don't get to have an explicit "delete". Destruction will happen when the object is no longer referenced.

Returning mutable vs. returning immutable (non-member-)objects

I hardly ever see the second one used and I wonder why?
Neither would it break support for situations where an NSArray is expected (as it's a subclass).
Nor would it break encapsulation by revealing mutable internals.
Under the precondition that it's never a mutable ivar that's returned, (which should be common sense anyway)
I can right now only think of advantages of using the second.
It actually is mutable. And muting is safe here, so why prevent it?
No need to call [[[foo fooBar] mutableCopy] autorelease], which needlessly allocates additional memory and needlessly wastes time.
Here are the method variations:
- (NSArray *)fooBar {
NSMutableArray *fooArray = [NSMutableArray array];
//populate fooArray
return fooArray;
}
- (NSMutableArray *)fooBar {
NSMutableArray *fooArray = [NSMutableArray array];
//populate fooArray
return fooArray;
}
I'm asking as my project has a bunch of methods with the same pattern.
And in most of the times the returned array will be modified afterwards (merged, edited, etc).
So I think it should be totally fine to return NSMutableArrays, yet nobody seems to be doing it.
NSMutableArray, NSMutableSet, NSMutableDictionary… it's basically the same deal.
For an explanation of using mutable versus immutable, check out Apple's documentation on Object Mutability.
In general, it is best to return an immutable version, unless it is specifically your intent that the object returned always be an immutable object available for any client to change. You should create your interfaces based on the intent of the interface, not off the current implementation. It is possible that requirements will change and you will need to change the implementation of fooBar such that it does return an instance variable. By returning mutable arrays you ensure that you encapsulate not only your instance variables, but your current implementation.
So, you may have a valid place to return a mutable array (I don't know), but you see most code passing immutable arrays because it fully encapsulates their variables and their implementations.
I suppose the first variation was preferred because polymorphism was preferred.
In either case, both methods return an instance of NSMutableArray, the only difference being that the first one hides that fact from the caller. In other words, the first variation is not safer than the second. It's essentially using polymorphism to tell the caller that any type of NSArray might be returned. If you need that kind of flexibility in your code, it definitely has it's advantages. (e.g., if one day, for whatever reason, you need to return a custom NSArray subclass, your code won't break at that level).
However, you seem to prefer communicating intent to the caller - i.e. that you actually return mutable arrays - which is also OK. To make everyone happy (if there is such thing anyways...), I suggest renaming the 2nd method to:
- (NSMutableArray *)mutableFooBar {
NSMutableArray *fooArray = [NSMutableArray array];
//populate fooArray
return fooArray;
}
As a side note, I think that the following is a slightly more efficient way to convert an existing immutable array into a mutable one:
NSMutableArray *mutableArray = [NSMutableArray arrayWithArray:fooArray];
(correct me if I'm wrong on that assumption).
I hope this answers your question...
Having a method return a mutable instance like that looks suspicious.
As the caller you have to question the original method signature and wonder if it really is safe to mutate the returned value. After all the class may inadvertently be returning a pointer to internal state.
If profiling reveals that this copy is indeed expensive, I usually change the method signature to make it obvious that the mutability is intended. Perhaps with something like:
- (void)populateFooBars:(NSMutableArray *)array;
That way it is clear that the mutability of the result is intentional.

Cocoa: Testing to find if an NSString is immutable or mutable?

This produces an immutable string object:
NSString* myStringA = #"A"; //CORRECTED FROM: NSMutableString* myStringA = #"A";
This produces a mutable string object:
NSMutableString* myStringB = [NSMutableString stringWithString:#"B"];
But both objects are reported as the same kind of object, "NSCFString":
NSLog(#"myStringA is type: %#, myStringB is type: %#",
[myStringA class], [myStringB class]);
So what is distinguishing these objects internally, and how do I test for that, so that I can easily determine if a mystery string variable is immutable or mutable before doing something evil to it?
The docs include a fairly long explanation on why Apple doesn't want you to do this and why they explicitly do not support it in Receiving Mutable Objects. The summary is:
So don’t make a decision on object
mutability based on what introspection
tells you about an object. Treat
objects as mutable or not based on
what you are handed at the API
boundaries (that is, based on the
return type). If you need to
unambiguously mark an object as
mutable or immutable when you pass it
to clients, pass that information as a
flag along with the object.
I find their NSView example the easiest to understand, and it illustrates a basic Cocoa problem. You have an NSMutableArray called "elements" that you want to expose as an array, but don't want callers to mess with. You have several options:
Expose your NSMutableArray as an NSArray.
Always make a non-mutable copy when requested
Store elements as an NSArray and create a new array every time it mutates.
I've done all of these at various points. #1 is by far the simplest and fastest solution. It's also dangerous, since the array might mutate behind the caller's back. But Apple indicates it's what they do in some cases (note the warning for -subviews in NSView). I can confirm that while #2 and #3 are much safer, they can create major performance problems, which is probably why Apple has chosen not to use them on oft-accessed members like -subviews.
The upshot of all of this is that if you use #1, then introspection will mislead you. You have an NSMutableArray cast as an NSArray, and introspection will indicate that it's mutable (introspection has no way to know otherwise). But you must not mutate it. Only the compile-time type check can tell you that, and so it's the only thing you can trust.
The fix for this would be some kind of fast copy-on-write immutable version of a mutable data structure. That way #2 could possibly be done with decent performance. I can imagine changes to the NSArray cluster that would allow this, but it doesn't exist in Cocoa today (and could impact NSArray performance in the normal case, making it a non-starter). Even if we had it, there's probably too much code out there that relies on the current behavior to ever allow mutability introspection to be trusted.
There's no (documented) way to determine if a string is mutable at runtime or not.
You would expect one of the following would work, but none of them work:
[[s class] isKindOfClass:[NSMutableString class]]; // always returns false
[s isMemberOfClass:[NSMutableString class]]; // always returns false
[s respondsToSelector:#selector(appendString)]; // always returns true
More info here, although it doesn't help you with the problem:
http://www.cocoabuilder.com/archive/cocoa/111173-mutability.html
If you want to check for debugging purposes the following code should work. Copy on immutable object is itself, while it's a true copy for mutable types, that's what the code is based on. Note that since it's calling copy it's slow, but should be fine for debugging. If you'd like to check for any other reasons than debugging see Rob answer (and forget about it).
BOOL isMutable(id object)
{
id copy = [object copy];
BOOL copyIsADifferentObject = (copy != object);
[copy release];
return copyIsADifferentObject;
}
Disclaimer: of course there is no guarantee that copy is equivalent with retain for immutable types. You can be sure that if isMutable returns NO then it's not mutable so the function should be probably named canBeMutable. In the real world however, it's a pretty safe assumption that immutable types (NSString,NSArray) will implement this optimization. There is a lot of code out including basic things like NSDictionary that expects fast copy from immutable types.