NOTE: I come from a world where a function always returns a value and a procedure or method does not. In NAV all functions/methods/procedures are called functions, so I will be using that terminology even though I do not mean it in the more traditional sense.
Recently I discovered (quite by accident) this neat little feature in Dynamics NAV (not sure which version this became available in to be honest).
The basic overview is this. If you have a function that takes a single parameter, you can assign the value to the function as if it is a property, rather than using the normal function call syntax. Here is a rather silly example scenario*:
You have a global variable that controls whether or not validation logic should be skipped inside the INSERT trigger (even when manually calling for validation). This is required to be set outside of the table based on some external condition.
Screenshot #1 |
Screenshot #2 |
You create a single parameter function that sets this global variable to the passed in value.
Screenshot #3 |
The validation logic checks the global variable and skips the validation logic if it is set to true.
Screenshot #4 |
So we run this logic and we see the following.
Screenshot #5 |
And if we were to call SetSkipValidation(SomeConidtionThatIsFalse); we would obviously see the message “Doing validation…”.
There is the long winded, silly scenario. Now to the first point. The feature I am referring to is in the screenshot #2. We could change the line SetSkipValidation(SomeSpecialCondition); to instead read SetSkipValidation := SomeSpecialCondition; and it would run exactly the same as before.
Screenshot #6 (slight change from Screenshot #2) |
Now here is the second point, the gotcha. If the red-boxed area from screenshot #6 is syntactically legal, so to is this slightly different version of screenshot #3.
Screenshot #7 (slight change from screenshot #3) |
Can you spot the difference? Rather than assigning the SkipValidation global variable to the Skip parameter value, we are accidentally calling the SetSkipValidation function recursively. An easy mistake since the function name and the global variable name are so similar (SetSkipValidation vs. SkipValidation).
If the shortcut syntax did not exist, you would get a syntax error for trying to assign a value to a function. However, as we now know, this is legal for single parameter functions. So what you have here is a recursive call with no terminating clause. This results in an insufficient memory exception (a stackoverflow, the recursive version of an endless loop in a sense). Oops. Yes I have done this myself, which is how I found out about the feature in the first place (ironically, I read about it in Vjeko’s blog within a few days of this happening).
So there it is. An interesting little feature. Just be careful you’re not using it accidentally.
*If you’d like a more realistic example of a global variable controlling validation logic, one thing we do is as follows: When a purchase order has been released (a condition on the purchase header table), you are no longer allowed to change many fields in the purchase lines.For example, you cannot change the quantity. However, under certain conditions we want to bypass the logic that prevents changing the quantity. So we set a global suspend prevention variable to true, validate the quantity (we want to validate it in order for lots of other necessary logic to fire when the quantity is changed) and then set the suspend variable back to false.