We don't know when 'Xplan Administrator Appreciation Day' is, maybe its already been this year? Maybe its coming up? In either case, to cover our bases (because surely such a day exists) we started braining storming ideas for things we could do to add some efficiency and ease into the role of the Xplan Administator.
XMERGE Functions – building blocks of powerful xplan templates
October 22, 2015 | matthew-townsend
Let’s talk about a powerful programming concept
Functions are going to let you take the next step in improving your xmerge coding and creating a solid design base that can be used throughout all your templates. At a high level, some of the benefits of these include:
Reducing duplication of code – write once use many
Increasing core code reusability
Improving the readability and clarity of your code
Consistency and error handling
Base framework for all your coded templates
What are functions
In programming, functions are self-contained blocks of code that perform a specific task. They effectively remove the need for you to constantly re-write or hard code the same thing, each time you want to use it. Another great benefit of functions is the ability to handle dynamic arguments or parameters so they can be even more flexible 🙂
A broad example
Let’s take an Australian Business Number (ABN), typically represented in the following format: 51 824 753 556
Seems simple..but in software – like xplan – unique numbers may actually be stored in the database as integers; which means no spaces or pretty formatting between the digits (51824753556). Rather than hard coding how the number should display each time its needed, a function would be written once so that whenever an ABN was displayed it would show the correct formatting.
What about in xmerge
Xmerge has a range of built in functions that you are likely already using often:
- Function name is ‘currency’ also how we invoke it in the code
- Argument 1 – the value amount that we want to output
- Argument 2 – number of decimal places we want output
Behind the scenes, the currency function is taking our two arguments or parameters, converting the value it and limiting the output to the number of decimal places we specified – reducing our work and allowing is to re-use it over and over again.
We also have the benefit of knowing the currency function has optional arguments built in. You can also check out this article and see how the built in floatify makes things a lot than repeating it all throughout our document.
Creating our own functions in xmerge
In Xmerge we’re a little constrained and can’t create functions in the full sense of the word, but we can utilise lambda to create function equivalents, which still have the same benefits mentioned earlier.
Structure of xmerge lambda functions
Remember, the idea of functions is to be able to reuse them, again and again, just with different inputs:
Function = lambda argument1: expression or condition using argument1
In practice, we would define a function first, like this:
<:let prefName = lambda x: str(x.preferred_name):>
- Function name in this case is ‘prefName’
- Argument 1 – This is really our input and we’ve just called it ‘x’. In this case it doesn’t really matter what value you use here for the parameter. Commonly though you will see val, x, y etc.
- Output – whatever x is we want it to return x’s preferred name
We could then call (invoke) it anytime in our template like this:
<:=prefName($client):> & <:=prefName($partner):>
You can see the function returns the value based on the argument passed to it, in this case $client (x.preferred_name) or $partner (x.preferred_name) we get the desired result for each input.
There’s a reason we did the article on ternary operators previously, because if we take the knowledge from that and apply it to our use of lambda, we can create a much more powerful name function that will account for all types and kinds.
<:let entityName=lambda x: str(x.preferred_name) if x.is_individual and x.preferred_name else str(x.first_name) if x.is_individual else str(x.superfund_name) if x.is_superfund else str(x.trust_name) if x.is_trust else str(x.company_name) if x.is_company else str(x.partnership_name) if x.is_partnership else str(x.entity_name):>
While the above might lose points for readability, it packs a lot of positive trade offs:
- Its highly functional, in that it will produce a result for every entity type;
- It’s dynamic for each entity and their actual name (rather than just relying on x.entity_name) and its error resistant for individuals in the event they don’t have a preferred name;
- Unlikely it would need to be changed;
- Can be used across everything, letters to entire advice documents can reuse this function and this approach;