Contents > 9 Extending the Metrics and Rule Engine > 9.5 Scalar Functions

9.5 Scalar Functions

A scalar function is used in metric expressions (see Section 8.5 "Expression Terms") and yields a numerical value, a string value, or a model element. In the following example, we will implement a function that yields the maximum value from a list of numerical values, e.g., in a metric expression like this:
```  max(NumClasses, NumInterfaces, NumUseCases)
```
The following implementation of the MAX function calculates the value of each argument provided to the function, and returns the maximum value:
```   packacke com.acme;
import com.sdmetrics.math.ExpressionNode;
import com.sdmetrics.metrics.MetricTools;
import com.sdmetrics.metrics.SDMetricsException;
import com.sdmetrics.metrics.ScalarOperation;
import com.sdmetrics.metrics.Variables;
import com.sdmetrics.model.ModelElement;

01 public class ScalarOperationMax extends ScalarOperation {

@Override
02 public Number calculateValue(ModelElement element, ExpressionNode node,
Variables vars) throws SDMetricsException {

03    float result = Float.NEGATIVE_INFINITY;
04    for (int index = 0; index < node.getOperandCount(); index++) {
05      float value = ((Number) evalExpression(element,
node.getOperand(index), vars)).floatValue();
06      result = Math.max(result, value);
}
07    return MetricTools.getNumber(result);
}
}
```
Again, we discuss the implementation line by line:
• 01: The class must have public visibility, a standard constructor, and extend the abstract class com.sdmetrics.metrics.ScalarOperation.
• 02: Like Boolean functions (Section 9.4.2 "Implementation of the Boolean Function"), the base class defines an abstract method calculateValue, with identical input parameters. The return value of the method is of type Object, and provides the value of the scalar function. Since our MAX function deals with numerical values, we have narrowed the return type to Number. Other acceptable return types are Integer, Float, String, or ModelElement.
• 05: Method evalExpression evaluates metric expressions. We use it to calculate the values of the arguments passed into the MAX function, one by one. Method evalExpression returns instances of Object. Since we expect the arguments to our MAX function to be numerical, we cast the result to Number and take its float value.
• 07: Static method MetricTools.getNumber(float) wraps the given float value into an Integer if it is small enough and has no fractional part, or else into a Float.
To use the scalar function, we register it with the metrics engine as follows:
```<scalaroperationdefinition name="max"
class="com.acme.ScalarOperationMax" />
```
As with Boolean functions, we deploy the class file of the class in the "bin" folder of our SDMetrics installation (path com/acme/ScalarOperationMax.class). After that, we can write metric expressions using the new function. For example:
```<metric name="DominantElementTypeSize" domain="package">
<description>Size of the package in terms of the number elements
of the most dominant type in the package.</description>
<compoundmetric
term="max(NumClasses, NumInterfaces, NumDataTypes, NumUseCases)" />
</metric>
```