Weak References with Dictionaries in Actionscript
Posted by Zachary Pinter on October 11, 2007 at 08:02 PM
Actionscript dictionaries are a great tool for dealing with memory management because you can use them to create weak references to objects. This means that the object automatically goes away upon garbage collection if the only reference to it is in the Dictinary.
To use a dictionary in this manner, simply pass true to the constructor. However, one should note that this only makes the keys of the Dictionary weak.
For example:
1 class MyObject { 2 public var message:String; 3 } 4 5 var dict:Dictionary = new Dictionary(true); 6 var obj1:MyObject = new MyObject(); 7 obj1.message = "My really long message..."; 8 var obj2:MyObject = new MyObject(); 9 obj2.message = "My second really long message..."; 10 11 dict[obj1] = true; //obj1 is weakly referenced 12 dict[2] = obj2; //obj2 is strongly referenced
If the only reference to an object is the key of a weakly referenced dictionary, the object will not persist after garbage collection. However, if the only reference to an object is the value of a key in a weakly referenced dictionary, the reference is considered strong and will force the object to persist after garbage collection.
So, what do you do if you want to store a dictionary of weakly referenced objects, but key them off of a meaningful value (such as an item id) rather than their reference id?
The answer is to use a simple WeakReference class (source):
1 class WeakRef { 2 private var dic:Dictionary; 3 4 public function WeakRef( obj:* ) { 5 dic = new Dictionary( true ); 6 dic[obj] = 1; 7 } 8 9 public function get():* { 10 for( var item:* in dic ) { 11 return item; 12 } 13 return null; 14 } 15 }
From here, you can do the following:
1 var dict:Dictionary = new Dictionary(true); 2 var obj1:MyObject = new MyObject(); 3 obj1.message = "My really long message..."; 4 var obj2:MyObject = new MyObject(); 5 obj2.message = "My second really long message..."; 6 7 dict[1] = new WeakReference(obj1); //weakly referenced value 8 dict[2] = new WeakReference(obj2); //weakly referenced value
Now, you can key based off of a meaningful value, and still get all the benefits of weak references.
Actionscript Hash
Posted by Zachary Pinter on October 09, 2007 at 08:36 PM
On the surface, the Dictionary object in Actionscript seems quite limited compared to the Hash and HashMap libraries of other languages. However, the functionality you would expect is still there, it's just obscure.
For example, to loop through all keys in a Dictionary:
1 for (var key:Object in groupMap) 2 { 3 trace(key + ", " + groupMap[key]); 4 }
To loop through all values in a Dictionary:
1 for each (var item:Object in groupMap) 2 { 3 trace(item); 4 }
To check if a key exists (in a way that's distinguishes from a key whose value could be null):
1 obj['key'] === undefined //key exists
To remove a key/value pair from a Dictionary:
1 delete obj['key']
All of the above code will also work for a regular object treated like a hash.
eBay Desktop Launched
Posted by Zachary Pinter on October 02, 2007 at 07:51 PM
As I mentioned previously, I started working for effectiveUI in July. Since then, I've been working on Project Sandimas, the code name for the AIR application now known as eBay Desktop. The product launched into open beta yesterday and has already won an award at the Adobe MAX conference.
So go ahead and try it out!
ZFS on OS X?
Posted by Zachary Pinter on April 30, 2006 at 11:00 PM
What are Ruby Symbols?
Posted by Zachary Pinter on December 13, 2005 at 05:36 AM
I've introduced a few friends/classmates/coworkers to Ruby and Rails lately, and many of them have since approached me and asked "what is that colon thing in ruby?" So, I've decided to explain Ruby symbols as I know them.
Symbols are essentially small, automatically created global read-only objects that have a unique numerical value associated with them and are accessed through the :[name] syntax. Any time you use a named symbol (such as :bob), you are really telling Ruby to find the object associated with the name "bob" in the global table of symbols. Therefore, :bob in one class returns exactly the same object that :bob returns in another class.
The numerical value associated with a symbol object is generated for you behind the scenes. You don't really care what it is, you just care that it is unique among all other symbols.
This nature of symbol objects creates some very useful applications. For one, you can use a symbol as a named constant whose value you do not care about. For instance, you might have a C library with tons of interesting constants like
AR_REL_OP_GREATER_EQUAL = 3For the sake of C programming, that constant has to have a value. However, if all you really care about is whether or not something is flagged as AR_REL_OP_GREATER_EQUAL, then the actual value is practically meaningless. In such a case with Ruby, you could use symbols to write code like
if x.operation == :greater_equal ... endYou can check whether or not a value equals :greater_equal without ever having to select a numerical value for :greater_equal. As an added bonus, you can call
:greater_equal.to_sand get a full-blown String object out of the name of the Symbol. Now, that might not seem like a big deal just now, but think about converting AR_REL_OP_GREATER_EQUAL into a cstring. With symbols, it's a piece of cake, and there are plenty of times when finding the actual name of a constant is useful, especially when it comes to debugging.
Since the actual object that is referenced by a symbol is global and unchangeable, it makes a perfect candidate for use as a key in a hash table. That is why you always see syntax such as
{:name=>"Zachary",:job=>"Programmer"}
The above code is short-hand syntax for creating a Hash object with the keys :name and :job mapped to the values "Zachary" and "Programmer". Yes, one can always use String objects as keys in a Hash, but in Ruby, a String object is changeable (mutable). For example, you can call gsub! on a String and replace the contents of the object. Doing so would change the value that the String would hash to, and corrupt any Hash table that String was used as a key in.
If you're a Java programmer, you should note this very important difference between a Ruby String and a Java String. In Java, String objects are unchangeable (immutable) and StringBuffers are changeable (mutable). In Ruby, Symbol objects are unchangeable and String objects are changeable. When you call concat ("+") or replace on a Java String, you are actualy creating a brand new String object (instead of making changes to the current one). This is precisely why Java programmers are told to use a StringBuffer class instead of the "+" sign to concatenate several strings. In Ruby, no concern is paid to concatenation, since the core String class is mutable. Similarly, in Java, it is common to use a String object as a key in a HashMap. In Ruby, that's frowned upon since a lot of things could go wrong if that String object were changed (as explained above).
Symbols may seem awkward at first because they are not common among other programming languages. However, there are many pro's to the tradeoff made by choosing String/Symbol (Ruby) over StringBuffer/String (Java). Additionally, the unique nature of symbols has it's own benefits when it comes to flags that were traditionally set with numerical constants.