如何执行val的多步骤初始化
为了学习一点kotlin
我建立了一个基于经典论文Monadic Parser Combinators的解析器组合库。
在我的情况下,我需要转发declare解析器,因为递归语法。 准备最终表达式解析器时,我需要更新前向声明
我第一次尝试是这样的
val addLike = mulLike separatedBy addLikeSeparator val expression = forwarded.second(addLike) addLike
这个想法是执行一个短的初始化,然后返回addLike
来初始化值。 这是一个非常常见的模式,当我做一些F#编程,我认为这是一个很好的模式,因为它简化了隐藏初始化细节。
然而,这在kotlin
中kotlin
:
Error:(195, 5) Kotlin: Expecting a top level declaration
这种方法也失败了:
val addLike = mulLike separatedBy addLikeSeparator val expression = forwarded.second(addLike); addLike
问题似乎是这样的;
将两个expressions
组合成一个statement
。
所以我试了一下,
希望它的行为有点像C / C ++,但没有运气:
val addLike = mulLike separatedBy addLikeSeparator val expression = forwarded.second(addLike), addLike
在阅读kotlin
规范后,我发现没有明确的解决方案,所以我转向了StackOverflow。 这个模式是否可以在kotlin
中以惯用的方式kotlin
?
更新
@Eric建议使用,如果run
,如果我更新我的代码,最终的解决方案有点像这样:
val expression = run () { forwarded.second(addLike) whitespaces keepRight addLike keepLeft expectEOS() }
这是我可以接受的。 谢谢@Eric。
在将对象分配给任何数据字段之前,有很多方法可以在对象上执行初始化代码。
您可以使用run
功能。 通过run
你可以编写一个lambda函数,在这里你可以执行你的初始化代码,然后把lambda的返回值作为数据字段的值:
val expression = run() { // initialization code here forwarded.second(addLike) // writing "return@run" is optional return@run addLike }
你也可以使用亚历山大·乌达洛夫的答案中提到的apply
。 你可以实例化你想分配数据字段的值,并将lambda中的初始化代码传入apply
:
val variable = addLike.apply() { // initialization code here forwarded.second(this) // "this" refers to addLike within this lambda }
你可以使用懒惰的代表 。 这与运行类似,只是lambda不会在构建期间立即执行以初始化数据字段。 而是在第一次访问数据字段时执行:
val expression by lazy() { // initialization code here forwarded.second(addLike) // writing "return@run" is optional return@lazy addLike }
您可以使用标准库中的apply
函数。 它在接收器上执行一个操作,然后返回:
val expression = addLike.apply { forwarded.second(this) }