We would like to thank MuleSoft Ambassador Joshua Erney for their contribution to this developer tutorial.
In the previous tutorial, we used the filter
function to explain how high-order functions work, we’ll use this opportunity to learn another concept alongside this function. In this tutorial, we’ll go through an interesting topic: generics (or type parameters in DataWeave).
If this is your first time learning about DataWeave, we encourage you to check out this other tutorial to learn about the online DataWeave Playground. With this tool, you will be able to try out the scripts you will see in this tutorial right from your browser.
When dealing with functions, it’s important to know what kind of data is valid input, and what to expect as output. For example, we know that the valid inputs to filter are an Array and a lambda, and it outputs an Array. However, this isn’t quite descriptive enough because there is another function to be accounted for, the lambda. The lambda takes in two arguments: a single item of type Any, and an index of type Number. It returns a Boolean. We can use a syntax that is very close to DataWeave to define this.
Prefix notation
Infix notation
While the above signature is correct, it’s not as precise as it could be. Array<Any>
could be Array<Number>
, Array<String>
, Array<Object>
, etc. If you pass an Array<Number>
to filter
, it can not return Array<String>
, it can only return Array<Number>
. In addition, if you pass an Array<Number>
to filter, the first parameter passed to the lambda could not be String either, it would have to be Number. Here’s a concrete example. You can mess with the code all you want, but you will never find a situation where filter
does not adhere to the signature defined above.
How do we define this kind of relationship between the parameters’ types of a function? We use generics.
In the syntax above, T
serves as a type variable. T
could be any type at all, but it must be the same throughout the signature. In other words, this signature is a guarantee that if you pass Array<Number>
to filter
, the first parameter to the lambda will be type Number, and the output will be Array<Number>
as well. If you’re familiar with generics from other languages like Java or Scala, this should look familiar.
We’ve now arrived at our final type signature of filter
. In conclusion, this: filter(Array<T>, ((T, Number) -> Boolean)): Array<T>
is shorthand for, “filter
is a function that takes 2 input parameters. The first parameter is an Array containing items of type T
. The second parameter is a function. The function takes T
as the type of its first parameter, and Number
as the type of its second. It returns a Boolean
. The filter
function returns an Array containing items of type T
.” As you can see, the type signature allows us to say a lot about a function without needing to write a whole paragraph about it!
Notice that this type definition does not provide any semantic information on what the types represent. It doesn’t tell us anything about why the T
in Array<T>
, and the T
that is the first input to the function are the same, it only tells us that they must be the same. It doesn’t tell us Number represents the index of the item the function is currently processing. It doesn’t tell us the Boolean value is used to determine if an item is removed from the input Array or not.
Now that you know how to use type parameters in DataWeave (or generics) you’ll be able to read the documentation directly whenever you need to search for a function’s syntax or its definition. In this tutorial, we made examples using the filter
function, but generics are used in more DataWeave functions.
Now that you understand the basics of the language, continue your development journey with the rest of the DataWeave tutorials to become a master in DW.
Start your 30-day free trial of the #1 platform for integration, APIs, and automation. No credit card required. No software to install.
Questions? Ask an expert.