我正在与借阅检查员打架.我有两个相似的代码片段,一个像我期望的那样工作,另一个没有.
一个像我期望的那样工作:
mod case1 {
struct Foo {}
struct Bar1 {
x: Foo,
}
impl Bar1 {
fn f<'a>(&'a mut self) -> &'a Foo {
&self.x
}
}
// only for example
fn f1() {
let mut bar = Bar1 { x: Foo {} };
let y = bar.f(); // (1) 'bar' is borrowed by 'y'
let z = bar.f(); // error (as expected) : cannot borrow `bar` as mutable more
// than once at a time [E0499]
}
fn …Run Code Online (Sandbox Code Playgroud) 考虑以下代码:
let u: Vec<u8> = (64..74).collect();
let v: Vec<u8> = u.iter().map(|i| i + 1).collect();
Run Code Online (Sandbox Code Playgroud)
u没有移动,因此v不可避免地是新分配的。
但是,如果我执行以下操作:
let w: Vec<u8> = u.into_iter().map(|i| i + 1).collect();
Run Code Online (Sandbox Code Playgroud)
u被感动了,w是它改造的名字。这是一些代表我的意思的伪代码:
let u: Vec<u8> = (64..74).collect();
let v: Vec<u8> = u.iter().map(|i| i + 1).collect();
Run Code Online (Sandbox Code Playgroud)
(在我看来)不需要新的分配,因为我们将类型映射到自身。这段代码不会出现这种情况:
let t: Vec<u8> = (64..74).collect();
let s: String = t.into_iter().map(|i| i as char).collect();
Run Code Online (Sandbox Code Playgroud)
总结我的问题
Vec当我们将 aVec转换为迭代器,然后将此迭代器映射到相同类型元素上的迭代器,然后将结果收集到 a时,是否有分配 new Vec?
如果确实有分配,为什么?
我试图--emit=mir,但我无法找到答案。我每晚都使用 rustc 1.20(如果这很重要)。
使用GHC 8.0.2版以下程序:
import Debug.Trace
f=trace("f was called")$(+1)
main = do
print $ f 1
print $ f 2
Run Code Online (Sandbox Code Playgroud)
输出:
f was called
2
3
Run Code Online (Sandbox Code Playgroud)
这是预期的行为吗?如果是,为什么?我希望字符串f was called被打印两次,一个前2前一个3.
TIO的结果相同:在线尝试!
编辑 但是这个程序:
import Debug.Trace
f n=trace("f was called:"++show n)$n+1
main = do
print $ f 1
print $ f 2
Run Code Online (Sandbox Code Playgroud)
输出:
f was called:1
2
f was called:2
3
Run Code Online (Sandbox Code Playgroud)
我怀疑这些行为与懒惰有关,但我的问题仍然存在:这是预期的行为,如果是,为什么?
Hackage断言:
跟踪函数在返回第二个参数作为结果之前输出作为其第一个参数给出的跟踪消息.
我在第一个例子中没有看到它.
编辑2基于@amalloy评论的第三个例子:
import Debug.Trace
f n=trace "f was called"$n+1
main = …Run Code Online (Sandbox Code Playgroud) 最近,我对 SO 进行了讨论(请参阅上下文),内容涉及以下两段代码:
res = [d.get(next((k for k in d if k in s), None), s) for s in lst]
Run Code Online (Sandbox Code Playgroud)
和:
res = [next((v for k,v in d.items() if k in s), s) for s in lst]
Run Code Online (Sandbox Code Playgroud)
两者都迭代s列表中的字符串并在 dict 中lst查找。如果找到,则返回关联值,否则返回。我很确定第二段代码比第一段更快,因为(对于每个)字典中没有查找,只是对(键,值)对进行迭代。sdsss
问题是: 如何检查这是否真的发生在幕后?
我第一次尝试该dis模块,但结果令人失望(python 3.6.3):
>>> dis.dis("[d.get(next((k for k in d if k in s), None), s) for s in lst]")
1 0 LOAD_CONST 0 (<code object <listcomp> …Run Code Online (Sandbox Code Playgroud) rust ×2
disassembly ×1
ghc ×1
haskell ×1
iterator ×1
lifetime ×1
performance ×1
python ×1
trace ×1
vector ×1