最近在工作中,我一直在将Makefile翻译成另一种构建系统。我发现有些地方的Make代码使用了函数式map、filter和foreach结构,这让我很惊讶,因为我认为构建脚本应该尽可能声明式。
无论如何,这让我想到一个问题:Makefile语言(以最新的GNU make为例)是否是图灵完备的?
最近在工作中,我一直在将Makefile翻译成另一种构建系统。我发现有些地方的Make代码使用了函数式map、filter和foreach结构,这让我很惊讶,因为我认为构建脚本应该尽可能声明式。
无论如何,这让我想到一个问题:Makefile语言(以最新的GNU make为例)是否是图灵完备的?
是的,参见这里。一旦你有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,)
这个程序输出平方数、斐波那契数和阶乘。似乎有一个16位的数字大小限制。遗憾。
Actually make detects the infinite loop and reports an error.
(顺便说一句,我不认为在实践中允许它们有什么用处。)
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.