gpt4 book ai didi

scala - 在猫中实现 while(true)

转载 作者:行者123 更新时间:2023-12-01 09:29:40 25 4
gpt4 key购买 nike

关闭。这个问题需要details or clarity .它目前不接受答案。












想改善这个问题吗?通过 editing this post 添加详细信息并澄清问题.

2年前关闭。




Improve this question




你如何在猫中实现以下循环?

首先(正常的 while(true) 循环):

while(true) { doSomething() }

第二个(while(true) 循环递增):

var i = 1
while(true) { i +=1; doSomething() }

第三个(while(true) 里面有几个自变量):

var x = 1
var y = 2
while(true) {
x = someCalculation()
y = otherCalculation()
doSomething()
}

最佳答案

我认为你的问题有点不恰当,但它以一种有趣的方式不恰当,所以也许我应该尝试解释我的意思。

询问“我如何实现

var i = 1
while(true) { i +=1; doSomething() }

在 Cats 中”的回答很简单:与您在不使用任何库的情况下在普通 Scala 中实现它的方式完全相同。在这种特殊情况下,Cats 不会使您能够实现任何在运行时行为截然不同的东西。它使您能够做什么要做的是更准确地表达每段代码具有的(副作用)效果,并将其编码为类型级别信息,可以在编译时静态类型检查期间进行验证。

所以,问题不应该是

"How do I do X in Cats?"



反而

"How do I prove / make explicit that my code does (or does not) have certain side effects using Cats?".



您示例中的 while 循环只是在 doSomething() 中执行了一些副作用。 ,并且它会干扰变量 i 的可变状态只要它想,就不会在组成子表达式的类型中明确表示。

现在你可能会使用类似 effects.IO 的东西, 并至少包裹你 doSomething 的 body 在 IO ,从而明确表示它执行输入/输出操作(此处:打印到 StdOut):
// Your side-effectful `doSomething` function in IO
def doSomething: IO[Unit] = IO { println("do something") }

现在您可能会问如何以这样的方式写下循环,以便它也很明显地执行此类 IO 操作。你可以这样做:
// Literally `while(true) { ... }`
def whileTrue_1: IO[Unit] =
Monad[IO].whileM_(IO(true)) { doSomething }

// Shortcut using `foreverM` syntax
import cats.syntax.flatMap._
def whileTrue_2: IO[Nothing] = doSomething.foreverM

// Use `>>` from `syntax.flatMap._`
def whileTrue_3: IO[Unit] = doSomething >> whileTrue_3

现在,如果你想加入可变变量 i在混合中,您可以将可变内存的写入/读取视为另一个 IO 操作:
// Treat access to mutable variable `i` as
// yet another IO side effect, do something
// with value of `i` again and again.
def whileInc_1: IO[Unit] = {
var i = 1
def doSomethingWithI: IO[Unit] = IO {
println(s"doing sth. with $i")
}

Monad[IO].whileM_(IO(true)) {
for {
_ <- IO { i += 1 }
_ <- doSomethingWithI
} yield ()
}
}

或者,您可能决定跟踪 i 状态的所有访问/更改。非常重要以至于您想使其明确,例如使用 StateT跟踪类型状态的 monad 转换器 Int :
// Explicitly track variable `i` in a state monad
import cats.data.StateT
import cats.data.StateT._
def whileInc_2: IO[Unit] = {

// Let's make `doSthWithI` not too boring,
// so that it at least accesses the state
// with variable `i`
def doSthWithI: StateT[IO, Int, Unit] =
for {
i <- get[IO, Int]
_ <- liftF(IO { println(i) })
} yield ()

// Define the loop
val loop = Monad[StateT[IO, Int, ?]].whileM_(
StateT.pure(true)
) {
for {
i <- get[IO, Int]
_ <- set[IO, Int](i + 1)
_ <- doSthWithI
} yield ()
}

// The `_._2` is there only to make the
// types match up, it's never actually used,
// because the loop runs forever.
loop.run(1).map(_._2)
}

它的功能与两个变量类似 xy (只需使用 (Int, Int) 而不是 Int 作为状态)。

不可否认,这段代码看起来有点冗长,尤其是最后一个例子开始看起来像企业版的嗡嗡声,但关键是如果你始终如一地将这些技术应用到你的代码库中,你就不必深入研究函数的主体,仅根据其签名就可以很好地了解它可以(或不能)做什么。当您试图理解代码时,这反过来是有利的(您可以通过浏览签名来理解它的作用,而无需阅读正文中的代码),并且它还迫使您编写更易于测试的更简单的代码(在至少是这个想法)。

关于scala - 在猫中实现 while(true),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56056228/

25 4 0
文章推荐: javascript - 如何使用 JavaScript 动态设置 `onSubmit`
文章推荐: r - 如何将id变量添加到R中的多个数据集
文章推荐: moovweb - 在 Tritium 中,如何将所有

标签转换为

Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com