我正在将一大块(2000行)专有C代码转换为Rust。在C中,通常会向下运行指针、数组索引等,只要它是非负的。在“铁锈”中,简化为“骨头”,它看起来就像:
while i >= 0 && more_conditions {
more_work;
i -= 1;
}
当然,当i
是usize
时,您会从减法中得到一个下溢出。我已经学会了如何使用for
循环和.rev()
,用一个抵消我的索引,或者使用不同的类型,使用as usize
等等。
通常情况下,它可以工作,而且通常我可以让它清晰易懂,但是我正在修改的代码充满了相互间运行的索引,并最终用i_low > i_high
进行了测试。
类似于(在锈病中)
loop {
while condition1(i_low) { i_low += 1; }
while condition2(i_high) { j_high -= 1; }
if i_low > i_high { return something; }
do_something_else;
}
随着i_high
的运行超过0,这种恐慌时有发生。
我在代码中插入了大量的j_high >= 0 &&
,而且它的可读性大大降低。
经验丰富的Rust程序员如何避免使用-1的usize
变量?
for i in (0..size).rev()
i as usize
,在检查i < 0
之后i-1
?还是你只是最终学会了围绕这些情况编写程序?
澄清:C代码并没有中断--据推测,它已经投入生产十年了,24/7在多台服务器上构建视频片段。它只是没有遵循锈蚀惯例--它通常会返回-1作为索引,然后再用-1来处理数组的低索引,索引一直为负值。所有这些都是在问题发生之前处理的--丑陋,但功能强大。类似于:
incident_segment = detect_incident(array, start, end);
attach(array, incident_segment);
store(array, start, incident_segment - 1);
process(array, incident_segment + 1, end);
在上面的代码中,三个产生的调用中的每一个都可能得到一个段索引,即-1 (附加、存储)或超出边界(进程),但是在调用之后。
我的锈蚀代码似乎也有效。事实上,为了处理负的usize,我添加了额外的逻辑来修剪一些递归,所以它运行的速度和C代码一样快(显然更快,但这也是因为我将输出分配到多个驱动器上)。
问题是客户端不希望进行完全重写,并且希望“本地”程序员能够相互检查这两个程序。根据到目前为止的答案,我认为使用i64和根据需要进行转换/隐藏可能是生成易于“本机”阅读的代码的最佳方法。我个人不需要喜欢..。
发布于 2018-10-12 18:01:51
如果你想成其为的话:
for j in (0..=i).rev() {
if conditions {
break;
}
//use j as your new i here
}
注意在迭代器中使用..=i
,这意味着它实际上将迭代包括i
:[0, 1, 2, ..., i-1, i]
,否则,您将得到[0, 1, 2, ..., i-2, i-1]
否则,下面是代码:
while (i as isize - 1) != -2 && more_conditions {
more_work;
i -= 1;
}
发布于 2018-10-12 18:32:25
我可能首先使用saturating_sub
(并行结构的_add
):
while condition1(i_low) { i_low = i_low.saturating_add(1); }
while condition2(i_high) { j_high = j_high.saturating_sub(1); }
您需要小心,以确保您的逻辑处理的值饱和在零。您还可以在wrapping_sub
中使用更多类似C的语义。
老实说,没有一刀切的解决办法。很多时候,如果你把复杂的逻辑抽象化一点,或者稍微把它侧转一下,它就会变得更简单。你没有提供任何具体的例子,所以我们不能给出任何有用的建议。我用迭代器解决了太多的问题,所以这通常是我的第一个解决方案。
捕获异常
绝对不是。这是非常低效和非惯用的。
https://stackoverflow.com/questions/52788350
复制相似问题