Analytics

Monday, July 5, 2010

Apply Groovy Curried Closures and Composition to Business Rules

Groovy offers new programming idioms
Groovy is a language that operates on the Java platform and is completely compatible with Java.  Many of its features are easily grasped by Java programmers attempting to learn the language. For example, Groovy automatically provides getters and setters for attributes on objects, treats numbers and strings as first class objects, and offers a myriad of programming shortcuts (like << to add to a list or [:] to create a map).

Closures are easy to understand

However, Groovy also contains programming idioms that are not customary in the Java world.  These concepts are borrowed from other languages and empower Groovy to be very effective and dynamic in solving business problems.  The concept of closures is one example.  Closures are a prime feature in Groovy, but do not exist in Java (although Java 7 is scheduled to contain closures). A closure is a defined block of code that can be passed around and executed at a later point.  They are commonly used when iterating over collections, and they eliminate much of the code noise that comes with Java iteration.  With some effort, closures in their most common application are fairly simple to grasp.

More complex Groovy idioms

Some concepts are more foreign to the conventional Java programmer. Curried closures are an extension to the concept of closure.  Currying a closure takes a little more effort to understand and is certainly not a concept common to Java.  Groovy also allows for composition of closures, where closures are combined together so that closures operate on other closure results.  These techniques are part of the functional programming paradigm which emphasizes the application of functions, rather than methods conducting state changes on data.  Haskell, Schema, and Erlang are functional programming languages.  Through an example, this article will demonstrate how curried closures and composition can be applied to solving business world problems.

Curry Definition

First let's define what a curried function is. The term curry comes from the mathematician Haskell Curry who developed the concept of partial functions.  In functional programming, currying a function means transforming a function into another function by fixing some of its input arguments.  Currying is good for mathematical business problems where you need to break the problem down into pieces.  Essentially, you have a template mathematical formula and you can assign fixed values to a portion of the formula to create new version of the template. A simple math example follows:

f(x, y) = x / y   ---- template
f(x, 2) = x / 2   ---- curry with fixed value
g(x) = f(x, 2)   ---- this is the new curried function
g(10) = 10 / 2 = 5

Function Composition Definition

Function composition is the application of one function to the result of the other.  Using composition, two or more functions can be combined to produce a more elaborate one.  A simple examples follows:

f(x) = x * 2
g(y) = y / 100
f(g(y)) = (y / 100 ) * 2

Investment Business Problem #1

Let's define a business problem that would be interesting to solve with Groovy using curried closures and function composition.  One we clearly see the problem definition, we can apply the programming concepts and illustrate the power of its usage.  

Bob wants to invest some money for retirement. He is 55 years old and will retire at 65.  He has $5000 total to play with.  He has found an investment vehicle that will deliver 8% interest every year for 10 years (compounded once a year). He is not sure whether to invest all of the $5k or only a portion of it.  He wants to see the difference. 

Used a Curried Closure 

Recall that in Groovy, we can create closures which are basically passable functions.  Here we can create a closure that encapsulates the investment formula. 

def interestFormula = { r, y, p -> p * Math.pow(1+(r), y) }

In order to reduce the formula to a specific context, we can replace some of the variables with fixed values.  Currying will carry out this task. Then we can reuse the closure to test out various principle investments.  


package curry.blog

def interestRate = 0.08
def years = 10
def principle1 = 3000
def principle2 = 5000

// create current investment from interest formula with set rates and 
// see what differences in savings will pay off
// years down the road
def interestFormula = { r, y, p -> p * Math.pow(1+(r), y) }
def invest = interestFormula.curry(interestRate, years)

println "invest ${principle1} and return: " + invest(principle1) 
println "invest ${principle2} and return: " + invest(principle2)

From the example above, the output is:

invest 3000 and return: 6476.7749918183645
invest 5000 and return: 10794.62498636394

Clearly, Bob can see that $5k investment returns almost $4k more than a $3k investment. If he can afford to put all $5k for retirement, it would pay off well. 

Investment Business Problem #2

Now we are ten years down the line, and Bob is ready to liquidate his investment.  However, he encounters a money savy friend who says he found a firm that will rollover his retirement fund and actually pay him 10% to manage his money. In order to rollover his retirement account, he must pay the existing firm $100.  Thus, Bob is considering liquidating his account and paying the government 30% tax to keep his money, or continue to invest by rolling over and gaining 10%, essentially deferring his taxes until later.  He wants to evaluate his initial $5k investment against the different paths he can take.

Used a Curried Closure and Composition 

We can create a closure to represent money after tax is applied.  We can then curry it to be specific to the 30% tax bracket.

def taxFormula = {  t, p ->; p * (1 - t) }
def applyTax = taxFormula.curry(taxRate)

For a rollover, we can create a simple closure as well. No currying necessary here as there is only on variable.

def doRollover = { z -> (z - rollOverFee) * (1 + rollOverMatching) }

Bob wants to compare the situation where he liquidates against when he reinvests.  A composition closure addresses this nicely.  We can create a composition template where you can apply different actions after the investment is liquidated.  Curry the composition with the investment closure, then leave the other variables open for the principle and the action.  Essentially the resulting closure does the investment result for you, then applies the various actions to the result.

def composition = {g, x, f -> f(g(x)) }
def considerPostInvestmentAction = composition.curry(invest)

See the entire Groovy script.  considerPostInvestmentAction calculates the investment, then tells you what the result is after you liquidate it and pay taxes, or roll it over.  It can accept a closure and an initial principle. The closure passed in represents the action taken on the liquid value, either tax applied or a rollover.  Bob can compare the differences.


package curry.blog

def interestRate = 0.08
def years = 10
def taxRate = 0.30
def principle2 = 5000
def rollOverFee = 100
def rollOverMatching = 0.10

def interestFormula = { r, y, p -> p * Math.pow(1+(r), y) }
def invest = interestFormula.curry(interestRate, years)

// tax formula which tells you how much you will have after taxes
def taxFormula = {  t, p -> p * (1 - t) }
// curry it with the tax Rate
def applyTax = taxFormula.curry(taxRate)
// formula for rollover; the amount you will have after rollover
def doRollover = { z -> (z - rollOverFee) * (1 + rollOverMatching) } 
// template for functional composition
def composition = {g, x, f -> f(g(x)) }

// use composition and currying to allow you apply a function on top of your 
// investment after you sell it. Thus you can decide 
// whether to pay taxes and keep the income, or roll over into another account
def considerPostInvestmentAction = composition.curry(invest)

println "initial investment is ${principle2}. After taxes it is: " + considerPostInvestmentAction(principle2, applyTax)
println "initial investment is ${principle2}. After rollover it is: " + considerPostInvestmentAction(principle2, doRollover)
The print lines reveal:


initial investment is 5000. After taxes it is: 7556.237490454758
initial investment is 5000. After rollover it is: 11764.087485000335 

Should Bob have the ability refrain from liquidating his investment, he can gain big. His $5k turns into ~$12k.  And he can hope that later down the line, he will be in a lower tax bracket and he can keep more of his money.  If he withdraws now, he is still in the 30% tax bracket and his investment only comes back with ~$7500. 

Conclusion

This business problem can certainly be solved with conventional Java paradigms. However, Groovy is rich in features as well as programming idioms.  Groovy gives the developer a chance to solve programs in a concise, elegant fashion.  If a business problem has functional and mathematical qualities, consider functional programming to solve the issue.

1 comment:

  1. My Rank, the only portal which offers jee mains online practice test with unlimited chapter wise practice test along with ask your query and live chat options. The portal is also loaded with WhiteBoard (live online classes by IITian faculty)

    ReplyDelete