Uberto Barbini
04/06/2019, 2:58 PMShawn
04/06/2019, 3:00 PMUberto Barbini
04/06/2019, 3:01 PMShawn
04/06/2019, 3:03 PMLETTING
is doing here?Pair
or Triple
-based solutionfun pythagoras(a: Double, b: Double): Double =
(a * a to b * b).let {
(x, y) -> Math.sqrt(x+y)
}
fun pythagoras(a: Double, b: Double): Double =
object {
val x = a * a
val y = b * b
}.run {
Math.sqrt(x + y)
}
tschuchort
04/06/2019, 4:59 PMUberto Barbini
04/06/2019, 6:34 PMelizarov
04/07/2019, 6:36 AMfun pythagora(a: Double, b: Double): Double {
val x = a * a
val y = b * b
return Math.sqrt(x + y)
}
What am I missing?raulraja
04/07/2019, 11:27 AMsuspend
which is what the Kotlin community already does for the most part when they use the coroutines-core
lib. The linter will verify that expressions returning Unit
that are not inside suspend
functions fail to compile in the same way today the Kotlin compiler verifies that suspend
functions can't be applied unless in the presence of a continuation. This is the same concept as Haskell's IO
. Also this can be implemented with no additional syntax in Kotlin, it already supports all this natively thanks to the core continuation intrinsics being part of the std lib. coroutines-core
implements the runtime for an effect system that tracks suspend
like Arrow Fx also does but geared more toward guaranteeing purity at compile time vs async concurrency. //@aballano is going to help us with the linter rules, the rest the Kotlin compiler and @RestrictsSuspension already takes care of. This is often ignored in Kotlin because it does not really have the FP names you'd expect but @RestrictsSuspension already allows you to group effects in different areas and prevent compilation unless you explicitly encode how a foreign suspend function is accepted within a restricted context. If interested more info here https://arrow-kt.io/docs/effects/fx/#pure-functions-side-effects-and-program-execution
Additionally if this was interesting to the compiler and the general community you could enable an experimental import that disallows returning Unit
unless you are inside suspend
. That is all the compiler is missing today to guarantee pure functions.Uberto Barbini
04/07/2019, 12:53 PMelizarov
04/08/2019, 6:31 AMbut the problem is that you can write any code in that pythagora fun, calling db, asking google etc.Can you, please, clarify how that problem is related to the “letting” syntax?
val x = ... ; val y = ... ; return ...
is just the Kotlin syntax for let x = ... in let y = ... in ...
construct and the choice of syntax is completely orthogonal to the purity of your functions. Kotlin is not a pure language and will never become one (due to JVM interop goals) and so any Kotlin syntactic construct allows you to call both pure and non-pure functions. So, programming with pure functions is a style issue in Kotlin — it is something you choose to do to improve your code, not something that is being enforced.tschuchort
04/08/2019, 8:47 AMelizarov
04/08/2019, 8:50 AMval x = ... ; val y = ... ; return ...
. It is a sequence of declarations, one building on another. Is it a val
name that confuses people? You can call it let
(like in Swift) when you read it, if it makes it more declarative for youIn computer science, imperative programming is a programming paradigm that uses statements that change a program’s state.
raulraja
04/08/2019, 11:01 AMsuspend
+ function application is still pure because suspend
can't run without the continuation. (suspend() -> A).invoke
is the same as IO.flatMap
but not stack safe. !
here is the same as ()
but stack safe.
val x: IO<Int> = fx {
val n = !IO { 1 }
val y = !IO { 1 }
x + y
}
val x : IO<Int> = IO { 1 }.flatMap { n -> IO { n + 1 } }
!
is conceptually the imperative version of flatMap
where the rest of the program down below gets nestedjust
, map
or flatMap
all those are gonne if you have the ability to non blocking go from F<A> -> A
do
blocks. In Kotlin you can have do notation at any level a la carte as long as you are in suspended continuation because you can always collapse the wrapper and extract the value so there is no need to work in a wrapped style with flatMap
etc.suspend
. For example println
or anything that returns Unit
or calls something that returns Unit
elizarov
04/08/2019, 2:55 PMraulraja
04/08/2019, 3:07 PMsuspend fun save(): Unit {
doSave()
etc()
}
Pure just means that when invoked it does not compile unless in IO or produces no effects. That is exactly what suspend does. It does not compile unless you have a continuation. We can't call that function directly on main or other places that are not suspended, that makes it pure and therefore is as valid as callback chains or wrappers for FP. FP style is fine with imperative style, what I believe is frowned upon is calling effects when the function ir not suspended or the datatypes like IO does not delay evaluation once it wraps the effect it is supposed to control.Uberto Barbini
04/08/2019, 7:23 PM