![](/img/trans.png)
[英]Scala: Is ForComprehension a Functional approach or imperative?
[英]Transform imperative function to be more functional
我在这里找到这个人:
var time = createdAt
var coolDown = duration
while (time <= timestamp) {
if (time <= timestamp && timestamp <= time + timeLimit.getOrElse(0L)) {
return None
} else {
time = time + timeLimit.getOrElse(0L) + coolDown
coolDown = 2 * coolDown
}
}
Some("Error")
并希望将其重构为比命令式功能更强大的功能,但是我在函数式编程方面还很陌生,我想知道您实现该功能的方法。 我用单元测试进行了介绍,并打算创建一个数学函数或具有一个递归函数。 有没有逐步进行的方法? 从头开始? 您将如何解决?
该函数应返回以下内容:
-N-|-C-|-N-|--C(2x)--|-N-|----C(4x)----|-N-|--------C(8x)---------|-N-|...
它返回Error
的时间呈指数增长。 假设coolDown
和timeLimit
是第一天返回None
的第二天,第二天Error
,第三天None
,然后两天Error
,依此类推...
是的,在@Carcigenicate发表评论后,这很容易。 我已经开始逐步进行重写,并且方向一致。 结果:
def evaluateCooldown(time: Long, coolDown: Long): Option[String] = {
if (time <= timestamp) {
if (timestamp <= time + timeLimit.getOrElse(0L)) {
None
} else {
evaluateCooldown(time + timeLimit.getOrElse(0L) + coolDown, 2 * coolDown)
}
} else {
Some("Error")
}
}
evaluateCooldown(unlockedAt, cdc.duration)
自然,有很多方法可以做到这一点。 这是使用惰性ADT的一种...
我们定义val ts = timestamp.getOrElse(0L)
def slen(n: Int) = math.pow(2, n - 1) * countDown + timeLimit
val prev = Stream.iterate(1)(slen).scan(0)(_ + _).takeWhile(_ < ts).last
查找时间戳之前的最后一个N | C部分的列表长度,然后
if (prev + timeLimit > ts) None else Some("Error")
另一种优化方法
我们可以用
用累积和替换scan
def clen(n: Int) = (math.pow(2, n) - 1) * countDown + n * timeLimit
val nextn = Stream.from(1).find(clen(_) > ts)
在时间戳之后找到第一部分的索引,然后
if (len(nextn - 1) + timeLimit > ts) None else Some("Error")
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.