tl;dr You are right that it is not possible currently, but there's no fundamental reason why Solidity couldn't implement the feature in future.
Fully dynamically sized arrays don't sit easily with the EVM's memory model. An arbitrary sized array could exist, but it would have to sit higher in memory than everything else to allow it to grow upwards in an unlimited way. By definition, then, you could have only one of them, and in any case it's difficult for the compiler to arrange this in general.
Actually, dynamically sized arrays are a bit of a luxury to us old-school types. C doesn't have them for example. You have to specifically reserve the memory for the array using malloc()
at runtime.
There are basically two scenarios:
Arbitrary sized arrays that can grow on demand. Solidity could probably implement these using a linked-list/skip-list structure internally, but this hasn't been done.
Dynamically sized arrays that can be created on-the-fly but remain fixed size once created. (This would meet your requirement.) I can't see any particular reason why Solidity couldn't implement this and it should be pretty easy. Again, it just hasn't been done See update below. Incidentally you can do this in the Ethereum LLL language via the alloc
expression, so there's no fundamental limitation.
Storage arrays are fundamentally different from memory arrays and indexed by a key=>value mechanism, so it's much easier to make them dynamic. Using a storage array and zeroing it on exit is an interesting idea, but you'll still only get about half the gas back; each element will cost about 10000 gas, which is huge.
In summary, for now, you're either going to have to allocate at least the maximum conceivable size required, or find an algorithm that uses fixed memory size. You are probably going to have to put a cap on n
and m
in any case to avoid getting into a state where your contract becomes unrunnable due to needing more gas than the prevailing block limit.
Update
It turns out that approach 2 above is possible in Solidity. You can use the following syntax to create an arbitrary sized array on-the-fly. It will not be resizable, but ought to meet your requirement.
function bar (uint n, uint m) returns (uint) {
uint maxnm = n < m ? m : n;
uint[] memory a = new uint[](maxnm);
return a[maxnm-1];
}