views:

2720

answers:

15

A friend asked me last week how to enumerate or list all variables within a program/function/etc. for the purposes of debugging (essentially getting a snapshot of everything so you can see what variables are set to, or if they are set at all). I looked around a bit and found a relatively good way for Python:

#!/usr/bin/python                                                                                                                                                                                                                           
foo1 = "Hello world"
foo2 = "bar"
foo3 = {"1":"a",
        "2":"b"}
foo4 = "1+1"

for name in dir():
    myvalue = eval(name)
    print name, "is", type(name), "and is equal to ", myvalue

which will output something like:

__builtins__ is <type 'str'> and is equal to  <module '__builtin__' (built-in)>
__doc__ is <type 'str'> and is equal to  None
__file__ is <type 'str'> and is equal to  ./foo.py
__name__ is <type 'str'> and is equal to  __main__
foo1 is <type 'str'> and is equal to  Hello world
foo2 is <type 'str'> and is equal to  bar
foo3 is <type 'str'> and is equal to  {'1': 'a', '2': 'b'}
foo4 is <type 'str'> and is equal to  1+1

I have so far found a partial way in PHP (courtesy of link text) but it only lists all variables and their types, not the contents:

<?php
// create a few variables
$bar = 'foo';
$foo ='bar';
// create a new array object
$arrayObj = new ArrayObject(get_defined_vars());
// loop over the array object and echo variables and values
for($iterator = $arrayObj->getIterator(); $iterator->valid(); $iterator->next())
        {
        echo $iterator->key() . ' => ' . $iterator->current() . '<br />';
        }
?>

So I put it to you: how do you list all variables and their contents in your favorite language?


Edit by VonC: I propose this question follows the spirit of a little "code-challenge".
If you do not agree, just edit and remove the tag and the link.

+3  A: 

First, I'd simply use a debugger ;-p Visual Studio, for example, has "Locals" and "Watch" windows that will show all the variables etc you want, fully expandable to any level.

In C# you can't really get at method variables very easily (and they many well be removed by the compiler) - but you can access fields etc via reflection:

static class Program { // formatted for minimal vertical space
    static object foo1 = "Hello world", foo2 = "bar",
                  foo3 = new[] { 1, 2, 3 }, foo4;
    static void Main() {
        foreach (var field in typeof(Program).GetFields(
                BindingFlags.Static | BindingFlags.NonPublic)) {
            var val = field.GetValue(null);
            if (val == null) {
                Console.WriteLine("{0} is null", field.Name);
            } else {
                Console.WriteLine("{0} ({1}) = {2}",
                    field.Name, val.GetType().Name, val);
            }
        }
    }
}
Marc Gravell
+6  A: 

This is what it would look like in Ruby:

#!/usr/bin/env ruby

foo1 = 'Hello world'
foo2 = 'bar'
foo3 = { '1' => 'a', '2' => 'b' }
foo4 = '1+1'

local_variables.each do |var|
  puts "#{var} is #{var.class} and is equal to #{eval(var).inspect}"
end

which will output

foo1 is String and is equal to "Hello world"
foo2 is String and is equal to "bar"
foo3 is String and is equal to {"1"=>"a", "2"=>"b"}
foo4 is String and is equal to "1+1"

However, didn't you mean to output the type of object the variable references instead of the type used to represent the variable identifier? IOW, the type of foo3 should be Hash (or dict) instead of String, right? In that case, the code would be

#!/usr/bin/env ruby

foo1 = 'Hello world'
foo2 = 'bar'
foo3 = { '1' => 'a', '2' => 'b' }
foo4 = '1+1'

local_variables.each do |var|
  val = eval(var)
  puts "#{var} is #{val.class} and is equal to #{val.inspect}"
end

and the result is

foo1 is String and is equal to "Hello world"
foo2 is String and is equal to "bar"
foo3 is Hash and is equal to {"1"=>"a", "2"=>"b"}
foo4 is String and is equal to "1+1"
Jörg W Mittag
you should also probably include:instance_variablesglobal_variablesclass_variablesconstants
Rado
+8  A: 

In python, using locals which returns a dictionary containing all the local bindings, thus, avoiding eval:

>>> foo1 = "Hello world"
>>> foo2 = "bar"
>>> foo3 = {"1":"a",
...         "2":"b"}
>>> foo4 = "1+1"

>>> import pprint
>>> pprint.pprint(locals())
{'__builtins__': <module '__builtin__' (built-in)>,
 '__doc__': None,
 '__name__': '__main__',
 'foo1': 'Hello world',
 'foo2': 'bar',
 'foo3': {'1': 'a', '2': 'b'},
 'foo4': '1+1',
 'pprint': <module 'pprint' from '/usr/lib/python2.5/pprint.pyc'>}
Aaron Maenpaa
+5  A: 

In php you could do this:

$defined = get_defined_vars(); 
foreach($defined as $varName => $varValue){
 echo "$varName is of type ".gettype($varValue)." and has value $varValue <br>";
}
Pim Jager
+1 Nice, this function is kinda of obscure but this is one of the smallest examples here, and some still say PHP sucks. =)
Alix Axel
+2  A: 

In java, the problem would be similar to C#, only in a more verbose mode (I know, I KNOW ;) Java is verbose... you made that clear already ;) )

You can access to object fields through Refection, but you may not access easily to method local variables. So the following is not for static analysis code, but for runtime debugging only.

package test;

import java.lang.reflect.Field;
import java.security.AccessController;
import java.security.PrivilegedAction;

/**
 * 
 * @author <a href="http://stackoverflow.com/users/6309/vonc"&gt;VonC&lt;/a&gt;
 */
public class DisplayVars
{

    private static int field1 = 1;
    private static String field2 = "~2~";
    private boolean isField = false;

    /**
     * @param args
     */
    public static void main(final String[] args)
    {
        final Field[] someFields = DisplayVars.class.getDeclaredFields();
        try
        {
            displayFields(someFields);
        } catch (IllegalAccessException e)
        {
            e.printStackTrace();
        }
    }

    /**
     * @param someFields
     * @throws IllegalAccessException
     * @throws IllegalArgumentException
     */
    @SuppressWarnings("unchecked")
    public static void displayFields(final Field[] someFields)
            throws IllegalAccessException
    {
        DisplayVars anObject = new DisplayVars();
        Object res = null;
        for (int ifields = 0; ifields < someFields.length; ifields++)
        {
            final Field aField = someFields[ifields];
            AccessController.doPrivileged(new PrivilegedAction() {
                public Object run()
                {
                    aField.setAccessible(true);
                    return null; // nothing to return
                }
            });
            res = aField.get(anObject);
            if (res != null)
            {
                System.out.println(aField.getName() + ": " + res.toString());
            } else
            {
                System.out.println(aField.getName() + ": null");
            }
        }
    }
}
VonC
Or you can use Apache Commons Beanutils.
Aaron Digulla
+2  A: 

Perl. Doesn't handle my locals, and doesn't filter out some useless references, but everything in package scope can be seen.

my %env = %{__PACKAGE__ . '::'};
while (($a, $b) = each %env) {
    print "\$$a = $$b\n";
    print "\@$a = (@$b)\n";
    print "%$a = (@{[%$b]})\n";
    print "*$a = $b\n";
}
ephemient
+6  A: 

In Lua the fundamental data structure is the table and even the global environment _G is a table. So, a simple enumeration will do the trick.

for k,v in pairs(_G) do
  print(k..' is '..type(v)..' and is equal to '..tostring(v))
end
Nick D
+1  A: 

Matlab:

who
Dario
A: 

Common Lisp:

(do-all-symbols (x) (print x))

To also show all bound values:

(do-all-symbols (x) (print x) (when (boundp x) (print (symbol-value x))))

This is a long list, and not particularly useful. I would really use the integrated debugger.

Svante
A: 

Here's an idea for oo-languages.

First you need something like toString() in Java to print meaningful contents. Second - you have to restrict yourself to one object-hierarchy. In the constructor of the root-object (like Any in Eiffel), your register the instance upon creation in some kind of global list. During destruction, you deregister (be sure to use some data structure that allows fast insert / search / removal). Any time during program execution, you can walk through this data-structure and print all objects registered there.

Due to it's structure, Eiffel might be very good for this purpose. Other Languages have problems with objects that are not user-defined (e.g. the jdk-classes). In Java it might be possible to create your own Object-class using some open-source jdk.

Tobias Langner
+1  A: 

Bash:

set

Disclaimer: Not my favourite language!

too much php
+1  A: 

In REBOL, all variables live inside a context of type object!. There's a global context, and every function has its own implicit local context. You can create new contexts explicitly by creating a new object! (or using the context function). This is different from traditional languages because variables (called "words" in REBOL) carry a reference to their context around with them, even when they have left the "scope" in which they were defined.

So, the bottom line is that, given a context, we can list the variables it defines. We'll use Ladislav Mecir's context-words? function.

context-words?: func [ ctx [object!] ] [ bind first ctx ctx ]

Now we can list all the words defined in the global context. (There are a lot of them.)

probe context-words? system/words

We can also write a function that then lists the variables it defines.

enumerable: func [a b c /local x y z] [
  probe context-words? bind? 'a
]

What we can't do in REBOL, as far as I know, is walk up the context tree, although the interpreter seems to be able to do this perfectly well when it decides how to bind words to their contexts. I think this is because the context tree (i.e., scope) may have one "shape" at the time a word is bound but quite another at the time it's evaluated.

Gregory Higley
+2  A: 

A fully recursive PHP one-liner:

print_r(get_defined_vars());
LapTop006
A: 

Quick and dirty JavaScript solution if you have FireBug installed (or another browser with console.log). If you don't, you'll have to change console.log to document.write, and run in at as an inline script at the end of your . Change MAX_DEPTH to how many levels of recursion you want (be careful!).

(function() {
    var MAX_DEPTH = 0;
    function printObj(name, o, depth) {
        console.log(name + " type: '"+typeof o+"' value: " + o);

        if(typeof o == "function" || depth >= MAX_DEPTH) return;
        for(var c in o) {
            printObj(name+"."+c, o[c], depth+1);
        }
    }
    for(var o in window) {
        printObj(o, window[o], 0);
    }
})();
gregers
A: 

Thank you for all ypurs answers. Do you know how to enumerate all variables in C ?

erwan