Rust是否检测到重复的闭包(例如循环中定义的闭包)?

3okqufwl  于 2023-02-23  发布在  其他
关注(0)|答案(2)|浏览(139)

当我需要调用许多可能失败的函数时,我有时会把它们放到闭包中,然后我?它们并捕获任何特殊的变量(其他语言中的异常机制)。
下面是我对https://www.codewars.com/kata/5a090c4e697598d0b9000004/train/rust的解决方案。

use std::collections::VecDeque;

fn solve(nums: &[i32]) -> Vec<i32> {
    let mut sorted = VecDeque::from_iter(nums.iter().copied());
    sorted.make_contiguous().sort();

    let mut rearranged = vec![];
    while let Some(()) =
        (||->Option<()>{
            rearranged.push(sorted.pop_back()?);
            rearranged.push(sorted.pop_front()?);
            Some(())
        })()
    {}
    rearranged
}

工作正常,很干净,但我想知道,“Rust是否在每个while循环迭代上都产生一个闭包”
如果是,它是否检测到生成的闭包“只是第一个闭包的重复”,并优化重复?
我很感谢一些理论上的考虑,当闭包是在循环内部定义的情况下,像上面。什么优化编译器做,以避免重复的数据?

7kqas0il

7kqas0il1#

最简单的检查方法是查看生成的程序集,当然使用--release
验证码:

solve:
    pushq   %rbp
    pushq   %r15
    pushq   %r14
    pushq   %r13
    pushq   %r12
    pushq   %rbx
    subq    $200, %rsp
    movq    %rdi, %r8
    testq   %rdx, %rdx
    je  .LBB6_6
    movq    %rdx, %rbx
    movq    %r8, 128(%rsp)
    xorl    %ebp, %ebp
    movq    %rdx, %rax
    shrq    $61, %rax
    sete    %al
    jne .LBB6_128
    movq    %rsi, %r14
    leaq    (,%rbx,4), %rdi
    movb    %al, %bpl
    shlq    $2, %rbp
    movq    %rdi, 104(%rsp)
    movq    %rbp, %rsi
    callq   *__rust_alloc@GOTPCREL(%rip)
    testq   %rax, %rax
    je  .LBB6_129
    movq    %rbx, 40(%rsp)
    leaq    (%r14,%rbx,4), %r12
    addq    $-4, %r12
    movq    %r12, %rbp
    subq    %r14, %rbp
    movq    %rbp, %rbx
    shrq    $2, %rbx
    leaq    4(%rbp), %rdx
    andq    $-4, %rdx
    movq    %rax, (%rsp)
    movq    %rax, %rdi
    movq    %r14, %rsi
    callq   *memcpy@GOTPCREL(%rip)
    leaq    1(%rbx), %rax
    movq    %rax, 16(%rsp)
    cmpq    $80, %rbp
    jae .LBB6_7
    movl    $1, %r15d
    cmpq    %r14, %r12
    movq    (%rsp), %r12
    je  .LBB6_106
    movq    16(%rsp), %rax
    leaq    (%r12,%rax,4), %r8
    addq    $-4, %r8
    leaq    (%r12,%rbx,4), %rcx
    addq    $4, %rcx
    movq    $-2, %rbp
    jmp .LBB6_97

在变量(playground)中定义闭包:

solve:
    pushq   %rbp
    pushq   %r15
    pushq   %r14
    pushq   %r13
    pushq   %r12
    pushq   %rbx
    subq    $200, %rsp
    movq    %rdi, %r8
    testq   %rdx, %rdx
    je  .LBB6_6
    movq    %rdx, %rbx
    movq    %r8, 128(%rsp)
    xorl    %ebp, %ebp
    movq    %rdx, %rax
    shrq    $61, %rax
    sete    %al
    jne .LBB6_128
    movq    %rsi, %r14
    leaq    (,%rbx,4), %rdi
    movb    %al, %bpl
    shlq    $2, %rbp
    movq    %rdi, 104(%rsp)
    movq    %rbp, %rsi
    callq   *__rust_alloc@GOTPCREL(%rip)
    testq   %rax, %rax
    je  .LBB6_129
    movq    %rbx, 40(%rsp)
    leaq    (%r14,%rbx,4), %r12
    addq    $-4, %r12
    movq    %r12, %rbp
    subq    %r14, %rbp
    movq    %rbp, %rbx
    shrq    $2, %rbx
    leaq    4(%rbp), %rdx
    andq    $-4, %rdx
    movq    %rax, (%rsp)
    movq    %rax, %rdi
    movq    %r14, %rsi
    callq   *memcpy@GOTPCREL(%rip)
    leaq    1(%rbx), %rax
    movq    %rax, 16(%rsp)
    cmpq    $80, %rbp
    jae .LBB6_7
    movl    $1, %r15d
    cmpq    %r14, %r12
    movq    (%rsp), %r12
    je  .LBB6_106
    movq    16(%rsp), %rax
    leaq    (%r12,%rax,4), %r8
    addq    $-4, %r8
    leaq    (%r12,%rbx,4), %rcx
    addq    $4, %rcx
    movq    $-2, %rbp
    jmp .LBB6_97

它们是一样的。

zazmityj

zazmityj2#

不。这是不可能的,因为这意味着在运行时动态生成代码。闭包的定义忽略了控制流。

相关问题