Skip to main content
Known Participant
September 28, 2023
Question

Recursive expression rule

  • September 28, 2023
  • 4 replies
  • 0 views

The expression rule below should return a list of dictionary containing loanAmount and monthlyPrincipal. It gives me a strange Expression evaluation error : with no specific errors.

If I change ri!loanAmount <= 0, to be ri!loanAmount <= 28824, it works for some reason. Not sure why and not sure what's going on.

This rule has a rule input called ri!loanAmount of type number(decimal) which I am testing with 100000 as a test scenario to make this work. 

Any ideas what's going on? If there are any other ways to get this to work without doing recursion, please let me know.

a!localVariables(
  
  local!principalPayment: 100000,
  local!interest: 15,
  local!loanTermYears: 30,
  local!periodicInterestRate: (local!interest/100)/12,
  local!periodicInterestRateModified: 1+local!periodicInterestRate,
  local!periodicInterestRateModifiedToPower: power(local!periodicInterestRateModified, local!loanTermYears*12),
  local!xx: local!periodicInterestRateModifiedToPower - 1,
  local!xxx: local!periodicInterestRate*local!periodicInterestRateModifiedToPower,
  local!monthlyPayment: local!principalPayment / (local!xx / local!xxx),

  local!monthlyPrincipal: local!monthlyPayment - (ri!loanAmount * local!periodicInterestRate),
  if(
    ri!loanAmount <= 0,
    {},
    {
      {
        loanAmount: ri!loanAmount - local!monthlyPrincipal,
        monthlyPrincipal: local!monthlyPrincipal,
      },
      rule!LO_recursiveRule(
        loanAmount: ri!loanAmount - local!monthlyPrincipal
      )
    }
  )
)

Second approach to indicate the number of iterations. Here I am using local!loanTermMonths to stop the recursion. It works until 26 (Starting from 360 going down) but if I change to 25 or less, it breaks with same error. So that's 334 iterations.

a!localVariables(
  
  local!principalPayment: 100000,
  local!staticLoanTerm: 360,
  local!interest: 15,
  local!loanTermMonths: ri!loanTermMonths,
  local!periodicInterestRate: (local!interest/100)/12,
  local!periodicInterestRateModified: 1+local!periodicInterestRate,
  local!periodicInterestRateModifiedToPower: power(local!periodicInterestRateModified, local!staticLoanTerm),
  local!xx: local!periodicInterestRateModifiedToPower - 1,
  local!xxx: local!periodicInterestRate*local!periodicInterestRateModifiedToPower,
  local!monthlyPayment: local!principalPayment / (local!xx / local!xxx),

  local!monthlyPrincipal: local!monthlyPayment - (ri!loanAmount * local!periodicInterestRate),
  if(
    local!loanTermMonths = 26,
    {},
    {
      {
        loanAmount: ri!loanAmount - local!monthlyPrincipal,
        monthlyPrincipal: local!monthlyPrincipal,
      },
      rule!LO_calculateAmortizationSchedule(
        loanAmount: ri!loanAmount - local!monthlyPrincipal,
        loanTermMonths: local!loanTermMonths-1
      )
    }
  )
)

This one does work (it is less number of iterations because instead of 360 months I am doing half (180).

a!localVariables(
  
  local!principalPayment: 100000,
  local!staticLoanTerm: 180,
  local!interest: 15,
  local!loanTermMonths: ri!loanTermMonths,
  local!periodicInterestRate: (local!interest/100)/12,
  local!periodicInterestRateModified: 1+local!periodicInterestRate,
  local!periodicInterestRateModifiedToPower: power(local!periodicInterestRateModified, local!staticLoanTerm),
  local!xx: local!periodicInterestRateModifiedToPower - 1,
  local!xxx: local!periodicInterestRate*local!periodicInterestRateModifiedToPower,
  local!monthlyPayment: local!principalPayment / (local!xx / local!xxx),

  local!monthlyPrincipal: local!monthlyPayment - (ri!loanAmount * local!periodicInterestRate),
  if(
    local!loanTermMonths = 0,
    {},
    {
      {
        loanAmount: ri!loanAmount - local!monthlyPrincipal,
        monthlyPrincipal: local!monthlyPrincipal,
      },
      rule!LO_calculateAmortizationSchedule(
        loanAmount: ri!loanAmount - local!monthlyPrincipal,
        loanTermMonths: local!loanTermMonths-1
      )
    }
  )
)

4 replies

stefanhelzle0001
Brainy
September 28, 2023

Did you try to create a extremely simplified version of this first? Like starting with 100 and subtract 10 in each iteration. Then get the recursion end statement right and make things more complicated.

Known Participant
September 28, 2023

I tried that and in the simplified version it was working. I incremented iteration slowly and it started t fail at 28824 and I don't understand why. I confirmed with the simplified version that the rule is working correctly.

stefanhelzle0001
Brainy
September 28, 2023

You mean that you had 28824 recursive calls? If yes, I think you are bouncing into some memory limits or other guardrails.