If our users work with formulas and arithmetic expressions all day, providing syntax that is natural for them will be a big win.
Suppose our users want to key in an expression to multiply 4 + 3 with 5 - 2. As programmers, we would readily write that expression with +, *, and (), like so:
| (4 + 3) * (5 - 2) |
Yep, but that’s not how our mathematical friends write that. They would instead write:
| (4 + 3) (5 - 2) |
Try sending that to the compiler, and watch it cry and complain. Well, that’s true in most programming languages—but Kotlin is special.
Kotlin has a special function called invoke() that allows an object to be treated like it’s a function. Look at the following, for example:
| "test check the operator precedence"() { |
| //... |
| } |
This is a valid syntax in Kotlin if the String class has a function named invoke() that is marked as an operator. In effect, if the compiler finds either a function or an operator extension function named invoke(), then it will automatically convert the previous call to the following:
| "test check the operator precedence".invoke() { |
| //... |
| } |
We can apply this convention to implement the arithmetic expression without the need for *, like so:
| operator fun Int.invoke(operand: Int) = this * operand |
| |
| println((4 + 3) (5 - 2)) |
The compiler replaces internally the expression passed to println() to:
| (4 + 3).invoke(5 - 2) |
The + is evaluated first, and the - is evaluated second. The partial results from these two computations are then used, the first as a target or receiver to invoke() and the second as an argument to that function. Here’s the result of executing our example code:
| 21 |
With a little bit of effort, we can get rid of unnecessary programming syntax when evaluating expressions and provide a more natural, domain-specific syntax for our users.
So far we’ve seen how to increase fluency and make DSLs intuitive to use by leveraging the low ceremony of the language and adding domain-specific functions and operators. Next we’ll see how to manage the execution context of code within DSLs.
18.209.229.59