我想知道为什么我们需要像“%identity”这样的函数,这与让a = a相同。是否会通过使用它来提高性能?
我在我的程序中引入幻像输入,调用身份函数很多次来转换类型,好奇如果“%identity”可以减少一些开销。
答案 0 :(得分:11)
%identity
函数是实现的一部分,而不是OCaml语言的一部分。它告诉编译器(实质上)没有任何事情可以将函数的参数更改为其返回值。换句话说,它告诉编译器继续使用相同的值,但改变它的类型的想法。如果使用不当,它基本上会使OCaml类型系统的所有出色安全保证无效。当然,它也不能保证在该语言的任何其他实现中工作(包括INRIA编译器的未来版本)。
OCaml编译器的内联功能应该已经保证不会为身份函数生成代码。所以我建议你继续使用它们。
<强>更新强>
在评论中回答一个不相关的问题....假设你有函数组合和身份函数:
let (<<) f g x = f (g x)
let id x = x
然后,这里是添加列表元素,乘以列表元素以及组合列表中所有函数的函数:
# let sum l = List.fold_right (+) l 0;;
val sum : int list -> int = <fun>
# let product l = List.fold_right ( * ) l 1;;
val product : int list -> int = <fun>
# let composition l = List.fold_right (<<) l id;;
val composition : ('a -> 'a) list -> 'a -> 'a = <fun>
示例:
# sum [2; 3; 5; 7];;
- : int = 17
# product [2; 4; 17];;
- : int = 136
# let mx = composition [(+) 1; ( * ) 10];;
val mx : int -> int = <fun>
# mx 2;;
- : int = 21
重点是0是加法的标识,1是乘法,1是id
的函数组合。 id
始终有用,就像0和1一样。
答案 1 :(得分:2)
使用%identity
作为外来原语可以并且将减少每次应用时评估(fun x -> x)
闭包所产生的开销。
OCaml编译器特殊情况%
原语:bytecomp/translcore.ml
将每个原语与一个特殊的内置AST节点相关联(在%identity
的情况下,它被映射到{Pidentity
1}});编译器在节点上匹配并简化它所应用的表达式。对于本机编译器,相关的行是:
asmcomp/closure.ml
第197行和ss:简化%identity
应用于参数本身的常量参数:
begin match p with
Pidentity -> make_const_int x
| Pnegint -> make_const_int (-x)
asmcomp/cmmgen.ml
第1047行和ss:简化%identity
作为直接评估参数的应用程序的LHS:
match p with
(* Generic operations *)
Pidentity ->
transl arg
字节码编译器对基元具有类似的简化规则。