1

我正在尝试将以下方案代码转换为 Mathematica(版本 8,如果重要的话):

(define (((lift g) . fs) . args)
  (apply g
         (map (lambda (f) (apply f args))
              fs)))

然后,您可以执行以下操作:

(let ((add (lift +))
      (square (lift sqr)))
  ((add (square sin) (square cos)) 42))
; returns 1, since sin^2(42) + cos^2(42) = 1

该部分(add (square sin) (square cos))创建一个函数x -> sin^2(x) + cos^2(x)

无论如何,我尝试在 Mathematica 中对此进行编码,但我似乎无法走得太远。这是我想写的:

lift[g_] := Function[{fs__}, Function[{args__},
            g @@ Map[(# @@ args)&, fs]]]

我想要fs__并且args__被绑定到它们各自函数的所有参数的列表中。但随后 Mathematica 抱怨“参数规范”Function应该是“一个符号或符号列表”。我知道我可以使用()&样式匿名函数并使用##来获取所有参数,但问题是当我嵌套其中两个匿名函数时,我失去了从内部函数访问外部参数的能力。

如何编写具有可变参数(和命名参数)的匿名函数?还是我应该在 Mathematica 中以另一种方式解决这个问题?

4

2 回答 2

3

我不确定这个函数是否符合您的要求,但您可以SlotSequence使用捕获外部函数的 (##)With

lift[g_] := Function[
  With[{fs = ##},
   Function[
    With[{args = ##},
     g @@ Map[(#[args]) &, List[fs]]]]]]

然后:

lift[f][a, b][c, d]

-> f[a[c, d], b[c, d]]

或者,更具可读性:

lift[g_] := Function[
  With[{fs = g[##]},
   Through[fs[##]] &]]
于 2012-12-11T08:51:15.517 回答
2

nikie 给出了一个很好的答案。我希望这个补充它。

您可以使用 创建临时函数Module,它为您提供参数规范的全套模式选项。例如,使用 nikie 的简洁方法:

lift1[g_] := Module[{fn}, fn[a__] := Through[g[a][##]] &; fn]

lift1[f][a, b][c, d]
f[a[c, d], b[c, d]]

在这种特殊情况下,您还可以使用SubValues如下规则:

lift2[g_][h__] := Through[g[h][##]] &

lift2[f][a, b][c, d]
f[a[c, d], b[c, d]]

甚至根本没有Function

lift3[g_][h__][i__] := Through[ g[h][i] ]

lift3[f][a, b][c, d]
f[a[c, d], b[c, d]]
于 2012-12-12T01:24:00.543 回答