GithubHelp home page GithubHelp logo

kotlin-puzzlers's Introduction

Kotlin Puzzlers

Kotlin is a "pragmatic programming language that was designed to avoid many well-known Java Puzzlers".

This is a collection that I and many contributors have found so far.

What is a puzzler?

A puzzler is some code that doesn't work the way it seems it should work.

An ideal programming language won't have any.

The puzzlers here are presented as kts files (Kotlin Scripts), which can skip the main() function and are compiled on-the-fly when run, thus allowing some of them to have "will not compile" option.

Contributing

As is common with puzzlers, please submit yours (either pull requests or issues) and I will credit you during the next talk.

Conference talks

Posts

kotlin-puzzlers's People

Contributors

ahanin avatar angryziber avatar armcha avatar bipokot avatar constorvar avatar havrikov avatar hkurokawa avatar ice-phoenix avatar kevinmost avatar mangatmodi avatar marcinmoskala avatar marstran avatar miha-x64 avatar siebelstim avatar sommd avatar thomasnield avatar tradunsky avatar twisterrob avatar voddan avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

kotlin-puzzlers's Issues

inner class with generics

will it compile and write my name?

class Being<T>(val name: T? = null) {

    fun greet(being: Matter) {
        (being as this.Human).sayHello(name)
    }

    inner class Human: Matter() {
        fun sayHello(name: T?) {
            print("hello $name")
        }
    }

    open class Matter
}

fun main() {
    val human = Being("shalva97")
    human.greet(Being.Matter())
}

lessThanOrEquals

fun main() {
    println((2.0..3.0).lessThanOrEquals(0.0, 1.0))
}

true, false, or compilation error?

After (or before) this puzzler the next puzzler may be shown:

fun main() {
    println((2..3).lessThanOrEquals(0, 1))
}

true, false, or compilation error?

Those two have different answers. The first one has the answer true because what lessThanOrEquals does is that it compares two arguments, not the ranges themselves. And the second puzzler is a compilation error.

Elaboration

lessThanOrEquals is only needed for floating point numbers to make it possible to implement coerceIn (1.0.coerceIn(1.0..2.0)) for floating point numbers. Inside coerceIn function we use lessThanOrEquals not compareTo because compareTo compares by total order but lessThanOrEquals compares according to IEEE.

You may observe total order vs IEEE comparison difference in this example:

fun main() {
    println(-0.0 == 0.0) // true. IEEE
    println(0.0.compareTo(-0.0) == 0) // false. Total Order
    // or try NaN :)
}

The credit also goes to https://github.com/ilya-g

Const val or val

What will this print in Kotlin 1.3.X and then in Kotlin 1.4.X ?

enum class EnumWithConst(val theValue: Int) {
        One(0),
        Two(EnumWithConst.constValue),
        Three(2 * EnumWithConst.constValue);

        companion object {
            const val constValue: Int = 100
        }
    }


    enum class EnumWithoutConst(val theValue: Int) {
        One(0),
        Two(EnumWithoutConst.simpleValue),
        Three(2 * EnumWithoutConst.simpleValue);

        companion object {
            val simpleValue: Int = 100
        }
    }

fun main() {
    println(EnumWithConst.values().joinToString { "$it => ${it.theValue}" })

    println("##############################")

    println(EnumWithoutConst.values().joinToString { "$it => ${it.theValue}" })
}

The related playground : https://pl.kotl.in/NjuR92qlu

Smart tailrec

fun main() {
    recursive()
}

tailrec fun recursive() {
    ::recursive()
}
  1. Infinite loop
  2. StackOverflowError
  3. Will not compile
  4. Something else

Correct answer: 3. Because foo::baz(args) syntax is reserved for future use

NaN puzzler

val number: Number = 0.0 / 0.0
println(if (number is Double) number == number else "number !is Double")

a) true
b) false
c) number !is Double
d) None of the above

Correct answer: a. Compiler ignores smart cast to Double and compares numbers like Objects, i.e. using equals() method. And equals() method returns true if it compares two NaNs.

Enum puzzler

enum class E { e }

val e = E.e
val a = when (E.e) {
e -> "1"
}

fun main(args: Array) {
print(a)
}

// What will it print?
// a) 1
// b) Will not compile
// c) null
// d) NullPointerException

It crushed my production

private fun foo(one: (String) -> Unit = {}, two: (String) -> Unit = {}) {
one("one")
two("two")
}

fun main(args: Array) {
foo({ print(it)} )
foo { print(it)}
}

// What will it print?
// a). oneone
// b). twotwo
// c). onetwo
// d). Will not compile

Kotlin is type safety and null safety language (no)

fun main() {
    val write = { a: Byte -> print("$a ") }

    val typeSafety =
            if (write as? (Double) -> Unit == null) {
                true
            } else {
                write(127)
                write(128.9)
                false
            }

    val nullSafety =
            if (write as? (Any?) -> Unit == null) {
                true
            } else {
                try {
                    write(null)
                    true
                } catch (e: java.lang.NullPointerException) {
                    false
                }
            }

    when {
        typeSafety && nullSafety -> println("Kotlin is type safety and null safety language")
        typeSafety -> println("Kotlin is type safety language")
        nullSafety -> println("Kotlin is null safety language")
        else -> println("Kotlin is a language")
    }
}

If you use "as?" for checking lambdas, Kotlin will check only arity but not arguments types

Puzzler idea related to ranges and steps

Hi! Don't know English very well so create an issue instead of a PR. Hope you will adopt this description.

Puzzler idea:

for (i in 1..10 step 2 step 3) {
    println(i)
}

What will happen?

  • 1 3 5 7 9
  • 1 4 7 10
  • 1 7
  • won't compile
  • something else

Correct answer:

Click here to view the spoiler Something else: it will print 1 4 7.

Why?

Because (1) step overwrites the previous step and constructs a new object (Kotlin sources):

public infix fun IntProgression.step(step: Int): IntProgression {
    checkStepIsPositive(step > 0, step)
    return IntProgression.fromClosedRange(first, last, if (this.step > 0) step else -step)
}

And (2) in the new object the last element is recalculated (Kotlin sources):

internal fun getProgressionLastElement(start: Int, end: Int, step: Int): Int = when {
    step > 0 -> if (start >= end) end else end - differenceModulo(end, start, step)
    step < 0 -> if (start <= end) end else end + differenceModulo(start, end, -step)
    else -> throw kotlin.IllegalArgumentException("Step is zero.")
}

So 1..10 step 2 becomes 1..9 step 2because of (2).
Then 1..9 step 2 step 3 becomes 1..9 step 3 because of (1)
and finally becomes 1..7 step 3 because of (2) again.

New puzzler

Hello!

class Error(val code: Int) {
     override fun toString(): String = "Error code is $code"
 }

enum class Errors(code: Int, val error: Error = error(code)) {
    ERROR_1(1),
    ERROR_2(2),
    ERROR_3(3);

    fun error(code: Int) = Error(code)
}

fun main(args: Array<String>) {
    Errors.values().forEach { println(it.error) }
}

This code throws ExceptionInInitializerError. I spent about 3 hours to find why. As it turned out there is Intelij Idea bug: if you ask Idea: "Where is error function declared", it will say: "In enum class Errors", but it's not true. It declared in kotlin standart lib.
public inline fun error(message: Any): Nothing = throw IllegalStateException(message.toString())
To fix this, you need to move error function out of enum

Suspend function

suspend fun getAny(): Any = COROUTINE_SUSPENDED

suspend fun main() {
    val result = withTimeoutOrNull(100) { getAny() == getAny() }
    println(result)
}

a) true
b) false
c) null
d) None of the above

Correct answer: d (this code never finished). Returning COROUTINE_SUSPENDED (using only in library functions) implies coroutine suspension, even though you use withTimeout() coroutine launcher it will never finish

Couple more puzzlers

I haven't seen your presentation but thanks a lot for these great puzzlers!
The puzzlers not detected by IDE static analysis are the best :)

In case you're interested, here are some puzzlers I came across:

  • recently posted on Kotlin slack
val whatAmI = {}()
println(whatAmI)
  • power throw!
throw throw throw Exception()
return return 123
val map = mapOf<Any, Any>().withDefault{ "default" }
println(map["1"])

Implicitly conversions

What will be:

    println(17.0 / 5 / 2 / 2)
    println(17 / 5.0 / 2 / 2)
    println(17 / 5 / 2.0 / 2)
    println(17 / 5 / 2 / 2.0)

More puzzlers

FYI I created this repo https://github.com/dkandalov/kotlin-puzzlers which includes some of the puzzlers from this repo and some new puzzlers. In particular these two might be interesting:

        fun printClassOf(x: X) = when (x) {
            is X.A -> println("is A")
            is X.B -> println("is B")
        }.exhaustive

        val Unit.exhaustive get() = this
    enum class Color {
        Red, Green, Blue;
        companion object
    }

    fun Color.Companion.from(s: String) = when (s) {
        "#FF0000" -> Red
        "#00FF00" -> Green
        else -> null
    }

Canadians!

Ideasource:

class SomethingTfun main() {
	SomethingTᐳ()
}

may need to add more red herrings, but this is already interesting: it compiles and executes! but what is T?

'N Sync puzzler

Late night brain-fart, could be fun.
Inspiration: https://youtu.be/MYQWtNG2so8?t=1101 (took the section heading too literally)

package by

object by {
    val by: by by by
}

operator fun `by`.getValue(by: by, prop: Any): by =
    TODO("by by by")

fun main() {
	println(by.by.by)
}

Not sure what the question would be, I guess "What happens when you try to compile & run this?"

Result (click to expand)
/**
Exception in thread "main" java.lang.ExceptionInInitializerError
	at b.y.ByKt.main(by.kt:11)
	at b.y.ByKt.main(by.kt)
Caused by: java.lang.IllegalArgumentException:
Parameter specified as non-null is null: method b.y.ByKt.getValue, parameter $this$getValue
	at b.y.ByKt.getValue(by.kt)
	at b.y.by.getBy(by.kt)
	at b.y.by.<clinit>(by.kt:4)
	... 2 more
 */

Explanation: the last by in val by: by by by refers to the same property it's trying to initialize.

(Suprising: the backticks are required to compile, not sure yet why.)

Generic version, for laughs This was an intermediate version, then I realized that `getValue` is enough to make it work.
package b.y

open class by<by : b.y.by<by>> {
	val by: by by by
}

operator fun `by`<*>.getValue(by: by<*>, prop: Any): Nothing =
	TODO("by by by")

fun main() {
	class by : b.y.by<by>()
	println(b.y.by().by)
}

too softcore

Your jpoint 2017 performance was more like introduction to kotlin and not puzzlers :)

Here is a couple of puzzlers for people who uses kotlin already:

operator fun Nothing?.not() = Unit
operator fun Unit.not() = null

var aaaa = null

fun main(args: Array<String>) {
	!!!!aaaa!!!! // will it work?
	(!!!!aaaa)!!!! // how about it?
	!!!!(aaaa!!!!) // or it?
}
operator fun Nothing?.not() = null

var aaaa = null

fun main(args: Array<String>) {
	!!!!aaaa!!!! // will it work?
	(!!!!aaaa)!!!! // how about it?
	!!!!(aaaa!!!!) // or it?
}

Returning wrong type object from suspend function

fun printAndReturn(string: String): Int {
    print(string)
    return 43
}

suspend fun suspendFunction(): String =
    suspendCoroutineUninterceptedOrReturn {
        printAndReturn("42 ")
    }

suspend fun main() {
    print(suspendFunction())
}
  1. 42 43
  2. 42 ClassCastException
  3. Will not compile
  4. None of the above

Correct answer: 1. As far as i understand all suspend functions have an Object as return type (thats why there is no ClassCastException) and suspendCoroutineUninterceptedOrReturn allows you to return anything regardless return type (its needed for some library functions)

Puzzler: Compiler crash on `+=` after a `?.` expression

This code makes the compiler crash.
The bug is know and referenced here: https://youtrack.jetbrains.com/issue/KT-31135

class foo(var bar : String)

fun main() {    
    var baz : foo? = foo("test")
    baz?.bar += "test"
}

It seems to be relate to the fact that

  1. the += is operated on an immutable class (String) and the statement is re-written as baz?.bar = baz?.bar + "test" and
  2. The plus extension function on a String takes a nullable receiver: operator fun String?.plus(other: Any?): String

Rewriting it by hand, this bug goes away. It looks like the compiler messes up the re-write.

If the plus's receiver were non-nullable, a compiler error would have been generated instead of it crashing.

Puzzlers with instance of Nothing class

I found a way to get instance of Nothing class and created some puzzlers with it

1) Returning null from NotNull function

    fun main() {
        println(thisFunctionNeverReturnsNull())
    }

    fun thisFunctionNeverReturnsNull(): String {
        val unsafe =
                Class.forName("sun.misc.Unsafe")
                        .declaredFields
                        .first { it.name == "theUnsafe" }
                        .apply { isAccessible = true }
                        .get(null)
                        as Unsafe
        unsafe.allocateInstance(Nothing::class.java) as Nothing
    }

2) Throwing java.lang.NPE in function (in this case "main") where nothing can thow NPE

    fun main() {
        getNothing()
    }

    fun getNothing(): Nothing {
        val unsafe =
                Class.forName("sun.misc.Unsafe")
                        .declaredFields
                        .first { it.name == "theUnsafe" }
                        .apply { isAccessible = true }
                        .get(null)
                        as Unsafe
        return unsafe.allocateInstance(Nothing::class.java) as Nothing
    }

3) Breaking compiler

    fun main() {
        val unsafe =
                Class.forName("sun.misc.Unsafe")
                        .declaredFields
                        .first { it.name == "theUnsafe" }
                        .apply { isAccessible = true }
                        .get(null)
                        as Unsafe
        val nothing = unsafe.allocateInstance(Nothing::class.java) as Nothing

        println(if (nothing) {}.toString())
    }

this code throws java.lang.VerifyError. It means that Kotlin compiled wrong bytecode. Let's look on the wrong bytecode line:

    CHECKCAST java/lang/Void
    ASTORE 1
    ALOAD 1
    INVOKEVIRTUAL kotlin/Unit.toString ()Ljava/lang/String;

As we can see, we try to invoke kotlin.Unit.toString() on java.lang.Void instance

New puzzler

    fun Any.toConsole(): Unit = print("$this  ")

    fun main() {
        val list = listOf(1, 2, 3)
        val array = IntArray(1)

        { 42 }.toConsole()
        list.toConsole()
        array.toConsole()
    }
  1. [I@3f99bd52 [1, 2, 3] kotlin.Unit
  2. 42 java.util.ArrayList@4481f34a [I@448139f0
  3. kotlin.Unit [1, 2, 3] [I@448139f0
  4. Function0<java.lang.Integer> java.util.ArrayList@4481f34a [I@448139f0
  5. Function0<java.lang.Integer> [1, 2, 3] [I@448139f0

Correct answer: first. Because { 42 } its a second argument of IntArray constructor

Context receivers

The feature is initially designed in ambiguous way.
Companions are for illustration because identifier is a type and value at the same time.

object Wtf
fun context(i: Wtf) {
    Throwable().printStackTrace()
}

context(Wtf)
fun foo() {

    context(Wtf)
    fun bar() {
    }
}

fun main() {
    Wtf.run { foo() }
}

Answer:
context() on a top-level fun is a context accepting a type. context() above a local function is just an invocation accepting a value. The only stack trace will be printed, with foo() on top of stack.

Generic puzzler

fun <T> weirdPrint(a: ArrayList<in T>) =
    try {
        print(a) as T
    } catch (e: Throwable) {
        throw UnsupportedOperationException()
    }

weirdPrint(if (false) arrayListOf(42) else arrayListOf("Hello"))

// a) [Hello]
// b) [Hello] NullPointerException
// c) [Hello] UnsupportedOperationException
// d) Will not compile

Correct answer is b. T implicitly infers to Nothing and if function returns Nothing, compiler inserts "throw null" after invocation. Why "throw null"? Because its shortest way to throw any exception

Windows vs Kotlin

fun main() {
	doSomething()
	doSomeThing()
}

fun f(block: () -> Unit) {
	block()
}

fun doSomething() {
	f { println("doSomething") }
}

fun doSomeThing() {
	f { println("doSomeThing") }
}

What's the output on Windows?

doSomething
doSomeThing
doSomething
doSomething
doSomeThing
doSomething
doSomeThing
doSomeThing
java.lang.NoClassDefFoundError
Expand
java.lang.NoClassDefFoundError: MainKt$doSomething$1 (wrong name: MainKt$doSomeThing$1)
	at Main.doSomething(Main.kt:11)

Encountered in Kotlin 1.4.32, verified fixed in 1.6.0 (not sure about 1.5.x)
On 1.6.0 two class files are generated: MainKt$doSomething$1 and MainKt$doSomeThing$2
On Unix this is not an issue because most file systems are case sensitive.

Two puzzlers with contracts

@UseExperimental(ExperimentalContracts::class)
inline fun runLambda(block: () -> Unit) {
    contract {
        callsInPlace(block, InvocationKind.AT_LEAST_ONCE)
    }
}

fun getNothing(): Nothing {
    runLambda { throw UnsupportedOperationException("Functions cant return Nothing!") }
}

fun main() {
    val nothing: Nothing = getNothing()
    print("Hello ")
    print(nothing as String)
}

a) UnsupportedOperationException
b) NullPointerException
c) Hello TypeCastException
d) Hello NullPointerException
e) Will not compile

Correct answer is b, We trick the compiler using the AT_LEAST_ONCE contract (it means that lambda must be called at least once, but we don’t do this). Due to this getNothing() function returns null with no expection. Than compiler looks at the main function and thinks: "Hmm... getNothing() returns Nothing, but its impossible without throwing an exception. In this case I will remove all instructions after getNothing() invocation, because they are redundand, and write "throw null' instead of "return"

@UseExperimental(ExperimentalContracts::class)
inline fun runLambda(block: () -> Unit) {
    contract {
        callsInPlace(block, InvocationKind.EXACTLY_ONCE)
    }
}

fun hello(): String {
    var hello: String
    runLambda { hello = "Hello " }
    return hello
}

fun world(): String {
    var world: String
    runLambda { world = "world!" }
    return world
}

fun main() {
    val result = hello().plus(world())
    println(result)
}

a) Hello world!
b) Will not compile
c) NullPointerException
d) nullnull
e) Not of the above

Correct answer is d. We trick compiler again, but now we used contracts to return uninitialized (null) String variable from NotNull function. But why we didnt get NullPointerException by invoking plus() function on null string? Because plus() compiles into StringBuilder like this:

    StringBuilder builder = new StringBuilder();
    builder.append(hello());
    builder.append(world());
    String result = builder.toString();

Thats why we got "nullnull"

Type safe code

What will this print?

fun main() {
    Fun().things()
}

data class Stuff(
    val s: String
)

class Fun {
    private val stuff: Stuff = createStuff()
    private val x: String = "x"

    fun things() {
        println(stuff.s)
    }

    private fun createStuff(): Stuff {
        return Stuff(x)
    }
}
solution

KotlinNullPointerException: null is passed to non-null parameter s in Stuff.constructor
The value of x is null at the point of Stuff constructor call, because the Fun vals are initialized in order.
Because it's in a function, Kotlin thinks it's safe, when inlined the problem becomes obvious.

Is there anything similar already?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.