Thursday, September 23, 2010

Tutorial: Undocumented behavior of kernel functions min()/max()

I was recently reviewing some code written to be shipped with AX6, and noticed an unfamiliar pattern being used in it. I investigated a bit deeper, and turns out it actually works fine on previous versions of AX as well.

I am talking about 2 kernel functions for finding the maximum or minimum of the specified values.
The signature of these methods is shown on the below image:

As you can see, it takes 2 arguments of anytype, and returns an anytype which is the largest of the two values. But it can accept much more than 2 arguments, even though it is not documented as such.

I wrote a small job to showcase this behavior. The code is provided below. You can also download it from my SkyDrive Dynamics AX share.
static void Tutorial_MinMaxFunctions(Args _args)
{
#define.ArraySize(11)

Random rand = new Random();

int counter;
int arrayInt[#ArraySize];
str arrayIntAsString;
int arrayIntMaxValue;
int arrayIntMinValue;
;

for (counter = 1; counter <= #ArraySize; counter++)
{
arrayInt[counter] = rand.nextInt();
if (arrayIntAsString)
arrayIntAsString += ', ';
arrayIntAsString += int2str(arrayInt[counter]);
}
info("Generated array of integers: " + arrayIntAsString);

info("The typical way to find a maximum is by looping through all the values one by one, calling the comparison function multiple times");
arrayIntMaxValue = minint();
arrayIntMinValue = maxint();
for (counter = 1; counter <= #ArraySize; counter++)
{
arrayIntMaxValue = max(arrayIntMaxValue, arrayInt[counter]);
arrayIntMinValue = min(arrayIntMinValue, arrayInt[counter]);
}
info(strfmt("Max.value: %1 and Min.value: %2", int2str(arrayIntMaxValue), int2str(arrayIntMinValue)));

info("Using max and min with 11 arguments works just as well");
arrayIntMaxValue = minint();
arrayIntMinValue = maxint();
arrayIntMaxValue = max(arrayInt[1], arrayInt[2], arrayInt[3], arrayInt[4], arrayInt[5], arrayInt[6], arrayInt[7], arrayInt[8], arrayInt[9], arrayInt[10], arrayInt[11]);
arrayIntMinValue = min(arrayInt[1], arrayInt[2], arrayInt[3], arrayInt[4], arrayInt[5], arrayInt[6], arrayInt[7], arrayInt[8], arrayInt[9], arrayInt[10], arrayInt[11]);
info(strfmt("Max.value: %1 and Min.value: %2", int2str(arrayIntMaxValue), int2str(arrayIntMinValue)));

info("Note that comparing an integer and a real also works, as well as outputing the results straight into an infolog message");
info(max(12, 12.001));
}

Another interesting point is that it can actually accept different types of arguments, for example, a real and an integer, as shown above. And it actually returns an anytype, which implicitly gets converted to a string when sent to the infolog.

Disclaimer: Since this is not a documented feature, it can theoretically change in the future releases, but I doubt it in this particular case.

No comments:

Post a Comment