# FEEL Operators Explained

# Blog: Method & Style (Bruce Silver)

Although DMN’s expression language FEEL was designed to be business-friendly, it remains intimidating to many. That has led to the oft-heard charge that “DMN is too hard for business users”. That’s not true, at least for those willing to learn how to use it. Although the Microsoft Excel Formula language is actually less business-friendly than FEEL, somehow you never hear that “Excel is too hard for business users.”

One key reason why FEEL is more business-friendly than the Excel Formula language, which they now call Power FX, is its *operators*. FEEL has many, and Power FX has very few. In this post we’ll discuss what operators are, how they simplify the expression syntax, and how DMN boxed expressions make some FEEL operators more easily understood by business users.

It bears repeating that an expression language is not the same as a programming language. A programming language has statements. It defines variables, calculates and assigns their values. You could call DMN as a whole a programming language, but the expression language FEEL does not define variables or assign their values. Those things done graphically, in diagrams and tables – the DRD and boxed expressions. FEEL expressions are simply *formulas that calculate values*: data values in, data values out.

## Functions and Operators

Those formulas are based on two primary constructs: functions and operators.

The logic of a *function* is specified in the *function definition* in terms of inputs called *parameters*. The same logic can be reused simply by *invoking* the function with different parameter values, called *arguments*. The syntax of *function* *invocation* – both in FEEL and Excel Formulas – is the *function name* immediately followed by parentheses enclosing a comma-separated list of arguments. FEEL provides a long list of *built-in functions*, meaning the function names and their parameters are defined by the language itself. Excel Formulas do the same. In addition, DMN allows modelers to create custom functions in the form of Business Knowledge Models (BKMs) and decision services, something Excel does not allow without programming.

*Operators* are based on reserved words and symbols in the expression with meaning defined by the expression language itself. There are no user-defined operators. They do not use the syntax of a name followed by parentheses enclosing a list of arguments. As a consequence, the syntax of an expression using operators is usually shorter, simpler, and easier to understand than an expression using functions.

You can see this from a few examples in FEEL where you could use either a function or an operator. One is simple addition. Compare the syntax of the expression adding variables *a* and *b* using the *sum()* function

sum(a, b)

with its equivalent using the addition operator +:

a + b

The FEEL function *list contains()* and the *in* operator do the same thing, test containment of a value in a list. Compare

list contains(myList, "abc")

with

"abc" in myList

Both FEEL and Excel support the basic arithmetic operators like +, -, *, and /, comparison operators like =, >, or <=, and string concatenation. But those are essentially the only operators provided by Excel, whereas FEEL provides several more. It is with these more complex operators that FEEL’s business-friendliness advantage stands out.

## if..then..else

Let’s start with the *conditional operator*, *if..then..else*. These keywords comprise an operator in FEEL, where Excel can use only functions. Compare the FEEL expression

if Credit Score = "High" and Affordability = "OK" then "Approved" else "Disapproved"

with Excel’s function-based equivalent:

IF(AND(Credit Score = "High", Affordability = "OK"), "Approved", "Disapproved")

The length is about the same but the FEEL is more human-readable. Of course, the Excel expression assumes you have assigned a variable name to the cells – something no one ever does. So you would be more likely to see something like this:

IF(AND(B3 = "High", C3 = "OK"), "Approved", "Disapproved")

That is a trivial example. A more realistic *if..then..else* might be

if Credit Score = "High" and Affordability = "OK" then "Approved" else if Credit Score = "High" and Affordability = "Marginal" then "Referred" else "Disapproved"

That’s longer but still human-readable. Compare that with the Excel formula:

IF(AND(Credit Score = "High", Affordability= "OK"), "Approved", IF(AND(Credit Score = "High", Affordability = "Marginal"), "Referred", "Disapproved"))

Even though the FEEL syntax is fairly straightforward, DMN includes a *conditional boxed expression* that enters the *if, then, *and *else* expressions in separate cells, in theory making the operator friendlier for some users and less like code. Using that boxed expression, the logic above looks like this:

## Filter

The FEEL *filter operator* is square brackets enclosing either a Boolean or integer expression, immediately following a list. When the enclosed expression is a Boolean, the filter selects items from the list for which the expression is true. When the enclosed expression evaluates to positive integer n, the filter selects the nth item in the list. (With negative integer n, it selects the nth item counting backward from the end.) In practice, the list you are filtering is usually a table, a list of rows representing table records, and the Boolean expression references columns of that table. I wrote about this last month in the context of lookup tables in DMN. As we saw then, if variable *Bankrates* is a table of available mortgage loan products like the one below,

then the filter

Bankrates[lenderName = "Citibank"]

selects the Citibank record from this table. Actually, a Boolean filter always returns a list, even if it contains just one item, so to extract the record from that list we need to append a second integer filter [1]. So the correct expression is

Bankrates[lenderName = "Citibank"][1]

Excel Formulas do not include a filter operator, but again use a function: FILTER(table, condition, else value). So *if* we had assigned cells A2:D11 to the name *Bankrates* and the column A2:A11 to the name *lenderName*, the equivalent Excel Formula would be

FILTER(Bankrates, lenderName = "Citibank", "")

but would more likely be entered as

FILTER(A2:D11, A2:A11 = "Citibank", "")

FEEL’s advantage becomes even more apparent with multiple query criteria. For example, the list of zero points/zero fees loan products in FEEL is

Bankrates[pointsPct = 0 and fees = 0]

whereas in Excel you would have

FILTER(A2:D11, (C2:C11=0)*(D2:D11=0), "")

There is no question here that FEEL is more business-friendly.

## Iteration

The *for..in..return* operator iterates over an input list and returns an output list. It means for each item in the input list, to which we assign a dummy *range variable* name, calculate the value of the *return expression:*

for in return

It doesn’t matter what you name the range variable, also called the *iterator*, as long as it does not conflict with a real variable name in the model. I usually just use something generic like *x*, but naming the range variable to suggest the list item makes the expression more understandable. In the most common form of iteration, the *input list* is some expression that represents a list or table, and the *range variable* is an item in that list or row in that table.

For example, suppose we want to process the *Bankrates* table above and create a new table *Payments by Lender* with columns *Lender Name* and *Monthly Payment*, using a requested loan amount of $400,000. And suppose we have a BKM *Lender Payment,* with parameters *Loan Product *and *Requested Amount,* that creates one row of the new table, a structure with components *Lender Name* and *Monthly Payment*. We will iterate a call to this BKM over the rows of *Bankrates* using the *for..in..return* operator. Each iteration will create one row of *Payments by Lender*, so at the end we will have a complete table.

The literal expression for *Payments by Lender* is

for product in Bankrates return Lender Payment(product, Requested Amount)

Here *product* is the range variable, meaning one row of *Bankrates*, a structure with four components as we saw earlier. *Bankrates* is the input list that we iterate over. The BKM *Lender Payment* is the return expression. Beginners are sometimes intimidated by this literal expression, so, as with *if..then..else*, DMN provides an *iterator boxed expression* that enters the for, in, and return expressions in separate cells.

The BKM *Lender Payment* uses a context boxed expression with no final result box to create each row of the table. The context entry *Monthly Payment* invokes another BKM, *Loan Amortization Formula*, which calculates the value based on the adjusted loan amount, the interest rate, and fees.

Excel Formulas do not include an iteration function. Power FX’s FORALL function provides iteration, but it is not available in Excel. To iterate an expression in Excel you are expected to fill down in the spreadsheet.

The FEEL operators *some..in..satisfies* and *every..in..satisfies* represent another type of iteration. The range variable and input list are the same as with *for..in..return*. But in these expressions the *satisfies* clause is a Boolean expression, and the iteration operator returns not a list but a simple Boolean value. The one with *some* returns true if *any* iteration returns true, and the one with *every* returns true only if *all* iterations return true.

For example, again using *Bankrates*,

some product in Bankrates satisfies product.pointsPct = 0 and product.fees = 0

returns true, while

every product in Bankrates satisfies product.pointsPct = 0 and product.fees = 0

returns false. The iterator boxed expression works with this operator as well.

The bottom line is this: FEEL operators are key to its combination of expressive power and business-friendliness, surpassing that of Microsoft Excel Formulas. Modelers should not be intimidated by them. For detailed instruction and practice in using these and other DMN constructs, check out my DMN Method and Style training. You get 60-day use of Trisotech Decision Modeler and post-class certification at no additional cost.