【问题标题】:GNUmake: how to write a true lambdaGNU make:如何编写一个真正的 lambda
【发布时间】:2017-08-25 19:26:29
【问题描述】:

以下是我对 GNUmake 中 lambda 表达式的一般模拟的看法:

space := $(strip) $(strip)
comma := ,

# convert a space-separated list in $1 into a comma-separated list:
list2param = $(subst $(space),$(comma),$(strip $1))

# param $1 = quoted GUNmake expression
# param $2 = parameters to the expression as space-separated list
lambda = $(eval _lambda=$1)$(eval _lambda:=$$(call _lambda,$(call list2param,$2)))$(_lambda)

例子:

$(info $(call lambda,$$1 .. $$2 .. $$3,foo bar baz))

输出:

foo .. bar .. baz

但这并不令人满意,因为我必须在幕后使用变量“_lambda”,并且该机制并不像 lambda,因为评估没有与定义分开。是否有一种干净、直接的方法来实现 lambda?还是已经实现了一些我盲目的程序编程眼睛没有注意到的机制?

【问题讨论】:

  • 你的高级问题是什么?
  • @MaximEgorushkin 例如在表格排序中,我需要一个排序键,我决定将其作为代码传递:$(info Sorting table: $(call sort_tbl,$(call select_from_MEMORY,1 2,where_name_FBL),3,$$(call lpad,$$(call lstrip,$$1,0x),8,0)))$$(call lpad ... 将采用第 1 列的元素(十六进制数字),去掉 0x 前缀并用 0 填充它以创建可排序的键。

标签: lambda functional-programming gnu-make


【解决方案1】:

与任何原始替换语言一样,您可以通过引用来推迟评估。下面的示例看起来很糟糕,并且不允许您嵌套 lambda,但在其他方面有效:

define lambda
$(eval lambda-f=$1)lambda-f
endef

$(foreach n,1 2 3,$(call $(call lambda,$$(info $$(shell seq -s ' ' $$1))),$n))

通过修改如下语法可以(可以说)重新获得一些可读性:

define lambda
$(eval lambda-f=$(subst ^,$$,$1))lambda-f
endef

$(foreach n,1 2 3,$(call $(call lambda,^(info ^(shell seq -s ' ' ^1))),$n))

【讨论】:

  • 使用# Count a binary literal up by 1 (e.g. 010011 -> 010100) bincnt=$(if $1,$(if $(patsubst %1,,$1),$(patsubst %0,%1,$1),$(call bincnt,$(patsubst %1,%,$1))0),1) # Generate a different symbol at each call symgen = $(eval last_symgen:=sym$(call bincnt,$(subst sym,,$(last_symgen))))$(last_symgen) 这两个函数可以在每次调用时生成不同的 lambda 名称。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2013-06-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-10-25
  • 1970-01-01
  • 2011-12-24
相关资源
最近更新 更多