参数化编程——面向对象及超越的等式方法

2021-08-06 05:41:27

很久以前,我有一个有趣但有缺陷的想法。这个想法是(可选)用定义或引用传统复合结构组件的方程替换表达式构造的实例。定义或使用的特殊变量我称为“代词”,但现在我更喜欢“参数”。我修复了这个缺陷……这样做发现了一个很有前途的新方程编程范式。新范式允许对 OO 之类的事物采用纯粹的等式方法,特别是允许对 Lucid 进行简单自然的 OO 扩展。但是参数化编程 (PP) 似乎超越了 OO。它可以与 Haskell 等其他声明性语言结合使用。首先,我们需要避免使用 where 子句,这会使问题复杂化。过去我在 Warwick 的时候,有一群热心的先驱系统语言 BCPL 的信徒。 BCPL 是怪物(和未实现的)语言 CPL 的后代,也是 C 本身的祖先(通过 B)。无论如何,BCPL 有许多不错的特性,包括 VALOF 结构。 VALOF 就像一个开始-结束块,只是你使用命令 RESULTIS 来返回一个值。例如 VALOF $( DISC := B*B - 4*A*C IF DISC < 0 RESULTIS ERR RESULTIS (-B + SQRT(DISC))/(2*A)$) BCPL 的 VALOF 很容易适应等式方法.我们简单地用一组(无序的)方程替换命令,其中包含一个用于特殊变量结果的方程:

valof 盘 = b*b - 4*a*c; root = (-b + sqrt(disc))/(2*a); result = if disc<0 then ERR else root fi;end(注意 Lucid 版本,其中变量按需求值,不会尝试取负平方根。方程不是赋值语句。)在某一时刻我想到了一个有趣的想法,为什么没有输出参数?那返回结果?例如,这将允许在没有嵌套结构的情况下等效于 if-then-else-fi:变量 result 的特殊之处在于它不能重命名——与 disc 和 root 不同。我称它为“参数”,就像 pyLucid 用于格式化输出的参数列、行和 numformat 一样。这就是我的想法。我展示了使用参数可以形式化其他“结构”,例如多个退出循环。就是这样。不是一个惊天动地的想法。一个有几个问题。例如,它将程序员可能想要使用的诸如“选择”或“测试”之类的标识符联系起来。所以我放弃了它,几十年。前几天我决定写一篇关于参数的博客文章,当我思考绑定标识符的问题时,我想到了一个简单的解决方案:在参数名称前加上相关结构的名称。因此例如

valof if.test = n < 1;如果.true = 1; if.false = n*(n-1); result = if.resultend 那么你会看看那个。熟悉的?是的,它看起来像是调用了一个名为“if”的 OO 对象。定义“输入”参数(如“if.test”)的等式是设置属性(在本例中为 test),表达式 if.result 正在调用方法结果。然而,除了调用一个隐式方程,即没有存储分配和没有参数初始化,没有任何与传统命令式 OO 中创建对象相关的开销。最多在编译时复制一个字符串,即隐式方程。显然 if 对象是内置的。我们可能想要的其他对象呢?假设我们想解一个二次方程。我们可以想象调用一个对象 quad valof import quad;四.a = 3;四.b = 9; quad.c = -8; result = [%quad.root1,quad.root2%];end 我把它放在那里是因为我认为 quad 不会是内置的,我们必须调用一些东西来引入所需的隐式方程。这些方程是什么?就像是

disc = b*b - 4*a*c;droot = sqrt(disc);root1 = (-b + droot)/2/aroot2 = (-b - droot)/2/a 除非这里没有足够的信息。我们需要指定 a、b 和 c 是输入参数(基本上是属性),而 root1 和 root2(但不是 disc 和 droot)是输出参数(基本上是方法)。此外,正如我们将发现的,这些包不能总是被认为是 OO 对象。所以我决定将这些方程组称为“方案”,如方案 quad disc = $b*$b - 4*$a*$c; droot = sqrt(光盘); $root1 = (-$b + droot)/2/$a $root2 = (-$b - droot)/2/$aend $root1 和 $root2 有定义的事实意味着 root1 和 root2 是输出参数。到现在为止还挺好。然后我想到了:输入和输出参数都可以是函数:valof importintegrally.a = 1;积分.b = 2;积分.f(x) = 1/x; log2 = integration.area;end 这是一个很大的惊喜! pyLucid(例如)是严格的一阶,您不能定义将另一个函数作为参数的函数。我们在原则上想出了如何做到这一点,但存在语法和实现上的复杂性。

现在我们几乎免费获得它,只需在编译时复制字符串即可完成所有工作。我们也可以将函数作为输出参数返回,就像在这个以数值方式计算导数的方案中一样:在这一点上,我想到这个想法与 Lucid 没有本质的关系,它适用于任何等式语言。此外,作为一种等式语言,Lucid 具有无关的包袱,例如是一阶的,需要进行维度分析才能进行推导。所以我决定指定并实现一种超级简单的方程语言作为演示参数的平台。因此诞生了 PYFL,基于 PYthon 的函数式语言。接下来的事情具有讽刺意味,理由有两个。首先,PYFL 并不是很简单。我发现使用有趣的特性来扩展 PYFL 相对容易,比如 VBO 或(自相矛盾的)函数 while 循环。同时,我对参数分心,直到很晚才实现它们。当我真正实现它们时,我发现它们并不像看起来那么简单。你不能只在最顶层有 if.result 的(比如说)方程。它必须包含在导入 if 方案的每个 valof 子句中。所以参数并不是完全的雾器,但它们还没有真正被尝试过。蒸汽还没有凝结。