[JAVA] Kotlin infix

What is this

I was wondering what kotlin's reserved word, infix, was, so I looked up the definition and how to make it.

table of contents

--Somehow fix --Example of standard library: "to" --Define infix functions --Call the defined infix function from Kotlin --Call the defined infix function from Java --Disassemble the infix function --Reference

Somehow fix

In the first place. What is infix? I don't know English words (laughs) When I run Google Translate, it returns "inside". I noticed here that this is one of the fixes. There are other fixes that I often use. prefix、suffix。 Literally in the middle, it is a function of Kotlin that can define a function that puts an infix function between objects and values and processes with two objects and values sandwiched between them as arguments.

Standard library example: "to"

The standard library infix function to is called as follows to create a Pair instance.

Pair.kt


val pair: Pair<String, String> = "key" to "value"

The method is defined as an extension function as shown below.

Standard.kt


/**

 * Creates a tuple of type [Pair] from this and [that]. 
 * 
 * This can be useful for creating [Map] literals with less noise, for example: 
 * @sample samples.collections.Maps.Instantiation.mapFromPairs 
 */
public infix fun <A, B> A.to(that: B): Pair<A, B> = Pair(this, that) 

Reference: Tuples.kt

Then, I would like to make my own infix function.

Define infix functions

Imagine a case where you often encounter "refilling values into instances of similar objects that have similar objects". Here, create a function that attaches a history sequence to the value of the Customer class to create an instance of the CustomerHistory class, and returns a Pair instance that includes those instances in the generics.

First, define the data class that will be the result of input and synthesis.

Data.kt


data class Customer (
        var id: String,
        var name: String
)

data class CustomerHistory (
        var id: String,
        var name: String,
        var seq: Int
)

Define the infix function that creates a CustomerHistory instance with a sequence from the original Customer as follows.

Infix.kt


/**
 *The receiver is treated as this inside the extension function. The sequence is received as a function argument.
 */
infix fun Customer.mapToHistory(seq: Int): Pair<Customer, CustomerHistory> = Pair(
        this,
        CustomerHistory(
                this.id,
                this.name,
                seq
        )
)

Now you are ready. Now, let's call the infix function defined from Kotlin code and Java code.

Call the defined infix function from Kotlin

Call the self-made infix function defined above.

Caller.kt


//Former story.
val customer: Customer = Customer("00001", "Eron Musk")

//Returns the original material and the Pair of the history object with a sequence.
val pair: Pair<Customer, CustomerHistory> = customer mapToHistory 2

The defined function wasn't good as an example, so it's hard to understand, but you can get the result by putting the defined function between objects and values.

Call the defined infix function from Java

Due to Kotlin's interoperability, it can also be called from Java. If you try a snippet of a similar call in Java

Caller.java


/**
 *The return value is kotlin included in Kotlin's library..Import and define Pair.
 */
public static void printHistory(Customer customer) {
        Pair<Customer, CustomerHistory> customerHistory = InfixKt.mapToHistory(customer, 2);
}

After all, I was expecting it, but from Java's point of view, the infix function is a static method.

Disassemble the infix function

The defined Kotlin file was compiled with kotlinc.

I can almost imagine the instruction procedure by looking at the call from Java, but I'm curious. So, let's disassemble the compiled Kotlin file (class file).


mac:classes user$ javap InfixKt.class
Compiled from "Infix.kt"
public final class InfixKt {
  public static final kotlin.Pair<Customer, CustomerHistory> mapToHistory(Customer, int);
}

It was just as I expected ... Kotlin files with no classes or multiple classes are named \ Kt when compiled. The original file name was ʻInfix.kt`. Looking at the result of disassembly, it is a static method included in the final class.

2020-07-02: Addendum It is a static method because the function I made is an extension function.

Add an option to javap and try to output a little more detailed information.

mac:classes user$ javap -c -l -p InfixKt.class
Compiled from "Infix.kt"
public final class InfixKt {
  public static final kotlin.Pair<Customer, CustomerHistory> mapToHistory(Customer, int);
    Code:
       0: aload_0
       1: ldc           #10                 // String $this$mapToHistory
       3: invokestatic  #16                 // Method kotlin/jvm/internal/Intrinsics.checkParameterIsNotNull:(Ljava/lang/Object;Ljava/lang/String;)V
       6: new           #18                 // class kotlin/Pair
       9: dup
      10: aload_0
      11: new           #20                 // class CustomerHistory
      14: dup
      15: aload_0
      16: invokevirtual #26                 // Method Customer.getId:()Ljava/lang/String;
      19: aload_0
      20: invokevirtual #29                 // Method Customer.getName:()Ljava/lang/String;
      23: iload_1
      24: invokespecial #33                 // Method CustomerHistory."<init>":(Ljava/lang/String;Ljava/lang/String;I)V
      27: invokespecial #36                 // Method kotlin/Pair."<init>":(Ljava/lang/Object;Ljava/lang/Object;)V
      30: areturn
    LineNumberTable:
      line 12: 6
      line 13: 10
      line 14: 11
      line 15: 15
      line 16: 19
      line 17: 23
      line 14: 24
      line 12: 27
      line 19: 30
    LocalVariableTable:
      Start  Length  Slot  Name   Signature
          0      31     0 $this$mapToHistory   LCustomer;
          0      31     1   seq   I
}

After all, it seems that it is a Java opcode that I knew even after it was compiled.

Summary of 3 lines

――Infix is a word that refers to infix and is like being placed between prefixes / suffixes. --The infix function is a function that performs processing by placing it between values and objects. --From Java's point of view, it looks like syntactic sugar for static methods.

reference

Books Kotlin in Action

website [Internal notation-Kotlin reference](https://dogwood008.github.io/kotlin-web-site-ja/docs/reference/functions.html#%E4%B8%AD%E7%BD%AE%E8% A8% 98% E6% B3% 95)

Recommended Posts

Kotlin infix
About Kotlin
Kotlin Bytecode
HMAC in Kotlin
Kotlin cheat sheet
Kotlin Study Book (Kotlin)