Ratpack is built for Java and Groovy, but it works with the JVM, of course, with other languages like Kotlin and Scala. Here are some tips on what it would be like to write a Ratpack in Kotlin. If you have any better ideas, please share them in the comments.
Since Ratpack leverages Groovy's DSL, it has methods that take lambdas as arguments in many places. For example, the part that sets the handler on the server can be described as follows.
RatpackServer.start(spec -> {
spec.handlers(chain -> {
chain.get("index.html", ctx -> {
ctx.render(ctx.file("index.html"));
});
});
});
When Kotlin receives a lambda at the end of a method argument, it can write that lambda outside the parentheses. You can also use ʻit` as a placeholder for lambda arguments.
RatpackServer.start {
it.handlers {
it.get("index.html") {
it.render(it.file("index.html"))
}
}
}
It's inferior to Groovy, but you can write code with a DSL-like look.
Ratpack uses a functional interface called ʻActionin many parts. This is the Java 8
Consumerequivalent and is often used to configure something. For example, the
handlers () method that sets the handler on the server has ʻAction <Chain>
as an argument. We will set the URL and handler mapping in this chain, but as the number of handlers increases to some extent, we will want to divide this ʻAction. The split ʻAction
can be combined into one using the ʻappend () method. However, repeating ʻappend ()
many times makes it difficult to understand. I would like to use infix notation if possible.
Use Kotlin's Operator overloading to enable operator overloading.
operator fun <T> Action<T>.plus(other: Action<in T>): Action<T> = this.append(other)
fun createHandlers() = AccountAction() + HistroyAction() + // ...
Needless to say, overuse of operator overloads is strictly prohibited.
Pair
and Destructuring DeclarationMethods such as flatRight
in Promise
are relatively common and convenient methods for grouping multiple Promise
s together. The return type will be the Pair
type, which is a tuple in Ratpack.
Tuples are useful, but in unsupported programming languages (that is, Java) you have to use methods like left
, right
to get the value, which is sometimes an anti-pattern.
Kotlin does not support tuples themselves, but instead uses a feature called Destructuring Declaration to provide pseudo-tuples. This is a function that can be used by dividing each componentN ()
if each class has a componentN ()
(N is a number) method.
Of course, Ratpack's Pair
does not have acomponent1 ()
method, but by implementing it as an extension method, it is possible to perform pseudo split assignment.
operator fun <T> Pair<T, *>.component1(): T = this.left
operator fun <T> Pair<*, T>.component2(): T = this.right
Such old code splitting the Pair
authenticator.checkLoggedIn(ctx).flatRight {
ctx.parse(ReportParameter::class.java)
}.nextOp { pair ->
val user = pair.left
val parameter = pair.right
// (...)
}
You will be able to write like this.
authenticator.checkLoggedIn(ctx).flatRight {
ctx.parse(ReportParameter::class.java)
}.nextOp { (user, parameter) ->
// (...)
}
The regrettable point is that the IDE does not complement and you have to write the ʻimport` statement of the extension method yourself.
Recommended Posts