makefiles图灵是否完整?

Jay*_*rod 46 makefile turing-complete

最近在工作中,我一直在从Makefile转换到另一种构建系统.我在一些地方看到了一些非常多毛的Make代码,使用了功能映射,过滤器和foreach结构.这让我感到惊讶,因为我认为构建脚本应尽可能具有声明性.

无论如何,这让我想到:是Makefile语言(说最新的GNU make具体)Turing完成了吗?

dei*_*nst 43

是的,看到这个.一旦你有了lambda,它就会从那里下山.

这是一个抄袭的斐波那契例子

这应该足以建立一个更普遍的基础(我必须重新开始工作,或者我会发挥更多.)

dec = $(patsubst .%,%,$1)

not = $(if $1,,.)

lteq = $(if $1,$(if $(findstring $1,$2),.,),.)
gteq = $(if $2,$(if $(findstring $2,$1),.,),.)
eq = $(and $(call lteq,$1,$2),$(call gteq,$1,$2))
lt = $(and $(call lteq,$1,$2),$(call not,$(call gteq,$1,$2)))

add = $1$2
sub = $(if $(call not,$2),$1,$(call sub,$(call dec,$1),$(call dec,$2)))
mul = $(if $(call not,$2),$2,$(call add,$1,$(call mul,$1,$(call dec,$2))))
fibo = $(if $(call lt,$1,..),$1,$(call add,$(call fibo,$(call dec,$1)),$(call fibo,$(call sub,$1,..))))
fact = $(if $(call lt,$1,..),.,$(call mul,$1,$(call fact,$(call dec,$1))))

numeral = $(words $(subst .,. ,$1))

go = $(or $(info $(call numeral,$(call mul,$1,$1)) $(call numeral,$(call fibo,$1)) $(call numeral,$(call fact,$1)) ),$(call go,.$1))

_ := $(call go,)
Run Code Online (Sandbox Code Playgroud)

这打印出正方形,斐波那契数和阶乘.数字大小似乎有16位限制.游民.

  • 太棒了.可怕的.非常可怕. (12认同)
  • 一旦你有了lambda,那么我想你可以创建一个Y-combinator来为你提供递归.如你所说,从那里开始都是下坡路. (3认同)
  • 我刚才意识到他的网站是.我同意.Oleg Kiselyov很棒.他60行代码中纯粹功能性的OO系统是纯粹的天才. (2认同)

rei*_*ost 9

现在换一个否定的答案:GNU make积极阻止一些机制来创建递归:

1)递归扩展变量

在"递归函数"意义上不是递归的:它们不能用它们自己来定义:

Actually make detects the infinite loop and reports an error.
Run Code Online (Sandbox Code Playgroud)

(顺便说一下,我没看到如何允许它们在实践中有用.)

2)规则链接

也不能递归,:

No single implicit rule can appear more than once in a chain. (...)
This constraint has the added benefit of preventing any infinite loop
in the search for an implicit rule chain.
Run Code Online (Sandbox Code Playgroud)

(在调试我的Makefile时,我失去了很多时间 - 除了使makefile难以维护的所有其他东西.)

PS为最近的项目我写了一个GNU make 3.82的补丁,它用一个新的-M选项消除了这个限制(见讨论).这对我来说可以.

  • 这很有趣,但是如果make总能在$(eval)之类的情况下检测到递归宏,我会感到非常惊讶. (3认同)