功能语言中的部分评估和函数内联之间有什么区别?

Aad*_*hah 14 optimization haskell functional-programming inlining compiler-optimization

我知道:

  1. 函数内联是用函数定义替换函数调用.
  2. 部分评估是在编译时评估程序的已知(静态)部分.

在命令式语言(如C)中,两者之间存在区别,其中运算符与函数不同.但是,在Haskell这样的函数式语言中,两者之间是否存在差异?运算符也是函数?

两者之间的唯一区别是功能内联可以在程序的选择部分上执行,而部分评估是在整个程序上执行的(即?vs ?)?

两种优化技术之间的语义差异是什么?

Han*_*Lub 6

两者之间有区别

  • 在编译器(或甚至预处理器)已知的给定运算符和函数集上计算常量表达式,这在编译时发生.例如,编译器编译print(2*2)print(4).这似乎并不局限于运算符表达式,因为您似乎暗示(例如print(sqrt(2.0))
  • 部分评估,这是一个更广泛的概念.编译器可能会意识到,print(myfunc(2))有可能转化为print(c)这里c是调用的结果myfunc(2).然后它可以(在" 专业化时间 ")呼叫myfunc(2)确定c.当然,如果myfunc有副作用,例如擦除自己的硬盘而不是程序用户,这将是非常错误的.因此编译器需要某种注释或属性来知道何时允许/期望(例如C++ 11的constexpr)

内联是一个不相关的概念.内联函数调用意味着用被调用函数的主体替换调用.这个机构没有评估.

在命令式语言(如C)中,两者之间存在区别,其中运算符与函数不同.但是,在Haskell这样的函数式语言中,两者之间是否存在差异?运算符也是函数?

这种独特性(运算符与函数)纯粹是语法的,与内联和部分评估之间的差异无关:

函数调用和带运算符的表达式都可以用C进行内联和编译时评估.编译时评估仅限于一组固定的运算符和函数(主要是运算符,但这是历史事故)上的表达式

这两个概念都有意义,并且在Haskell中是不同的.

  • 内联:由于显而易见的原因,ghc有无法递归的{-# INLINE f #-}地方f,
  • 部分评估:这通常推广到超级编译,其中不仅基本类型的表达式被转换,甚至函数,例如转换map f (map g xsmap (f . g) xs).它也可以(但不必)进行内联.模板Haskell是另一种在编译时(明确地)评估程序的一部分的方法.

因此,对于标题问题的答案是:内联评估和部分评估之间的区别与函数和运算符之间的差异无关,在函数式语言中与C语言的区别大致相同.在C语言中,部分评估可能更难因为副作用(参见上面擦过的硬盘)