我知道:
- 函数内联就是用函数定义代替函数调用。
- 部分评估是在编译时评估程序的已知(静态)部分。
在 C 等命令式语言中,两者之间存在区别,其中运算符与函数不同。但是,在像 Haskell 这样的函数式语言(其中运算符也是函数)中,两者之间有什么区别吗?
两者之间的唯一区别是函数内联可以在程序的选择性部分上执行,而部分评估是在整个程序上执行的(即。∃
vs ∀
)?
两种优化技术之间的语义差异是什么?
之间存在差异
- 对编译器(甚至预处理器)已知的一组给定运算符和函数求常量表达式,这发生在编译时间。例如。编译器编译
print(2*2)
as print(4)
。正如您似乎暗示的那样,这绝不需要限于运算符表达式(例如print(sqrt(2.0)
)
- 部分评估,这是一个更广泛的概念。编译器可以意识到
print(myfunc(2))
可以转化为print(c)
where c
是调用的结果myfunc(2)
。然后它可以(在“专业化时间") call myfunc(2)
确定c
。当然,如果myfunc
有副作用,例如擦除自己的硬盘而不是程序用户的硬盘。因此,编译器需要某种注释或属性来知道何时允许/需要这种情况(例如 C++11 的常量表达式 http://www.cprogramming.com/c++11/c++11-compile-time-processing-with-constexpr.html)
内联是一个不相关的概念。内联函数调用意味着用被调用函数的主体替换调用。此机构不予评估。
在 C 等命令式语言中,两者之间存在区别,其中运算符与函数不同。但是,在像 Haskell 这样的函数式语言(其中运算符也是函数)中,两者之间有什么区别吗?
这种区别(运算符与函数)纯粹是语法上的,与内联和部分求值之间的差异无关:
函数调用和带有运算符的表达式都可以在 C 中内联和编译时求值。编译时求值仅限于一组固定运算符和函数上的表达式(主要是运算符,但这是历史意外)
这两个概念在 Haskell 中都是有意义且截然不同的。
- 内联:
ghc
has {-# INLINE f #-}
, where f
由于显而易见的原因,不能递归,
- 部分评估:这通常被概括为超级编译 https://stackoverflow.com/questions/9067545/what-is-supercompilation其中不仅基类型的表达式被转换,甚至函数也被转换,例如转变
map f (map g xs
) into map (f . g) xs
)。它也可以(但不需要)进行内联。哈斯克尔模板 https://www.haskell.org/haskellwiki/Template_Haskell是在编译时(显式)评估程序部分的另一种方法。
因此,您标题问题的答案是:内联和部分求值之间的差异与函数和运算符之间的差异无关,并且在函数语言中与在 C 中大致相同。部分求值在 C 中可能更困难因为副作用(参见上面擦除的硬盘)
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)