如何进行闭包以避免捕获变量的冗余克隆?

时间:2019-01-15 00:07:30

标签: rust closures clone

我正在尝试实现经典的$(document).ready(function(){ $("#form_submission_phone_number").keypress(function(e){ if(this.value.length!=11){ $('.nom').remove(); $(this).after('<span class="nom" style="font-size: 14px; font-weight: bold; color: #FF0000; opacity: 0.6;margin-top: -2px;display: block;">please enter full 11-digit mobile number starting with 1</span>'); }else{ $('.nom').remove(); } var keyCode = e.which; /* 8 - (backspace) 32 - (space) 48-57 - (0-9)Numbers */ if ( (keyCode != 8 || keyCode ==32 ) && (keyCode < 48 || keyCode > 57)) { return false; } if(this.value.length==11){ return false; } }); $('#form_submission_phone_number').keyup(function(e){if(e.keyCode == 8)$(this).val('');}) });函数,该函数需要一个可加的东西,并返回一个闭包,而闭包需要另一个可加的东西,并返回总和。这是我的尝试:

make_adder

因为我不想将use std::ops::Add; fn make_adder<T: Add + Clone>(x: T) -> impl Fn(T) -> T::Output { move |y| x.clone() + y } 限制为T,所以我在闭包内调用Copy。我认为这也意味着闭包将始终存在一个冗余clone()作为“原型”。我能以某种方式做得更好吗?

2 个答案:

答案 0 :(得分:3)

实际上,您无法避免这种情况。您永远都不知道闭包是否会在其他时间被调用。您需要保留该值以防万一。在性能分析确定这是一个瓶颈之前,我不会担心执行克隆。


在某些情况下,您可以将闭包类型更改为FnOnce,这将强制其只能被调用一次:

fn make_adder<T>(x: T) -> impl FnOnce(T) -> T::Output
where
    T: Add,
{
    move |y| x + y
}

在其他情况下,您可能可以向该问题添加一些间接方式。例如,不要传递一个T,而是传递一个生成T的闭包(大概不是通过克隆自己的捕获变量...)。该T始终可以直接食用:

fn make_adder<T>(x: impl Fn() -> T) -> impl Fn(T) -> T::Output
where
    T: Add,
{
    move |y| x() + y
}

答案 1 :(得分:2)

如果您使用的是支持在引用上加法的类型(也许所有有用的类型,包括内置数字类型),也许您可​​以使用引用。

fn make_adder<T, U>(x: T) -> impl Fn(T) -> U
where
    for<'a> &'a T: Add<T, Output = U>,
{
    move |y| &x + y
}

fn make_adder<'a, T>(x: &'a T) -> impl Fn(T) -> <&'a T as Add<T>>::Output
where
    &'a T: Add<T>,
{
    move |y| x + y
}