rust func as function arg type
原文链接 https://liutaihua.github.io/2015/12/20/rust-func-as-function-arg-type.html
注:以下为加速网络访问所做的原文缓存,经过重新格式化,可能存在格式方面的问题,或偶有遗漏信息,请以原文为准。
<!-- common.css --> * {-webkit-tap-highlight-color: rgba(0,0,0,0);}html {-webkit-text-size-adjust: none;}body {font-family: Arial, Helvetica, sans-serif;margin: 0;color: #333;word-wrap: break-word;}h1, h2, h3, h4, h5, h6 {line-height: 1.1;}img {max-width: 100% !important;}blockquote {margin: 0;padding: 0 15px;color: #777;border-left: 4px solid #ddd;}hr {background-color: #ddd;border: 0;height: 1px;margin: 15px 0;}code {font-family: Menlo, Consolas, 'Ubuntu Mono', Monaco, 'source-code-pro', monospace;line-height: 1.4;margin: 0;padding: 0.2em 0;font-size: 85%;background-color: rgba(0,0,0,0.04);border-radius: 3px;}pre {margin: 0;}pre > code {margin: 0;padding: 0;font-size: 100%;word-break: normal;background: transparent;border: 0;}ol {list-style-type: decimal;}ol ol, ul ol {list-style-type: lower-latin;}ol ol ol, ul ol ol, ul ul ol, ol ul ol {list-style-type: lower-roman;}table {border-spacing: 0;border-collapse: collapse;margin-top: 0;margin-bottom: 16px;}table th {font-weight: bold;}table th, table td {padding: 6px 13px;border: 1px solid #ddd;}table tr {border-top: 1px solid #ccc;}table tr:nth-child(even) {background-color: #f8f8f8;}input[type="checkbox"] {cursor: default;margin-right: 0.5em;font-size: 13px;}.task-list-item {list-style-type: none;}.task-list-item+.task-list-item {margin-top: 3px;}.task-list-item input {float: left;margin: 0.3em 1em 0.25em -1.6em;vertical-align: middle;}#tag-field {margin: 8px 2px 10px;}#tag-field .tag {display: inline-block;background: #cadff3;border-radius: 4px;padding: 1px 8px;color: black;font-size: 12px;margin-right: 10px;line-height: 1.4;} <!-- ace-static.css --> .ace_static_highlight {white-space: pre-wrap;}.ace_static_highlight .ace_gutter {width: 2em;text-align: right;padding: 0 3px 0 0;margin-right: 3px;}.ace_static_highlight.ace_show_gutter .ace_line {padding-left: 2.6em;}.ace_static_highlight .ace_line {position: relative;}.ace_static_highlight .ace_gutter-cell {-moz-user-select: -moz-none;-khtml-user-select: none;-webkit-user-select: none;user-select: none;top: 0;bottom: 0;left: 0;position: absolute;}.ace_static_highlight .ace_gutter-cell:before {content: counter(ace_line, decimal);counter-increment: ace_line;}.ace_static_highlight {counter-reset: ace_line;} .ace-monokai .ace_gutter {background: #2F3129;color: #8F908A}.ace-monokai .ace_print-margin {width: 1px;background: #555651}.ace-monokai {background-color: #272822;color: #F8F8F2}.ace-monokai .ace_cursor {color: #F8F8F0}.ace-monokai .ace_marker-layer .ace_selection {background: #49483E}.ace-monokai.ace_multiselect .ace_selection.ace_start {box-shadow: 0 0 3px 0px #272822;border-radius: 2px}.ace-monokai .ace_marker-layer .ace_step {background: rgb(102, 82, 0)}.ace-monokai .ace_marker-layer .ace_bracket {margin: -1px 0 0 -1px;border: 1px solid #49483E}.ace-monokai .ace_marker-layer .ace_active-line {background: #202020}.ace-monokai .ace_gutter-active-line {background-color: #272727}.ace-monokai .ace_marker-layer .ace_selected-word {border: 1px solid #49483E}.ace-monokai .ace_invisible {color: #52524d}.ace-monokai .ace_entity.ace_name.ace_tag,.ace-monokai .ace_keyword,.ace-monokai .ace_meta.ace_tag,.ace-monokai .ace_storage {color: #F92672}.ace-monokai .ace_punctuation,.ace-monokai .ace_punctuation.ace_tag {color: #fff}.ace-monokai .ace_constant.ace_character,.ace-monokai .ace_constant.ace_language,.ace-monokai .ace_constant.ace_numeric,.ace-monokai .ace_constant.ace_other {color: #AE81FF}.ace-monokai .ace_invalid {color: #F8F8F0;background-color: #F92672}.ace-monokai .ace_invalid.ace_deprecated {color: #F8F8F0;background-color: #AE81FF}.ace-monokai .ace_support.ace_constant,.ace-monokai .ace_support.ace_function {color: #66D9EF}.ace-monokai .ace_fold {background-color: #A6E22E;border-color: #F8F8F2}.ace-monokai .ace_storage.ace_type,.ace-monokai .ace_support.ace_class,.ace-monokai .ace_support.ace_type {font-style: italic;color: #66D9EF}.ace-monokai .ace_entity.ace_name.ace_function,.ace-monokai .ace_entity.ace_other,.ace-monokai .ace_entity.ace_other.ace_attribute-name,.ace-monokai .ace_variable {color: #A6E22E}.ace-monokai .ace_variable.ace_parameter {font-style: italic;color: #FD971F}.ace-monokai .ace_string {color: #E6DB74}.ace-monokai .ace_comment {color: #75715E}.ace-monokai .ace_indent-guide {background: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAACCAYAAACZgbYnAAAAEklEQVQImWPQ0FD0ZXBzd/wPAAjVAoxeSgNeAAAAAElFTkSuQmCC) right repeat-y} <!-- export.css --> body{margin:0 auto;max-width:800px;line-height:1.4} #nav{margin:5px 0 10px;font-size:15px} #titlearea{border-bottom:1px solid #ccc;font-size:17px;padding:10px 0;} #contentarea{font-size:15px;margin:16px 0} .cell{outline:0;min-height:20px;margin:5px 0;padding:5px 0;} .code-cell{font-family:Menlo,Consolas,'Ubuntu Mono',Monaco,'source-code-pro',monospace;font-size:12px;} .latex-cell{white-space:pre-wrap;} <!-- User CSS --> .text-cell {font-size: 15px;}.code-cell {font-size: 12px;}.markdown-cell {font-size: 15px;}.latex-cell {font-size: 15px;}
Rust: func as function arg
在很久很久以前, 其实特么也不是很久, rust以前能直接用closure作为参数类型传参,结果现在在rustc 1.5下试了一下, 根本不行啊:
fn call_fun(f: |i32| -> i32) { // error: expected type, found |
println!("call func got res: {}", f(32));
}
fn call_function(function: fn(u8) -> bool) -> bool { // fix error of the above
function(8)
}
fn main() {
let max = 5;
let closure = move |arg: u8| { arg < max };
println!("{}", call_function(closure));
}
// 编译会产生下面的错误
// test.rs:18:34: 18:41 error: mismatched types:
// expected fn(u8) -> bool
,
// found [closure@tt.rs:17:19: 17:47 max:_]
// (expected fn pointer,
// found closure) [E0308]
// tt.rs:18 println!("{}", call_function(closure));
// ^~~~~~~
只能说以前看到的rust语法已经在后续的发展中修改了。 那么我们现在变成这样的做法了:fn call_function(function: fn(u8) -> bool) -> bool {
function(8)
}
fn my_local_function(arg: u8) -> bool{
let max = 5;
arg < max
}
fn main() {
println!("{}", call_function(my_local_function));
}
它的泛型用法:fn call_function(function: fn(u8) -> bool) -> bool {
function(8)
}
fn my_local_function(arg: u8) -> bool{
let max = 5;
arg < max
}
fn main() {
println!("{}", call_function(my_local_function));
fn double(x: i32) -> i32 {x + x}; // Ok
println!("Res is {}", call_twice(10i32, double)); // OK
let closure = |x: i32| -> i32 {x + x};
println!("Closure res is {}", call_twice(10i32, closure));
}
fn call_twice<A, F>(val: A, f: F) -> A where F: Fn(A)->A {
let tmp = f(val);
f(tmp)
}
总的说, 就是函数声明语义, 已经不能中参数类型中, 直接用匿名函数来表示参数的类型了; 这里还有一个方式, 就是用Trait的方式, 也可以做到func as arg type:trait FunctionCaller {
fn call_function(&self, function: &Fn(u8) -> bool) -> bool;
}
struct MyFunctionCaller {
data: u8,
}
impl FunctionCaller for MyFunctionCaller {
fn call_function(&self, function: &Fn(u8) -> bool) -> bool {
function(self.data)
}
}
fn main() {
let my_function_caller = &MyFunctionCaller{data: 8};
println!("{}", invoke(my_function_caller));
}
fn invoke(function_caller: &FunctionCaller) -> bool {
let max = 5;
let closure = &move |arg: u8| { arg < max };
function_caller.call_function(closure)
}