views:

314

answers:

3

In an actionscript function (method) I have access to arguments.caller which returns a Function object but I can't find out the name of the function represented by this Function object. Its toString() simply returns [Function] and I can't find any other useful accessors that give me that... Help :-/

+1  A: 

A function is just an object like any other - it doesn't have a "name" in and of itself; it only has a name in the sense that you might make one or more references to it. If what you're asking is how to get the name of the reference by which the function was called, then there's no general way to do that. (After all the function could be declared anonymously, in which case it has no name at all.)

It would probably be best to examine why you need to know the function's name, and figure out some other way to pass in or access the information you're trying to derive from that name. Passing in an additional parameter might be one approach, but it depends on what you're doing.

fenomas
A: 

As far as I know, not in AS2 AS3 only.

A: 

I found an answer and I'll paste it below.

@fenomas: yes, you are right of course, functions are just objects and what I'm looking for is a the name of the reference to them (if exists, i.e. the function is not anonymous). You also right that in general this doesn't look like the best way to do programming ;-) But my scenario is special: I want to implement a Checks class (similar to C CHECK) with methods such as Check.checkTrue and Checks.checkRef in which when the check fails I get a nice trace. The traces will appear only in debug version, not in release.

I'm using MTASC and the code below only works with MTASC. It should also be used only for debugging purposes and not release. The technique is to iterate on _global and find a function that's equal to my calling function. It's a hack that does not always work (anonymous) but it serves me pretty well in most cases.

39:   /**
40:    * Checks that cond is true. Use this method to validate that condition
41:    * cond holds.
42:    * If cond is false, traces a severe message and returns false to indicate
43:    * check failure.
44:    *
45:    * @param cond the contition expected to be true
46:    * @param msg the message to emit in case the condition is false.
47:    *
48:    * @return false is cond is false
49:    */
50:   public static function checkTrue(cond:Boolean, msg:String):Boolean {
51:     if (!cond) {
52:       trace("severe", "CHECK FAILED at " +
53:           **getFunctionName(arguments.caller)** + ":\n" + msg);
54:     }
55:     return cond;
56:   }


94:   /**
95:    * Gets the name of the function func.
96:    * Warning: Use this only in debug version, not in release
98:    *
99:    * @return The full package path to the function. null if the function
100:    *      isn't found.
101:    */
102:   private static function getFunctionName(func:Function):String {
103:     var name:String = getFunctionNameRecursive(func, _global);
108:     return name;
109:   }
110: 
111:   /**
112:    * Gets the name of the function func by recursively iterating over root.
113:    * Warning: Use this only in debug version, not in release
114:    */
115:   private static function getFunctionNameRecursive(func:Function,
116:       root:Object):String {
117:     if (!root) {
118:       return null;
119:     }
120: 
121:     // Iterate over classes in this package
122:     // A class is a function with a prototype object
123:     for (var i:String in root) {
124:       if (root[i] instanceof Function && root[i].prototype != null) {
125:         // Found a class.
126:         // Iterate over class static members to see if there's a match
127:         for (var f:String in root[i]) {
128:           if(root[i][f] == func) {
129:             return i + "." + f;
130:           }
131:         }
132:         // Loop over the class's prototype to look for instance methods
133:         var instance:Object = root[i].prototype;
134:         // Reveal prototype's methods.
135:         // Warning: Not to be used in production code!!!
136:         // The following line make all the instance attributes visible to the
137:         // for-in construct. The "n" value is 8 which means "unhide"
138:         // See http://osflash.org/flashcoders/undocumented/assetpropflags
139:         // This operation is later undone by setting the "n" to 1 which means
140:         // "hide"
141:         _global.ASSetPropFlags(instance, null, 8, 1);
142:         for (var f:String in instance) {
143:           if(instance[f] == func) {
144:             return i + "." + f;
145:           }
146:         }
147:         // And hide instance methods again
148:         // This line undoes the previous ASSetPropFlags
149:         _global.ASSetPropFlags(instance, null, 1, false);
150:       }
151:     }
152: 
153:     // Iterate over sub packages. Sub packages have type "object"
154:     for (var i:String in root) {
155:       if (typeof(root[i]) == "object") {
156:         var name:String = getFunctionNameRecursive(func, root[i]);
157:         if (name) {
158:           return i + "." + name;
159:         }
160:       }
161:     }
162:     return null;
163:   }
Ran