【发布时间】:2012-06-25 13:21:50
【问题描述】:
每当我尝试在 D 中使用范围时,我都会惨遭失败。
在 D 中使用范围的正确方法是什么? (请参阅内联 cmets 了解我的困惑。)
void print(R)(/* ref? auto ref? neither? */ R r)
{
foreach (x; r)
{
writeln(x);
}
// Million $$$ question:
//
// Will I get back the same things as last time?
// Do I have to check for this every time?
foreach (x; r)
{
writeln(x);
}
}
void test2(alias F, R)(/* ref/auto ref? */ R items)
{
// Will it consume items?
// _Should_ it consume items?
// Will the caller be affected? How do I know?
// Am I supposed to?
F(items);
}
【问题讨论】:
-
范围是集合的接口,就像其他语言中的迭代器一样。虽然你总是可以迭代一个迭代器(或一个范围),但你不能有效地对其他行为进行广泛的概括。我的理解是范围本身始终是一个引用类型,但底层集合可以是任何支持接口的东西,所以如果你要修改范围的元素,你应该使用 ref 并且你应该使用约束来确保基础集合是可写的。如果你不打算修改元素,那么你不需要参考。
-
对不起,我要澄清一下:如果你要修改范围的元素,你应该在 foreach 循环中使用 ref (如果集合的元素是值类型),我不'不认为您需要该函数的 ref 限定符,因为范围应该始终是一个参考,但我可能会忽略一些东西。
-
@Tim:我认为你误解了这个问题(或者我不明白你的意思)。我说的是修改范围,而不是items。 (比如,想想:
LockingTextReader(stdin),而不是数组。其中一个是单通道,另一个是多通道。) -
嗯,好的,所以我在让 DMD 强制执行 const 和 immutable 应该做出的保证时遇到了很多麻烦,但理论上......无论如何,
std.range.isForwardRange是内置的在“可重复”范围合同中。 -
没问题,感谢您的讨论,它帮助我理清了自己的想法:D