以下是一个非官方的概述,介绍这些名称似乎是如何产生的。
let
let
受到函数式编程世界的启发。根据 Wikipedia 的说法:
"let" 表达式将函数定义与受限范围关联起来
在 Haskell 等 FP 语言中,您可以使用 let
在受限范围内绑定变量值,如下所示:
aaa = let y = 1+2
z = 4+6
in y+z
在 Kotlin 中,等效(尽管过于复杂)的代码将是
fun aaa() = (1+2).let { y ->
(4+6).let { z ->
y + z
}
}
let
的典型用法是将某些计算的结果绑定到作用域中,而不会“污染”外部作用域。
creater.createObject().let {
if (it.isCorrect && it.shouldBeLogged) {
logger.log(it)
}
}
with
with
函数的灵感来自于像 Delphi 或 Visual Basic(以及可能许多其他语言)中的 with
语言结构,其中
The with keyword is a convenience provided by Delphi for referencing
elements of a complex variable, such as a record or object.
myObject.colour := clRed;
myObject.size := 23.5;
myObject.name := 'Fred';
can be rewritten :
with myObject do
begin
colour := clRed;
size := 23.5;
name := 'Fred';
end;
相应的 Kotlin 代码如下:
with(myObject) {
color = clRed
size = 23.5
name = "Fred"
}
apply
apply
是在里程碑阶段(M13)相对较晚添加到stdlib中的。您可以看到this2015年的问题,用户要求恰好需要这样的函数,甚至建议后来使用的名称“apply”。
在https://youtrack.jetbrains.com/issue/KT-6903和https://youtrack.jetbrains.com/issue/KT-6094中,您可以看到关于命名的讨论。提出了像build
和init
等替代方案,但最终由Daniil Vodopian提出的apply
赢得了胜利。
apply
类似于with
,因为它可以用于初始化构造函数之外的对象。这就是为什么,在我看来,apply
也可以被命名为with
。然而,由于with
首先添加到stdlib中,Kotlin开发人员决定不破坏现有代码,并使用不同的名称添加它。
具有讽刺意味的是,语言Xtend提供了所谓的with-operator =>
,基本上与apply
相同。
also
also
比apply
更晚加入到stdlib中,即在版本1.1中。同样,https://youtrack.jetbrains.com/issue/KT-6903中包含了相关的讨论。该函数基本上与apply
相似,只是它接受一个普通的lambda表达式(T) -> Unit
,而不是扩展lambda表达式T.() -> Unit
。
其中提出的名称有"applyIt"、"applyLet"、"on"、"tap"、"touch"、"peek"和"make"等。但是"also"获胜了,因为它不会与任何关键字或其他stdlib函数发生冲突,并且它的用法(或多或少)读起来像英语句子。
例如:
val object = creater.createObject().also { it.initiliaze() }
这段文字有点像
创建者,创建对象并同时初始化!
其他标准库函数的用法也有点像英语句子,包括在1.1版本中添加的takeIf
和takeUnless
。
run
最后,run
函数实际上有两个签名。第一个签名 fun <R> run(block: () -> R): R
简单地接受一个 lambda 并运行它。它通常用于将 lambda 表达式的结果分配给顶级属性。
val logger = run {
val name = System.property("logger_name")
Logger.create(name)
}
第二个签名
fun <T, R> T.run(block: T.() -> R): R
是一个扩展函数,它将扩展lambda作为参数,并似乎也因对称性的原因而被命名为“run”。它还在扩展接收方的上下文中“运行”lambda。
val result = myObject.run {
intitialize()
computeResult()
}
我不知道这个命名背后有什么历史原因。
nullables
中使用let
来继续执行。我当场学会了。with
或also
也是一样。一旦你知道它们的存在,你就会遇到一些你知道有某个东西,但你不记得哪个是哪个的情况。多次查看文档可以确保你将来会记住它们。至少这是我的做法。 - MikeSW