[Solved] Equivalent Kotlin code to my F# functional code [closed]


The main problem I found was finding an equivalent operator to the pipeOperator|>, then i found three potential alternatives:

using .let
using .run
using infix function

Below example was good startup for me to solve my issue:

fun main(args: Array<String>) {
    var a = 3
    val b: Int = 6


    println("Hello World! doubling, then tripling the sume of $a and $b is " +
            "${(sumx(a,b)
                    next ::dbl
                    next ::trpl
                    )}")

    println("Hello World! doubling, then tripling the sume of $a and $b is " +
            "${(sumx(a,b)
                    .let (::dbl)
                    .let (::trpl)
                    )}")
    println("Hello World! doubling, then tripling the sume of $a and $b is " +
            "${(sumx(a,b)
                    .run (::dbl)
                    .run (::trpl)
                    )}")

    println("Hello World! doubling, then tripling the sume of $a and $b is " +
            "${(sumx(a,b)
                    into (::dbl)
                    into (::trpl)
                    )}")
}

fun sumx (x: Int, y: Int) : Int = x + y
fun dbl (x: Int): Int = x * 2
fun trpl (x: Int): Int = x * 3

infix fun <T, R> T.next(map : (T) -> R) : R = map(this)
infix fun <T, R> T.into(func: (T) -> R) = func(this)

UPDATE

I Created the gradle project using this command: gradle init --type java-library

Deleted the src/main and the src/test folders

Created the src/kotlin and src/resources folders

Created my file at src/kotlin/Main.kt as below:

import kotlin.coroutines.experimental.buildSequence

fun main(args: Array<String>) {
    println("Hi, Let's start")

    val series = listOf(
            30, 21, 29, 31, 40, 48, 53, 47, 37, 39, 31, 29, 17, 9, 20, 24, 27, 35, 41, 38,
            27, 31, 27, 26, 21, 13, 21, 18, 33, 35, 40, 36, 22, 24, 21, 20, 17, 14, 17, 19,
            26, 29, 40, 31, 20, 24, 18, 26, 17, 9, 17, 21, 28, 32, 46, 33, 23, 28, 22, 27,
            18, 8, 17, 21, 31, 34, 44, 38, 31, 30, 26, 32
    )

    fun initialSeasonalComponents(series: List<Int>, slen: Int): Map<Int, Double> {
        val nSeasons = (series.size / slen).toFloat()
        val grouped = series.map { it.toFloat() }.chunked(slen)
        val seasonAverages = grouped.map { it.average() }
        return (0 until slen).associate {
            Pair(it, grouped.zip(seasonAverages)
                    .fold(0.0) { s, (els, av) -> els[it] + s - av }
                    / nSeasons)
        }
    }

    println("Seasons Averageß: \n ${initialSeasonalComponents(series, 12)}")

    fun initialTrend(series: List<Int>, slen: Int): Double =
            series.windowed(slen)
                    .fold(0) { s, x -> x.last() - x.first() + s }
                    .toFloat() / slen.toDouble()

    println("Initial Trend: \n ${initialTrend(series, 12)}")

    fun tripleExponentialSmoothing(series: List<Int>, slen: Int, alpha: Double, beta: Double, gamma: Double, nPreds: Int): Sequence<Double> {
        var smooth = 0.0
        var trend = 0.0
        val seasonals = initialSeasonalComponents(series, 12).toMutableMap()
        return buildSequence {
            for (i in 0 until (series.size + nPreds)) {
                when {
                    i == 0 -> {
                        smooth = series.first().toDouble()
                        trend = initialTrend(series, slen)
                        yield(series.first().toDouble())
                    }
                    i >= series.size -> {
                        val m = i - series.size + 1
                        yield((smooth + m * trend) + (seasonals[i % slen] ?: 0.0 /* Need default values because of null safety */))
                    }
                    else -> {
                        val v = series.first().toDouble()
                        val lastSmooth = smooth
                        smooth = alpha * (v - (seasonals[i % slen] ?: 0.0)) + (1.0 - alpha) * (smooth + trend)
                        trend = beta * (smooth - lastSmooth) + (1.0 - beta) * trend
                        seasonals[i % slen] = gamma * (v - smooth) + (1.0 - gamma) * (seasonals[i % slen] ?: 0.0)
                        yield(smooth + trend + (seasonals[i % slen] ?: 0.0))
                    }
                }
            }
        }
    }

    val f = tripleExponentialSmoothing(series, 12, 0.716, 0.029, 0.993, 24).toList()
    val res = f.map {it.format(2)} // used to format the numbers, can be avoided.

    println("Forecast: \n $res")
}

fun Double.format(digits: Int) = java.lang.String.format("%.${digits}f", this) // Extension function to format the numbers

The 0.0 is the initial state for the fold function, { s, (els, av) -> } is the operation applied to each element, where s is the accumulator and (els, av) is the current element (in this case an entry of a map), which has been deconstructed1, leaving els as the key and av as the value of the current entry.

My gradle.build is:

buildscript {
    ext.kotlin_version = '1.2.21'

    repositories {
        mavenCentral()
    }
    dependencies {
        classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"   // for gradle build
    }
}
apply plugin: 'kotlin'

repositories {     jcenter()    }

dependencies {
    compile "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
}

sourceSets.main {
    kotlin.srcDirs += 'src/kotlin'
    resources.srcDirs += 'src/resources'
}

jar {
    baseName 'myApp'
    manifest.attributes 'Main-Class': 'MainKt'  // '[namespace].[arctifact/file]Kt'
    from { configurations.compile.collect { it.isDirectory() ? it : zipTree(it) } }
}

The generated jar file was saved at build/libs/MyApp.jar and i run it using command java -jar myApp.jar

solved Equivalent Kotlin code to my F# functional code [closed]