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.
While the above signature is correct, it’s not as precise as it could be.
Array<Any> could be
Array<Object>, etc. If you pass an
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.
1 2 3 4 %dw 2.0 output application/json --- [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] filter (n) -> n > 5
1 2 3 4 5 6 7 [ 6, 7, 8, 9, 10 ]
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
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
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
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.