Creative Commons Licence This work is licensed under a Creative Commons
Attribution-ShareAlike 4.0 International License

Source: gitlab

Snake in KotlinJS

Andy Balaam
artificialworlds.net/blog

Contents

Snake

Kotlin

KotlinJS

♥ Kotlin

♥ Kotlin

fun main(args: Array<String>) { val x: String? = args.firstOrNull() println(x.length); }

♥ Kotlin

fun main(args: Array<String>) { val x: String? = args.firstOrNull() println(x.length); ^ error: only safe (?.) calls are allowed on a nullable receiver of type String? }

♥ Kotlin

fun main(args: Array<String>) { val x: String? = args.firstOrNull() if (x != null) { println(x.length); }

Compiles fine.

♥ Kotlin

data class Point(val x: Int, val y: Int)

That is the whole file.

♥ Kotlin

data class Point(val x: Int, val y: Int) val p = Point(x = 10, y = 10)

♥ Kotlin

data class Point(val x: Int, val y: Int) val p = Point( x = 10, y = 10 ) p.x = 3

♥ Kotlin

data class Point(val x: Int, val y: Int) val p = Point( x = 10, y = 10 ) p.x = 3 ^ error: val cannot be reassigned

♥ Kotlin

data class Point(var x: Int, var y: Int) fun main() { val p = Point( x = 10, y = 10 ) p.x = 3 }

Compiles fine! Immutability is shallow.

♥ Kotlin

var body = (0..4).map { Point(10, 10 + it) }

♥ Kotlin

var body = (0..4).map { Point(10, 10 + it) }

How does it feel?

import kotlin.browser.document import kotlin.browser.window fun main() { val canvas = document.getElementById( "snake-canvas") as HTMLCanvasElement window.onresize = { scaleCanvas(canvas, window) } }

It feels like JavaScript with types.

How does it feel?

fun headHittingBody() = snake.body.drop(1).any { head == it } if (headOutsideGame || (head != apple && headHittingBody()) ) { snake.alive = false }

No wait it feels like Kotlin

How does it feel?

val ctx = canvas.getContext("2d") as CanvasRenderingContext2D ctx.fillText( "Score: ${game.snake.body.size}.", canvas.width / 2.0, canvas.height / 2.0 )

It's like you're calling JS APIs but passing in Kotlin objects and using Kotlin syntactic sugar.

How does it feel?

How does it feel?

Deployment

$ grep script index.html <script src="web/kotlin.js"... <script src="web/snake-kotlinjs.js" ...

Deployment

$ ls web/ 2078581 kotlin.js 161108 kotlin.meta.js 1594 snake-kotlinjs/root-package.kjsm 13284 snake-kotlinjs.js 1312 snake-kotlinjs.meta.js

Deployment

$ cat snake-kotlinjs.js ... var headHittingBody = Game$step$headHittingBody(this, head); if ( headOutsideGame || ( !(head != null ? head.equals(this.apple) : null ) && headHittingBody()) ) { this.snake.alive = false; } ...

Deployment

$ wc -l src/main/kotlin/*.kt 195 total $ wc -l web/snake-kotlinjs.js 415 web/snake-kotlinjs.js

Deployment

$ wc -l web/kotlin.js 50868 web/kotlin.js

Deployment

$ wc -l web/kotlin.js 50868 web/kotlin.js MutableMap.prototype.getOrDefault_xwzc9p$ = Map.prototype.getOrDefault_xwzc9p$;

Deployment

Credit: prnsml

Deployment

Credit: prnsml

$ ls -l web/kotlin.js # Before 2.0M web/kotlin.js $ ls -l web/kotlin.js # After dead code elimination 192K web/kotlin.js $ ls -l web/*ugly*.js # After uglifyjs 88K web/kotlin.uglyfyjs.min.js

Conclusions

Also...

More info