Skip to content

Data science workflows written with Kotlin can be rendered to html, pdf, and markdown using Jupyter. To do so we need a kernel.

A kernel provides programming language support in Jupyter. IPython is the default kernel. Additional kernels include R, Julia, and many more.

Two competing kernels are available for Kotlin


    • More established
    • Backed by JB
    • Friendly and responsive developers
    • Not really active

    a collection of JVM kernels and interactive widgets for plotting, tables, auto-translation, and other extensions to Jupyter Notebook.

    • Very active, fast progress
    • Friendly and very responsive developers
    • Not just a kernel
    • Display handler registry in kernel krangl.beakerx.TableDisplayer.register()

In our opinion, Kotlin-powered Jupyter notebooks are definitely cool, but lacks efficiency because of missing tooling (error checking, completion, refactoring):

Build reports embedding code and results

However, the kernel can be used for literate programming, which enables result consistency and streamline communication by building reports from code

So finally we want to develop data workflows interactively using plain and simple code. Similar to how it is possible with R via the well known tool chain built around knitr->pandoc:

Similary, in python this can be achieved by startin with markdown -> notedown + nbconvert

Can we do this with Kotlin?

Let's consider the following example

//' ## Flowers Analysis

//' The iris flower
//' ![](


import krangl.*

//' The first records in the input data (which is bundled with krangl) are

//' The structure of the input data is

//' Calculate mean petal
val summarizeDf: DataFrame = irisData
    .summarize("mean_petal_width") { it["Petal.Width"].mean() }

//' Print the summarized data

//' Conclusion: Iris flowers of species _virginica_ have on average the largest petal width.

An kts->html conversion could be impelmented as follows:

reportName=$(basename $inputScript .kts)

Rscript - ${inputScript} <<"EOF"
knitr::spin(commandArgs(T)[1], doc = "^//'[ ]?", knit=F)

kscript -t ' { it.replace("{r }", "")}.print()' ${reportName}.Rmd > ${reportName}.md

notedown ${reportName}.md > ${reportName}.ipynb

jupyter nbconvert --ExecutePreprocessor.kernel_name=kotlin \
        --execute --to html ${reportName}.ipynb --output ${reportName}

Proof-of-Concept. :-)