Kotlin DSL | Coding a DSL: 5 — plus and minus operators and inline functions
Overloading plus and minus operators and high-order functions optimization with the inline modifier
You can go to any article of this series by clicking on one of the links below:
Kotlin DSL
- Introduction
- Base knowledge to build a DSL in Kotlin — Part 1
- Base knowledge to build a DSL in Kotlin — Part 2
- Codebase: Project Shapes-DSL
- Coding a DSL: 1 — Package structure and the ‘Panel’ object
- Coding a DSL: 2 — The ‘Square’ object
- Coding a DSL: 3 — The ‘Triangle’ and ‘Rhombus’ objects
- Coding a DSL: 4 — The ‘Empty Space’ and the ‘Composed Shape’ object
- Coding a DSL: 5 — plus and minus operators and inline functions
- Coding a DSL: 6 — The @DslMarker annotation
- Experimenting and conclusions
In the previous article, we defined space
and composed
functions which add “empty spaces” and composed shapes to the Panel respectively. We also created infix functions to create composed shapes in a more idiomatic manner. At the end of the previous article, the main
method’s content looked like this:
In this article, we will overload +
and -
operators to merge shapes with an arithmetic-like notation. At the end of this article, the main
method’s content should look like this:
Overloading operators ‘plus’ and ‘minus’
In order to overload +
y -
operators, we have to define 2 functions with the reserved names plus
and minus
respectively. The +
operator corresponds to the union
operation. The -
operator corresponds to the intersection
operation. To achieve the same behavior, we can make it either by copying both implementations or by invoking union
and intersection
functions inside these new functions. To avoid code duplication, we’ll go with the latter. Their signatures should look as follows:
operator fun Shape.plus(shape: Shape): ComposedShape
operator fun Shape.minus(shape: Shape): ComposedShape
💬 Let me remind you that in order to overload an operator, the function declaration must be preceded by the
operator
modifier.
plus
function must invoke union
function. Similarly, minus
function must invoke intersection
function.
Go to console_shapes_dsl.external
package and add the following code to the Extension.kt
file:
▶️ If you run the code, you’ll see that it works again.
Finally, we have achieved our goal. We have created a DSL to replace the initial code…
…with a more idiomatic one…
Although our DSL is ready to be used, there’s one more thing left to do to improve it a little bit.
Optimization
In the article Base knowledge to build a DSL in Kotlin — Part 2, I showed how inline functions work and why sometimes they are necessary.
To improve our DSL performance, we can mark our functions with the modifier inline
. I mentioned 3 indicators to consider making a function inline. These indicators are:
— It’s a high-order function.
— It’s not larger than 4 lines of code.
— It’s invoked repeatedly.
panel
, square
, triangle
, rhombus
and composed
functions comply with the the first two indicators. Since these functions are not invoked repeatedly, marking them with the modifier inline
wouldn’t make any difference in terms of performance. However, we are going to pretend that we have a use case where adding shapes in a loop is required, just for illustration purpose.
Go to console_shapes_dsl.external
package and open the Extension.kt
file. Mark panel
, square
, triangle
, rhombus
and composed
with the modifier inline
. These functions should look as follows:
▶️ You can run the code; however, you won’t notice a performance gain. This change is merely symbolic and just for illustration purpose.
Although we already have a functional DSL, there’s still a very important detail that you must take into account and that has to do with restricting the scope within lambdas, but I will cover that in the next article.
Continue with the next article Coding a DSL: 6 — The @DslMarker annotation
💬 If you enjoyed this article, you can show your appreciation by buying me a coffee at the link below. Thanks for reading and for your support.
- 📖 You can learn about High-Order Functions on Kotlin’s official documentation at https://kotlinlang.org/docs/lambdas.html
- 📖 You can learn about Lambdas with Receivers on Kotlin’s official documentation at https://kotlinlang.org/docs/lambdas.html#function-literals-with-receiver
- 📖 You can learn about Scope Functions on Kotlin’s official documentation at https://kotlinlang.org/docs/scope-functions.html