身份函数。
参数:x 类型:'T(输入值)
返回值:相同的值
F#核心库版本支持:2.0、4.0、Portable
为什么会有一个返回其输入的函数?
身份函数。
参数:x 类型:'T(输入值)
返回值:相同的值
F#核心库版本支持:2.0、4.0、Portable
为什么会有一个返回其输入的函数?
let control = ...
let allGrandChildren = control.Children |> Seq.collect (fun c -> c.Children)
但是很多时候,序列的每个元素本身就是一个序列 - 例如,您可能有一个列表的列表:
let l = [ [1;2]; [3;4]; [5;6] ]
在这种情况下,您传递到Seq.collect
的参数函数只需要返回该参数:
let flattened = [ [1;2]; [3;4]; [5;6] ] |> Seq.collect (fun x -> x)
这个表达式fun x -> x
是一个函数,它只返回其参数,也被称为“恒等函数”。
let flattened = [ [1;2]; [3;4]; [5;6] ] |> Seq.collect id
在使用高阶函数(例如上面的Seq.collect
)时,这种用法经常出现,因此它应该在标准库中有一席之地。
另一个引人注目的例子是Seq.choose
- 这个函数会过滤Option
值的序列并同时解包它们。例如,下面是将所有字符串解析为数字并丢弃无法解析的字符串的方法:
let tryParse s = match System.Int32.TryParse s with | true, x -> Some x | _ -> None
let strings = [ "1"; "2"; "foo"; "42" ]
let numbers = strings |> Seq.choose tryParse // numbers = [1;2;42]
但是如果您已经有一个Option
值列表怎么办?恒等函数来帮忙!
let toNumbers optionNumbers =
optionNumbers |> Seq.choose id
Seq.collect id
。我的思路通常无法迈出下一步到 Seq.concat
,不过你的评论可能会增加下次这种情况发生的机会。无论如何,拥有灵活性是很好的。我有时希望 C# 中有一个 Id()
函数,并且有时会手动实现它,但类型推断的差异使其稍微不那么有用。 - phoog对于某些高阶函数(接受函数作为参数的函数),这是很有用的,因此您可以将id
作为参数传递,而不是编写lambda表达式(fun x -> x)
。
[[1;2]; [3]] |> List.collect id // [1; 2; 3]
List.concat
,这样会更易读 :-). - Tomas Petricek当处理选项时,它非常有用。
我编写了一个小的习惯用语JSON助手,将所有可选字段标识为Option,并在传递null字符串时抛出错误,如果不是“string option”类型,则会抛出错误。
现在有一个函数提供了一个盒装输出值,它可以是:
为了正确地包装该值,我使用
val |> if isOption then fnOptTransform else id
所以我正在应用高阶函数fnOptTransform,并通过调用id来避免编写单独的lambda表达式(我尽可能避免这样做)。发现它很有用。
id
是函数集合在组合下的恒等元素。在函数式编程语言中,您经常希望将函数作为对象进行操作、执行各种操作等。 - matt_t_gregg