- mongodb - 在 MongoDB mapreduce 中,如何展平值对象?
- javascript - 对象传播与 Object.assign
- html - 输入类型 ="submit"Vs 按钮标签它们可以互换吗?
- sql - 使用 MongoDB 而不是 MS SQL Server 的优缺点
我正在查看找到的箭头库 here .为什么要使用 Option
类型而不是 Kotlin 的内置 nullables?
最佳答案
我已经使用 Arrow 提供的 Option
数据类型一年多了,一开始,我们对自己做了完全相同的问题。答案如下。
如果您仅将 option
数据类型与 Kotlin 中的 nullables
进行比较,它们几乎是偶数。相同的语义(有或没有一些值),几乎相同的语法(选项使用 map
,可空值使用 safe call operator)。
但是当使用 Options
时,您可以从箭头生态系统中获益!
当使用 Options
时,您使用的是 Monad 模式
。将 monad 模式与 arrow 等库一起使用时, scala cats , scalaz ,您可以从几个功能概念中受益。仅 3 个好处示例(还有很多):
Option
不是唯一的!例如,Either
对于表达和避免抛出异常非常有用。 Try
、Validated
和 IO
是其他常见 monad 的示例,它们可以帮助我们(以更好的方式)我们在典型项目中所做的事情。
您可以轻松地将一个 monad 转换为另一个。您有一个 Try
但想返回(并表达)一个 Either
?只需转换为它。您有一个 Either
但不关心错误?只需转换为 Option
。
val foo = Try { 2 / 0 }
val bar = foo.toEither()
val baz = bar.toOption()
这种抽象还可以帮助您创建不关心容器(monad)本身的函数,只关心内容。例如,您可以创建与 ANY MONAD 一起使用的扩展方法 Sum(anyContainerWithBigDecimalInside, anotherContainerWithBigDecimal)
(更准确地说:“适用于任何 applicative 实例” )这样:
fun <F> Applicative<F>.sum(vararg kinds: Kind<F, BigDecimal>): Kind<F, BigDecimal> {
return kinds.reduce { kindA, kindB ->
map(kindA, kindB) { (a, b) -> a.add(b) }
}
}
理解起来有点复杂,但非常有用且易于使用。
从 nullables 到 monads 不仅仅是将安全调用运算符更改为 map
调用。看看箭头作为“Monad Comprehensions”模式的实现提供的“绑定(bind)”功能:
fun calculateRocketBoost(rocketStatus: RocketStatus): Option<Double> {
return binding {
val (gravity) = rocketStatus.gravity
val (currentSpeed) = rocketStatus.currentSpeed
val (fuel) = rocketStatus.fuel
val (science) = calculateRocketScienceStuff(rocketStatus)
val fuelConsumptionRate = Math.pow(gravity, fuel)
val universeStuff = Math.log(fuelConsumptionRate * science)
universeStuff * currentSpeed
}
}
上例中使用的所有函数以及 rocketStatus
参数的属性都是 Options
。在 binding
block 中,flatMap
调用是为我们抽象的。该代码更易于阅读(和编写),您无需检查值是否存在,如果其中一些不存在,则计算将停止,结果将是带有 None< 的选项
!
现在试着想象这段代码用空验证代替。不仅仅是安全调用操作符
,还可能是if null then return
代码路径。不是更难吗?
另外,上面的例子使用了 Option
,但是作为抽象的 monad 理解的真正威力是当你将它与像 IO 这样的 monad 一起使用时。您可以在其中以与上述完全相同的“干净、顺序和命令式”的方式抽象异步代码执行:O
我强烈建议您在看到概念符合您需要的语义时立即开始使用诸如 Option
、Either
等 monad,即使您不确定如果您将从功能生态系统中获得其他巨大好处,或者您还不太了解它们。很快你就会在没有注意到学习曲线的情况下使用它。在我的公司,我们几乎在所有 Kotlin 项目中都使用它,甚至在面向对象的项目中(占大多数)。
关于kotlin - 为什么使用 Arrow 的 Options 而不是 Kotlin 可为空的,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48895103/
我正在查看Kotlin Github page我注意到 Kotlin 语言本身大部分是用 Kotlin 编写的:我只是想知道,一种语言怎么可能大部分都是用它自己的语言编写的?在您可以使用正在创建的语言
我有以下非常简单的 kotlin 代码来演示中缀函数 com.lopushen.demo.presentation 包 fun main(args: Array) { print("Hello
我在 Java 中有 2 个模型类,其中一个扩展了另一个 @UseStag public class GenericMessages extends NavigationLocalizationMap
Kotlin 代码 runBlocking { flow { for (i in 0..4) { println("Emit $i")
这三个 Kotlin 插件和它们的实际作用有什么区别? plugins { id 'kotlin-android' id 'org.jetbrains.kotlin.android'
我正在为某些现有库添加 Kotlin 原生 linuxX64 目标支持。库已成功编译,但在运行测试用例时,出现以下运行时错误: kotlin.native.concurrent.InvalidMuta
关闭。这个问题需要details or clarity .它目前不接受答案。 想改进这个问题吗? 通过 editing this post 添加细节并澄清问题. 关闭 2 年前。 Improve t
我创建了一个类并向其添加了一个与成员函数具有相同签名的扩展,并执行了这个方法,它总是执行成员方法。 class Worker { fun work() = "...working" } fun
我知道传递给函数的参数将被视为“val”,即使变量被初始化为“var”。但这对我来说一直是个问题。在下面的示例代码中,我想通过使用函数“changeNum”修改变量“num”的值。但当然,Kotlin
现在,我正在尝试用 Kotlin 重写我的 Java 应用程序。然后,我遇到了日志语句,比如 log.info("do the print thing for {}", arg); 所以我有两种方法可
有点出名article关于许多语言的异步编程模型的状态,指出它们存在“颜色”问题,特别是将生态系统分为两个独立的世界:异步和非异步。以下是这种语言的属性: 每个函数都有一种颜色,红色或蓝色(例如asy
因为 KDoc 文档生成引擎是 abandoned in favor of Dokka , Kotlin 文档应该称为“KDoc 注释”,还是“Dokka 注释”? 最佳答案 如所述here , KD
我想在可空对象上传递函数引用。以 Android 为例,假设我想使用 Activity#onBackPressed来自作为该事件的子级的片段。 如果我想调用这个函数,我可以很容易地做到 activit
我有一个列表 (x, y)其中y只能是 0 或 1 这样 例如: [(3, 0), (3, 1), (5, 1)] [(5, 0), (3, 1), (5, 1)] [(1, 1), (3, 1),
从强类型语言的定义来看: A strongly-typed programming language is one in which each type of data (such as intege
这不能编译的事实是否意味着它们不是一流的类型? fun foo(s: String): Int = s.length // This won't compile. val bar = foo 有没有办
如果在 Java i++是一个表达式和 i++;是一个表达式语句,分号(;) 在 Kotlin 中是可选的,是 i++ Kotlin 中的表达式或表达式语句? 最佳答案 i++是一个表达式,因为它有一
代码(如下所示)是否正确?它取自 Kotlin-docs.pdf 的第 63 页,这也是 https://kotlinlang.org/docs/reference/generics.html 的最后
我正在尝试使用 Kotlin 为 Android 的一些全局 API 解析器(检查网络连接、调用 API 并通过来自源的单个调用返回格式化数据),并且在某些时候我不得不创建一个通用类型 object就
kotlinlang 中的任务: 使用月份变量重写此模式,使其与格式 13 JUN 1992(两位数字、一个空格、一个月份缩写、一个空格、四位数字)中的日期相匹配。 答案是:val month = "
我是一名优秀的程序员,十分优秀!