Limit of VarSet ( or looking for data types )

I'm running this piece of code:

for (i=0; i< 100000; i++) {
  VarSet("Test"+i, 100000);
}

It gives me Error 15. Endless loop detected in FOR loop.

Question 1. Is there a limit to the number of dynamic variables I can set? Or is there an amibroker configuration that triggers this error somewhere?

What I'm trying to do is create a dictionary of a key ( price level ) to values ( array of bars who's closing value is within the price level of the key ). I can't use a matrix because... the values are dynamic in length... well I can but it's not great.

Question 2. Are there any datatypes like a hashtable or dictionary that I can use in amibroker for the above purpose?
I know of Scalar, Array, String, Dynamic (VarGet/Set), Matrix, Static ( StaticVarGet/Set ).
Is there anything else?

Thanks for reading!

Well, this proves it isn't a VarSet limit, this will work.

for (i=0; i < 100; i++) {
	for (j = 0; j < 1000; j++) {
		VarSet("Test"+i+"|"+j, 100000);
	}
}

"Endless loop detection threshold" is set from Menu > Preferences > AFL

2 Likes

Check this preference setting

image

2 Likes
  1. There is no hard coded limit on dynamic variables
  2. There is no dictionary built-in object right now, but this has been in the consideration for quite some time.

As to the error, others already explained why you get it.

1 Like

It would be good to have built in data structures like dictionary, set, struct, list to be able to express more complex programs easier.

Here is an attempt at a dictionary module, pretty rudimentary but will do the job for now.

global g_dict_prefix;

g_dict_prefix = "dict_";

function dict_init(dictName) {
    VarSetText(g_dict_prefix + dictName, "init");
}

function dict_insert(dictName, key, value) {    
    VarSet( g_dict_prefix + dictName + key, value);
    VarSetText( g_dict_prefix + dictName,  VarGetText( g_dict_prefix + dictName) + "," + key);
}

function dict_get(dictName, key) { 
    return VarGet(g_dict_prefix + dictName + key); 
}

function dict_remove(dictName) {
    local keys, i, key;

    keys = VarGetText(g_dict_prefix + dictName);    
    i=0;
    while(true)
    {   
        key = StrExtract(keys, i);
        if (key == "") break;

        VarSet(g_dict_prefix + dictName + key, 0);
        i++;
    }

    _TRACE(StrFormat("dict - cleaned dictionary: %s, %g items", dictName, i));
    _TRACE("Keys: " + keys);
}

// usage
dict_init("test");
dict_insert("test", 1, 20);
_TRACE("Dict get value: " + dict_get("test", 1));
dict_remove("test");
_TRACE("Dict get value: " + dict_get("test", 1));

It's got a major performance flaw in that it cannot identify unique keys on the insertion so if there is a lot of update operations, it'll waste time cleaning it up. A VarSetRemove would help here but ultimately, it's just the wrong data structure...

1 Like

Yes I know that dictionary would be useful. I was thinking about that quite a bit of time. For what it is worth, if you use varname a a key, you don't need to do anything. If you have duplicate key, it will overwrite existing one. To lookup for the key you can simply use VarGet and it will give you Null.

2 Likes

This topic was automatically closed 100 days after the last reply. New replies are no longer allowed.