In the journey to build a good useful language, we decided to enforce consistency wherever we can.
That’s one of the three rules we have in the team.

  • Consistency
  • Fix the broken window
  • Zero support scalation policy

To achieve this, one of the fundamental steps was to get rid of the hardcoded operators. Before this, functions such as map reduce filter were reserved words of language. That made the language very little extensible and made the fixes were scarce, because we had to deliver the whole product to fix an error.
At the same time, we had to maintain consistency with DataWeave 1.0, because we couldn’t afford to let users learn the new version from scratch.
That’s why we introduced the infix functions. These are normal functions, which can be used between arguments instead of being a prefix.

So now

Because map is now a function.

How do we create infix functions?

It is really easy indeed, it is just a function.

That script returns a value "Hello world!".

When we wanted to make map become a function, we found that it was overloaded for Ranges and Arrays. In that moment we decided to implement function overloading in the language.

Outputs

1
[ "Hello world!", 3 ]

Chaining

We knew that precedence was a complicated thing in DataWeave 1.0, people spent their time fixing their scripts using dozens of parenthesis. We decided to solve it by unifying precedence in a simple way.
All that is on the left side of an Infix operator is the first argument, and the first expression on the right side is the second.

But wait, what is the dollar sign?

It is an argument of an automatic function injection. I explain it in detail here

We are still missing a mechanism to replace core functions like map

Previously, we had no way to iterate over arrays or objects. The language itself did not provide any mechanism to do that. We decided to implement tail call functions to solve that problem.

Briefly, it allows us to create streamable recursive functions, and that’s really important due the async nature of DataWeave.

We use tail recursion to create lazy generators, a good example could be a sequence generator.

Here is an example of tail call and async generators using this feature. It is a prime number finder using DataWeave.

Going back to the map function, in DataWeave 1.0 it was a Scala binding. It was a hardcoded operator in the language. Right now we can implement the map function directly in DataWeave, without external bindings. It looks like this