Using SelectionInList with SortedCollection? - smalltalk

Using Visualworks (Cincom Smalltalk), and a List widget, how does one use a SortedCollection along with SelectionInList? For instance, how do I initialize a SelectionInList with a SortedCollection?
I'm confused about the process, and I can't find any good documentation about how to proceed.

just like that:
aSelectionInList list: aSortedCollection.
the selection in list is an object that manages a selection and a list, it doesn't actually care too much about what kind of collection you pass as a list, as long as it is sequencable (i.e. responds to #at:)

You really want to use List all the time in SelectionInList objects. The reason is that List manages its dependencies itself in an instance variable. Other kinds of collections manage their dependencies using a system-wide Dependencies collection. This means that if your window shuts down unexpectedly you could be left with garbage in the Dependencies collection that still holds onto your entire Window structure and prevents it from being garbage collected. I've seen images grow to huge sizes because of this.
If you use a List, you can always sort it in place by using the sort or sort: methods. If you ever need to add elements to the list, you can just add them at the end and re-sort.

Related

Getting error when trying to modify a property of a nscopied object

I've created a model that has mainly a nested array of custom objects for use in a split-view (both UITableViews) "to-do" list type app. The left (master) is the lists of lists and the right (detail) is the lists :) Some other variables are kept in some of the classes like isSelected, isExpanded...
All of these classes implement NSCopying protocol. When I make a copy of a master list item and change the copy's name that works, but if I change anything in the detail list item belonging to that master list item, it changes in both the copy and the original. So I guess my question is how do I create a deep copy of a master list item. I thought by making them all implement NSCopying protocol it would automatically do this. I I really don't know what to put for code with so anything you need just ask.
Take a look at NSKeyedArchiver - you can archive your array of arrays, unarchive it, and you have a deep copied clone.
(Of course this only works if all your objects support archiving.)
how do I create a deep copy of a master list item
By implementing the deep copy logic in your own code. Deep copies are typically -- sometimes, but generally not -- more than just doing a copy of every object in the collection and everything it is connected to. Outside of property lists, anyway, which do support deep copies, but are limited to very simple, non-cyclic object graphs.
So, you would iterate the collection and copy each item in the collection, as needed. While implementing copyWithZone: may seem reasonable, a deep copy is often done by manually instantiating new instances and setting the various attributes based on the original as needed, copying where required.
-(MyClass)deepCopy {
MyClass* theCopy = [self mutableCopy];
for (MyElementType* element in self.dataContainer) {
MyElementType* theCopiedElement = [element deepCopy];
[theCopy somehowInsertThisElementInTheRightPlace:theCopiedElement]l
}
return theCopy;
}
Obviously, there's a bit of magic involved in that 5th line -- exactly how you do it depends on how the subsidiary data items are attached to your object. But there are really only 3-4 basic scenarios. Recursion naturally handles everything else.
(And note that you can be "smart" and not copy immutable objects, etc.)
(Also note that you can create "categories" for NSMutableArray and NSMutableDictionary.)

Stamping / Tagging / Branding Object Instances

I have a routine which accepts an object and does some processing on it. The objects may or may-not be mutable.
void CommandProcessor(ICommand command) {
// do a lot of things
}
There is a probability that the same command instance loops back in the processor. Things turn nasty when that happens. I want to detect these return visitors and prevent them from being processed. question is how can I do that transparently i.e. without disturbing the object themselves.
here is what i tried
Added a property Boolean Visited {get, set} on the ICommand.
I dont like this because the logic of one module shows up in other. The ShutdownCommand is concerned with shutting down, not with the bookkeeping. Also an EatIceCreamCommand may always return False in a hope to get more. Some non-mutable objects have outright problems with a setter.
privately maintain a lookup table of all processed instances. when an object comes first check against the list.
I dont like this either. (1) performance. the lookup table grows large. we need to do liner search to match instances. (2) cant rely on hashcode. the object may forge a different hashcode from time to time. (3) keeping the objects in a list prevents them from being garbage collected.
I need a way to put some invisible marker on the instance (of ICommand) which only my code can see. currently i dont discriminate between the invocations. just pray the same instances dont come back. does anyone have a better idea to implement this functionality..?
Assuming you can't stop this from happening just logically (try to cut out the loop) I would go for a HashSet of commands that you've already seen.
Even if the objects are violating the contracts of HashCode and Equals (which I would view as a problem to start with) you can create your own IEqualityComparer<ICommand> which uses System.Runtime.CompilerServices.RuntimeHelpers.GetHashCode to call Object.GetHashCode non-virtually. The Equals method would just test for reference identity. So your pool would contain distinct instances without caring whether or how the commands override Equals and GetHashCode.
That just leaves the problem of accumulating garbage. Assuming you don't have the option of purging the pool periodically, you could use WeakReference<T> (or the non-generic WeakReference class for .NET 4) to avoid retaining objects. You would then find all "dead" weak references every so often to prevent even accumulating those. (Your comparer would actually be an IEqualityComparer<WeakReference<T>> in this case, comparing the targets of the weak references for identity.)
It's not particularly elegant, but I'd argue that's inherent in the design - you need processing a command to change state somewhere, and an immutable object can't change state by definition, so you need the state outside the command. A hash set seems a fairly reasonable approach for that, and hopefully I've made it clear how you can avoid all three of the problems you mentioned.
EDIT: One thing I hadn't considered is that using WeakReference<T> makes it hard to remove entries - when the original value is garbage collected, you're not going to be able to find its hash code any more. You may well need to just create a new HashSet with the still-alive entries. Or use your own LRU cache, as mentioned in comments.

Can I safely modify a VB collection's items while iterating over it (using For Each)?

Can I safely modify -I mean: remove and re-add on a different index position- any item that I iterate over using a For Each loop in VB? We are talking about the VB Microsoft.VisualBasic.Collection class.
And if yes: Is this by design, or an implementational detail, that I am building upon then?
I might be too lazy to search hard enough, but the dox don't seem to say anything about this.
The IEnumerator<T> spec says that you can't:
An enumerator remains valid as long as the collection remains unchanged. If changes are made to the collection, such as adding, modifying, or deleting elements, the enumerator is irrecoverably invalidated and its behavior is undefined.
Some collections might not follow this rule.
You can't modify a collection whilst iterating through it as you describe; i.e. you can't remove an item without getting an exception such as "collection was modified".
That's not to say you can't modify the items at all (do something other than add/remove).
If you run into this error, try refactoring your code e.g. using a for loop (often in reverse, to avoid offsetting the index counter).
No you can't. Rather make a copy of the collection to edit and use the copy afterwards.

How to set up single array or dictionary for use in multiple datasources?

I have multiple TableViewDatasources that need to display list of objects form same pool depending of certain property.
E.g.
object.flag1 is set- it will show up in TableView1
object.flag2 is set- it will show up in TableView2
The obvious way would be to have separate arrays for each TableView, But same object may appear in different arrays. Also I need to update objects very often or access all objects through same array.
How do I setup a single dictionary or array to have all objects in one structure?
To put it in another way:
When table view or selection changes, application need to redraw TableViews with the new data. Application have to access the pool of objects and search through them using iterator and accessing each object and its properties.
I think that this is an expensive operation and want to avoid that. Perhaps maybe by making a global pool of objects a dictionary and exposing objects properties as dictionary fields.
So instead of iterating global pool of objects I could access global pool Dicitonary in a manner of database by selecting objects that has fields that match particular criteria.
Anyone know any example of doing that?
This sounds like a case of premature optimization. Unless you are managing many hundreds of items and/or causing redraws to happen terribly often, iterating through even a hundred objects and maintaining a couple of arrays isn't going to incur enough overhead -- either memory or CPU -- to be problematic.
Implement it the easy way, then measure it to determine if you really have a performance problem.
I'd be inclined to create proxy collections which act as the data sources. These proxies gather the appropriate objects from the pool when they prepare their content. Without knowing the scale of your pool and subsets, it's too early to consider optimising that.

Reading a pointer from XML without being sure the relevant Obj-C instance exists

I have a "parent" Obj-C object containing (in a collection) a bunch of objects whose instance variables point to one another, possibly circularly (fear not, no retaining going on between these "siblings"). I write the parent object to XML, which of course involves (among other things) writing out its "children", in no particular order, and due to the possible circularity, I replace these references between the children with unique IDs that each child has.
The problem is reading this XML back in... as I create one "child", I come across an ID, but there's no guarantee the object it refers to has been created yet. Since the references are possibly circular, there isn't even an order in which to read them that solves this problem.
What do I do? My current solution is to replace (in the actual instance variables) the references with strings containing the unique IDs. This is nasty, though, because to use these instance variables, instead of something like [oneObject aSibling] I now have to do something like [theParent childWithID:[oneObject aSiblingID]]. I suppose I could create an aSibling method to simplify things, but it feels like there's a cleaner way than all this. Is there?
This sounds an awful lot like you are re-inventing NSCoding as it handles circular references, etc... Now, there might be a good reason to re-invent that wheel. Only you can answer that question.
In any case, sounds like you want a two pass unarchival process.
Pass 1: Grab all the objects out of the backing store and reconstitute. As each object comes out, shove it in a dictionary or map with the UID as the key. Whenever an object contains a UID, register the object as needing to be fixed up; add it to a set or array that you keep around during unarchival.
Pass 2: Walk the set or array of objects that need to be fixed up and fix 'em up, replacing the UIDs with objects from the map you built in pass #1.
I hit a bit of parse error on that last paragraph. Assuming your classes are sensibly declared, they ought to be able to repair themselves on the fly.
(All things considered, this is exactly the kind of data structure that is much easier to implement in a GC'd environment. If you are targeting Mac OS X, not the iPhone, turning on GC is going to make your life easier, most likely)
Java's serialization process does much the same thing. Every object it writes out, it puts in a 'previously seen objects' table. When it comes to writing out a subsequent reference, if it's seen the object before, then it writes out a code which indicates that it's a previously seen object from the list. When the reverse occurs, whenever it sees such a reference, it replaces it on the fly with the instance before.
That approach means that you don't have to use this map for all instances, but rather the substitution happens only for objects you've seen a second time. However, you still need to be able to uniquely reference the first instance you've got written, whether by some pointer to a part in the data structure or not is dependent on what you're writing.