https://medium.com/makingtuenti/infix-functions-in-kotlin-2db3d3142dd2
https://www.programiz.com/kotlin-programming/infix-notation
https://github.com/http4k/http4k/blob/master/http4k-core/src/main/kotlin/org/http4k/routing/routing.kt
Say we have enums that represents the shapes of the cards.
1 2 3 4 5 6 |
enum class Suit { HEARTS, SPADES, CLUBS, DIAMONDS } |
We also have enums that represent the numbers (or ranking) of the cards.
1 2 3 4 5 |
enum class Rank { TWO, THREE, FOUR, FIVE, SIX, SEVEN, EIGHT, NINE, TEN, JACK, QUEEN, KING, ACE } |
1 |
data class Card(val rank: Rank, val suit: Suit) |
In order to create a card we have to do the following:
1 |
val card = Card(Rank.QUEEN, Suit.HEARTS) |
We can simplify the way of creating a new card so we’re going to add a function called of to Rank
For enum class Rank, we create a function called of.
It takes in a parameter of Suit object.
1 2 3 4 5 6 7 |
enum class Rank { TWO, THREE, FOUR, FIVE, SIX, SEVEN, EIGHT, NINE, TEN, JACK, QUEEN, KING, ACE; fun of(suit: Suit) = Card(this, suit) } |
We declare that our function takes in parameter of type Suit. When we instantiate Card, we use this to reference our Rank object, and then just have the user pass in suit
Then just use it like so:
1 |
val card = Rank.QUEEN.of(Suit.HEARTS) |
‘this’ references Rank.Queen
‘suit’ references Suit.Hearts
We can still improve it if we use static imports for QUEEN and HEARTS to get the card creation closer to natural language. So you put the class enum in another class file.
For example, without static imports, we’d have to go
1 2 3 |
Math.sqrt(4) Math.pow(2,2) Math.abs(6.3) |
But WITH static imports, we don’t always have to reference Math anymore.
1 2 3 4 5 6 7 8 9 |
import static java.lang.Math.*; class Test2 { public static void main(String[] args) { System.out.println(sqrt(4)); System.out.println(pow(2, 2)); System.out.println(abs(6.3)); } } |
Hence, in our example, we can use static imports to simply access the enums value themselves:
1 |
val card = QUEEN.of(HEARTS) |
This is much better, but we can do more.
Let’s convert the of function in an infix function. We only have to add the reserved word infix at the beginning of the function:
1 2 3 4 5 6 7 |
enum class Rank { TWO, THREE, FOUR, FIVE, SIX, SEVEN, EIGHT, NINE, TEN, JACK, QUEEN, KING, ACE; infix fun of(suit: Suit) = Card(this, suit) } |
An infix function add to the function the ability to use it with infix notation.
We can now do this:
1 2 3 4 |
// We call function 'of'. // QUEEN is parameter 'this' // HEARTS is the parameter suit val card = QUEEN of HEARTS |
Given
1 |
"hello" bind GET to { request:Request => Response ... } |
from definition:
1 |
infix fun String.bind(method: Method): PathMethod = PathMethod(this, method) |
where http4k added functionality ‘bind’ to String.
(https://github.com/http4k/api/blob/master/org.http4k.contract/kotlin.-string/index.md)
In this example, we declare the infix function name to be bind.
‘this’ is the String itself.
Hence this is how we get “hello” bind
Notice in the infix fun String.bind that it takes in a parameter of type Method. This is how we have “hello” bind GET
So now using infix notation, we provided a string that gets bound to a Method called GET.
We want this to be paired with a provided anonymous function like so:
“hello” bind GET – string that identifies the HTTP Method.
to {….} – the string that identifies the HTTP Method should execute this anon function.
First, let’s see a simpler example.
We created a much simpler infix function tofunction
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
class A { fun test() { println("I am a test") } infix fun eat(food: Any) { println("I like to eat $food") } infix fun to (action: (name: String) -> String) { println("--- A is executing (to) another function! ----") println(action("Ricky")) } } fun main() { val a = A() a eat "sandiwches" a to { name: String -> "Welcome $name"} } |
Now we see how a to { name: String -> “Welcome $name”} can actually execute a function.
Hence, it is similar way in http4. Http4’s object have set up the string hello to GET using infix fun ‘bind’.
“hello” bind GET to {request:Request -> Reponse…}
Then it uses infix function ‘to’ to have it execute with an anonymous function.
Its using syntactic sugar to execute many functions together on 1 line.