DEV Community 👩‍💻👨‍💻

Gauthier POGAM--LE MONTAGNER
Gauthier POGAM--LE MONTAGNER

Posted on

DataWeave: accept lambda as parameter of a function

When writing DataWeave code, it is common to use functions that take a lambda as parameter, such as map or flatten. Using lambda in DataWeave is well documented and easy to understand for developers that already worked with functional programming in other languages.

However, creating a DataWeave function that accepts a lambda as parameter, while relatively easy, is not well documented in Mulesoft' documentation.

As creating functions taking lambda as parameters can be very useful, I will explain how to pass a lambda as parameter of a function. Common use cases are to accept a callback or apply a transformation or a predicate passed as a parameter.

What is a lambda?

In functional programming, data are immutable and thus cannot be modified. To change a value, we do not modify it directly. Instead, the value is processed and a new value defined.

%dw 2.0
var initialValue = 21
// Error: a variable cannot be modified after its declaration
var newValue = 42
// Success: a new variable is created containing the new value.
var newValue = 42 * 2
Enter fullscreen mode Exit fullscreen mode

Arrays follow the same principle and their values cannot be modified. Instead, we will use functions that applies some behaviour to each element. This behaviour is defined in a lambda, a function without a name that can be saved in a variable or passed as a parameter.

%dw 2.0
var initialValue = [1, 2, 3]

var newValue = initialValue map ((value) -> value * 2)
newValue // [2, 4, 6]
Enter fullscreen mode Exit fullscreen mode

In the example above, (value) -> value * 2 is a lambda that takes the existing value and multiply it by 2. This function is passed as a parameter of map.

DataWeave allows a lambda to you anonymous parameters, and to be passed without being surrounded by variables. This shorten the code and can make it more clear. The following line does the same thing as its equivalent above:

var newValue = initialValue map $ * 2

For more information, refer to Mulesoft's documentation.

Taking lambdas as parameters

To write a function that accepts a lambda as parameter, you need two things:

  1. Define the parameter and type it so it is clear it accepts a lambda.
  2. Call the lambda and give it the required parameters.

To define and type the parameter, you must specify the parameter name and the signature of the function it accepts:

helloNewYear(lambda: (param1: String, param2: Number) -> String) = ...

In this example, we declare a function helloNewYear that accepts one parameter: a lambda. This lambda should be a function accepting a String and a Number as parameter, and returning a String.

Once we have our parameter, we need to call it. It is called in the same way as any other function, taking the parameter name as function name:

helloNewYear(lambda: (param1: String, param2: Number) -> String) = lambda("Hello", 2022)

Now, we can call our function and pass it the lambda we want to execute:

helloNewYear((sentence, year) -> sentence ++ " " ++ year)

This will output "Hello 2022". Your lambda can contain any behaviour you wish to define.

Code Example

%dw 2.0

// Processing function that takes a lambda as parameter
fun updateEvenCharacters(
    str: String,
    // The type of the parameter is the expected signature of the lambda to call
    mapper: (str: String, num: Number) -> String
): String =
    str splitBy ""
        // The lambda is called as a normal function, with the parameter name being the function name
        map (if (isEven($$)) mapper($, $$) else $)
        joinBy ""

output text/plain
---
// Call the processing function and pass a lambda as second parameter 
updateEvenCharacters(
    "Hello World!",
    // The parameter should be the lambda to call.
    (value, index) ->  upper(value) ++ index
)
Enter fullscreen mode Exit fullscreen mode

__

Top comments (0)

An Animated Guide to Node.js Event Loop

>> Check out this classic DEV post <<