I have a file with a ton of vars defined at the top, I think I might have reached some limit because when I went to add the latest block of var’s all of a sudden the interpreter starts complaining “ERROR: variable not defined”. As soon as I comment out the block everything returns to normal, and if I comment out an earlier block and leave the newer one, that also works, leading me to believe there’s some kind of limit on the var’s?
There is a limit of 256 variables within a single function, I think. (Every block of code submitted to the interpreter interactively, including read from a file, first compiles to a function, so, limits on function size apply.)
Essentially you’re defining variables that are global within the file. Global variables have been discouraged in the field of programming for several decades, because it’s too easy to overwrite values in one part of the code that another part depends on.
So, first, if any of these variables are only used for temporary purposes within other functions inside the big file, move the definitions to be local to those functions. Local vars help prevent some types of bugs.
Second, massive functions are generally recommended to be split up into smaller functions (refactoring). So, are there clusters of related functionality in your code where it makes sense to share data within the cluster, but there’s no need (or limited need) to share with other clusters? 99.99% probability this answer is yes. Those clusters can be packaged into separate functions:
{
var xxx; // belongs to first cluster
...
}.value;
{
var xxx; // belongs to second cluster
...
}.value;
etc etc
By the time you’re finished, there may still be a few file-globals, but only a dozen or two.
And (edit, forgot this one) – vars such as x0, x1, x2
could (or perhaps should) be consolidated into an array.
hjh
Although… I just tried to verify this by generating code with large numbers of variables, and I was able to go up to 100000 variables.
So I think I was wrong – the variable limit has been removed. Maybe you’re using an older SC?
With that said – it’s still not ideal to define a ton of variables in one function, so, still consider refactoring.
hjh
Did you check that you can actually use those variables and they behave as expected? I think the bytecodes that access variables are limited to 256 but creating them might not be limited?
Here is some code that fails…
~argsStr = 256.collect{|i| "a% ,".format(i) }.join;
"f = { var % a256; a256 = 10; a256 }".format(~argsStr).compile.()
// ERROR: Variable 'a256' not defined.
f
here is…
f = {
var a0 ,a1 ,a2 ,a3 ,a4 ,a5 ,a6 ,a7 ,a8 ,a9 ,a10 ,a11 ,a12 ,a13 ,a14 ,a15 ,
a16 ,a17 ,a18 ,a19 ,a20 ,a21 ,a22 ,a23 ,a24 ,a25 ,a26 ,a27 ,a28 ,a29 ,
a30 ,a31 ,a32 ,a33 ,a34 ,a35 ,a36 ,a37 ,a38 ,a39 ,a40 ,a41 ,a42 ,a43 ,
a44 ,a45 ,a46 ,a47 ,a48 ,a49 ,a50 ,a51 ,a52 ,a53 ,a54 ,a55 ,a56 ,a57 ,
a58 ,a59 ,a60 ,a61 ,a62 ,a63 ,a64 ,a65 ,a66 ,a67 ,a68 ,a69 ,a70 ,a71 ,
a72 ,a73 ,a74 ,a75 ,a76 ,a77 ,a78 ,a79 ,a80 ,a81 ,a82 ,a83 ,a84 ,a85 ,
a86 ,a87 ,a88 ,a89 ,a90 ,a91 ,a92 ,a93 ,a94 ,a95 ,a96 ,a97 ,a98 ,a99 ,
a100 ,a101 ,a102 ,a103 ,a104 ,a105 ,a106 ,a107 ,a108 ,a109 ,a110 ,
a111 ,a112 ,a113 ,a114 ,a115 ,a116 ,a117 ,a118 ,a119 ,a120 ,a121 ,
a122 ,a123 ,a124 ,a125 ,a126 ,a127 ,a128 ,a129 ,a130 ,a131 ,a132 ,
a133 ,a134 ,a135 ,a136 ,a137 ,a138 ,a139 ,a140 ,a141 ,a142 ,a143 ,
a144 ,a145 ,a146 ,a147 ,a148 ,a149 ,a150 ,a151 ,a152 ,a153 ,a154 ,
a155 ,a156 ,a157 ,a158 ,a159 ,a160 ,a161 ,a162 ,a163 ,a164 ,a165 ,
a166 ,a167 ,a168 ,a169 ,a170 ,a171 ,a172 ,a173 ,a174 ,a175 ,a176 ,
a177 ,a178 ,a179 ,a180 ,a181 ,a182 ,a183 ,a184 ,a185 ,a186 ,a187 ,
a188 ,a189 ,a190 ,a191 ,a192 ,a193 ,a194 ,a195 ,a196 ,a197 ,a198 ,
a199 ,a200 ,a201 ,a202 ,a203 ,a204 ,a205 ,a206 ,a207 ,a208 ,a209 ,
a210 ,a211 ,a212 ,a213 ,a214 ,a215 ,a216 ,a217 ,a218 ,a219 ,a220 ,
a221 ,a222 ,a223 ,a224 ,a225 ,a226 ,a227 ,a228 ,a229 ,a230 ,a231 ,
a232 ,a233 ,a234 ,a235 ,a236 ,a237 ,a238 ,a239 ,a240 ,a241 ,a242 ,
a243 ,a244 ,a245 ,a246 ,a247 ,a248 ,a249 ,a250 ,a251 ,a252 ,a253 ,
a254 ,a255 ,
a256;
a256 = 10;
a256
}
There is also a limit on how far up the home scope of the variable can be, its 256, but the compile posts another warning before you get there…
"{ var a = 10; % a % } ".format("{".dup(64).join, "}".dup(64).join) .compile
// fine
"{ var a = 10; % a % } ".format("{".dup(65).join, "}".dup(65).join) .compile
// ERROR: memory exhausted
Where the function here is something like…
{ var a = 10; {{{{{{{{{{{ a }}}}}}}}} }
Oh ok, no, I didn’t check that – reasonable supposition that unreachable variables would be disallowed in the compiler, but perhaps that’s not true.
I was certainly surprised in my test that the compiler didn’t choke on a massive number of variables.
EDIT: I did check it – indeed, 255 vars are OK, 256 vars are not.
(
var a = 1, b = 100000, mid, str, func;
while { (b - a) > 1 } {
mid = a + b div: 2;
[a, mid, b].postln;
str = CollStream.new << "{ var ";
mid.do { |i|
if(i > 0) { str << ", " };
str << "x" << i;
};
str << "; x" << (mid-1) << "; 0 }";
func = str.collection.compile;
if(func.value.value != 0) {
b = mid;
} {
a = mid;
}
};
[a, b].postln;
)
... after a bunch of compiler warnings...
-> [255, 256]
hjh
I agree.
@danknugz so to be clear. Yes there is a limit on the number of variables, that is 256.
… but honestly, you shouldn’t use more than about 10 or so at a time because it makes the code hard to read, more than 30 and I wouldn’t even bother reading it. What are you trying to do? Perhaps we can help you find a better way?
Thanks guys interesting to see, I ended up having to refactor some of the code to use a dictionary moving forward to avoid this issue. It’s just a GUI with some grid like buttons/elements and I had a bunch of var’s related.