Kotlin print(), println(), readLine(), Scanner, REPL

Hoy aprenderemos cómo utilizar las funciones de impresión de Kotlin y cómo obtener y analizar la entrada del usuario desde la consola. Además, exploraremos el REPL de Kotlin.

Funciones de Impresión en Kotlin

Para mostrar algo en la pantalla, se utilizan los siguientes dos métodos:

  • print()
  • println()

La instrucción print imprime todo lo que hay dentro en la pantalla. La instrucción println agrega una nueva línea al final de la salida. Las declaraciones de impresión llaman internamente a System.out.print. El siguiente código muestra las declaraciones de impresión en acción:

fun main(args: Array<String>) {
var x = 5
print(x++)
println("Hello World")
print("Do dinasours still exist?\n")
print(false)
print("\nx is $x.")
println(" x Got Updated!!")
print("Is x equal to 6?: ${x == 6}\n")    
}

Para imprimir una variable dentro de la declaración de impresión, necesitamos usar el símbolo del dólar ($) seguido del nombre de la variable/val dentro de una cadena literal con comillas dobles. Para imprimir el resultado de una expresión, usamos ${ //aquí va la expresión }. La salida cuando se ejecuta el código anterior en el Kotlin Online Compiler se muestra a continuación.

Escape de literales y expresiones

Para escapar el símbolo del dólar y, digamos, tratar ${expresión} como una cadena solamente en lugar de calcularlo, podemos escaparlo.

fun main(args: Array<String>) {
val y = "\${2 == 5}"
println("y = ${y}")       
println("Do we use $ to get variables in Python or PHP? Example: ${'$'}x and ${'$'}y")
val z = 5
var str = "$z"
println("z is $str")
str = "\$z"
println("str is $str")
}

Tenga en cuenta que un simple $ sin ninguna expresión/variable establecida contra él lo escapa implícitamente y lo trata como parte de la cadena solamente.

Valores de función de impresión

fun sumOfTwo(a: Int, b: Int) : Int{
    return a + b
}

fun main(args: Array<String>) {
val a = 2
val b = 3
println("Value of ${'$'}a and ${'$'}b is : ${sumOfTwo(a,b)}") 
println(println("Printing Value of ${'$'}a and ${'$'}b is : ${sumOfTwo(a,b)}"))    
}

Se imprime la siguiente salida: Nota: Pasar una impresión dentro de otra se comporta como recursión. Lo más interno se imprime primero. La instrucción de impresión devuelve un Unit (equivalente a void en Java).

Entrada de usuario Kotlin

Para obtener la entrada del usuario, se pueden usar los siguientes dos métodos:

Nota: La entrada del usuario requiere una herramienta de línea de comandos. Puede usar REPL o IntelliJ. Vamos a usar IntelliJ aquí.

Usando readLine()

readLine() devuelve el valor del tipo String? para manejar valores nulos que pueden ocurrir al leer el final del archivo, etc. El siguiente código muestra un ejemplo usando readLine().

fun main(args: Array<String>) {
    println("Enter your name:")
    var name = readLine()
    print("Length is ${name?.length}")
}

Como puedes ver, necesitamos desempaquetar el tipo nullable para usar las funciones del tipo String en la propiedad. Usa !! para convertir forzosamente el String? a String, solo cuando estés absolutamente seguro de que el valor no será nulo. De lo contrario, provocará un fallo. Convirtiendo la entrada a un entero Para convertir el String de entrada a un Int, hacemos lo siguiente:

fun main(args: Array<String>) {
var number = readLine()
try {
        println("Number multiply by 5 is ${number?.toInt()?.times(5)}")
    } catch (ex: NumberFormatException) {
        println("Number not valid")
    }
}

Nuevamente, usamos el operador ?. para convertir el tipo nullable primero a un Int usando toInt(). Luego lo multiplicamos por 5. Leyendo la entrada continuamente Podemos usar el bucle do while para leer la entrada continuamente como se muestra a continuación.

    do {
        line = readLine()

        if (line == "quit") {
            println("Closing Program")
            break
        }

        println("Echo $line")

    } while (true)
}

La salida de lo anterior en la línea de comandos de IntelliJ es la siguiente.

Leyendo múltiples valores usando el operador de separación

Podemos leer múltiples valores separados por delimitadores y guardarlos en forma de tupla como se muestra a continuación.

fun readIntegers(separator: Char = ',')
        = readLine()!!.split(separator).map(String::toInt)

fun main(args: Array<String>) {
    println("Enter your values:")
    try {
        val (a, b, c) = readLine()!!.split(' ')
        println("Values are $a $b and $c")
    } catch (ex: IndexOutOfBoundsException) {
        println("Invalid. Missing values")
    }

    try {
        val (x, y, z) = readIntegers()
        println("x is $x y is $y z is $z")
    } catch (ex: IndexOutOfBoundsException) {
        println("Invalid. Missing values")
    }
    catch (ex: NumberFormatException) {
        println("Number not valid")
    }

}

La función split toma el carácter que será el delimitador. La función readIntegers() utiliza un mapa en un split para convertir cada valor a Int. Si introduces valores menores que los especificados en la tupla, obtendrás una IndexOutOfBoundsException. Hemos utilizado try-catch en ambas entradas. La salida se ve así: Alternativamente, en lugar de tuplas, también podemos usar una lista como se muestra a continuación.

val ints: List<String>? = readLine()?.split("|".toRegex())
println(ints)

Clase Scanner de Kotlin

Para tomar entradas podemos usar Scanner(System.`in`) que toma entradas desde el teclado de entrada estándar. El siguiente código demuestra lo mismo:

fun main(args: Array) {
    val reader = Scanner(System.`in`)
    print("Enter a number: ")

    // nextInt() lee el siguiente entero. next() lee el String 
    var integer:Int = reader.nextInt()

    println("You entered: $integer")

reader.nextInt() lee el siguiente entero. reader.next() lee el siguiente String. reader.nextFloat() lee el siguiente flotante y así sucesivamente. reader.nextLine() pasa el Scanner a la siguiente línea y también borra el búfer. El siguiente código demuestra la lectura de diferentes tipos de entradas dentro de una declaración de impresión directamente.

import java.util.*

fun main(args: Array) {

    val reader = Scanner(System.`in`)
    print("Enter a number: ")

    try {
        var integer: Int = reader.nextInt()
        println("You entered: $integer")
    } catch (ex: InputMismatchException) {
        println("Enter valid number")
    }
    enterValues(reader)
    //mueve el escáner a la siguiente línea de lo contrario la entrada en búfer sería leída para el siguiente aquí solamente. 
    reader.nextLine()
    enterValues(reader)
}

fun enterValues(reader: Scanner) {
    println("Enter a float/boolean :")
    try {
        print("Values: ${reader.nextFloat()}, ${reader.nextBoolean()}")
    } catch (ex: InputMismatchException) {
        println("First value should be a float, second should be a boolean. (Separated by enter key)")
    }
}

Se lanza InputMismatchException cuando la entrada es de un tipo diferente al solicitado. La salida se muestra a continuación.

REPL de Kotlin

REPL, también conocido como Read-Eval-Print-Loop, se utiliza para ejecutar una parte de código en un shell interactivo directamente. Podemos hacerlo en nuestra terminal/línea de comandos iniciando el compilador de Kotlin.

Instalación del compilador de línea de comandos

Podemos instalar el compilador de línea de comandos en Mac/Windows/Ubuntu como se muestra aquí. Típicamente, en un Mac, podemos usar HomeBrew en nuestra terminal para instalar el compilador de Kotlin.

brew update
brew install kotlin

Una vez hecho esto, inicie el REPL ingresando kotlinc en su terminal/cmd. A continuación, se muestra mi primer código en el REPL. Eso es todo para las funciones de impresión de Kotlin y una breve introducción al REPL de Kotlin.

Source:
https://www.digitalocean.com/community/tutorials/kotlin-print-println-readline-scanner-repl