【问题标题】:Lisp is for List Processing. Is there a language for Tree Processing?Lisp 用于列表处理。是否有用于树处理的语言?
【发布时间】:2011-04-13 22:55:53
【问题描述】:

Lisp 的名称来源于 LISt P处理。链表是 Lisp 语言的主要数据结构,而 Lisp 源代码本身就是由列表组成的。因此,Lisp 程序可以将源代码作为数据结构进行操作(这称为同音性)。

但是,根据定义,列表是一个顺序结构。这鼓励我们使用顺序语言习语(一次处理一件事并累积结果的算法)来解决问题。例如,在使用 cons 单元格实现单链表的 Lisp 中,car 操作返回列表的第一个元素,而 cdr em> 返回列表的其余部分。我的愿景是一种用于并行执行的函数式语言,它将问题分成大致相等的子问题,递归地解决它们,然后组合子解决方案。

几乎所有编程语言的代码都已经被解析成树;有没有像 Lisp 这样的同音语言,但以树为主要数据结构?顺便说一句,我将其称为 Treep,用于 TREE P 处理。

更新:Guy Steele 2009 年关于并行算法和数据结构的有趣演示文稿 (PDF),Organizing Functional Code for Parallel Execution: or, foldl and foldr Considered Slightly Harmful

【问题讨论】:

  • 您是否只是用一个新的用户名向该网站发送垃圾邮件以供一次性使用?
  • 请注意我如何跟踪你在这个主题上的进展——我对这个像树同形编程语言和树上的计算非常生气

标签: list tree lisp language-design parallel-processing


【解决方案1】:

Lisp 列表是树,而 Lisp 代码也是一棵树,就像任何其他代码一样。

(+ (* 1 3) (* 4 6))

是一棵树:

     +
    / \
   /   \
   *   *
  / \ / \
  1 3 4 6

而且它不仅仅是二叉树。

(+ 1 2 3)

   +
  /|\
 / | \
1  2  3

所以,也许 Lisp 既是你的答案,也是你的问题。

【讨论】:

  • ...如果你反其道而行之,你可以说 Lisp 列表确实是 cons 单元格;但是,我的问题更多是关于允许对树进行更多惯用(并行)处理的语言的设计。例如,(+ (* 1 3) (* 4 6)) 可以并行评估(* 1 3)(* 4 6),而语言级构造将提供更有效的并行性。
  • @Treep:并行执行代码与并行处理树数据是不同的。
  • 您的回答具有误导性。表达式(+ (* 1 3) (* 4 6)) 不会形成您说明的平衡二叉树。它形成了一个非常不平衡的二叉树,其中所有数据都在叶子节点中。此外,它总是形成二叉树,因为 cons 单元只有两部分:car 和 cdr。
【解决方案2】:

我认为这种变化不会非常深刻。 Lisp 让列表成为其他列表的成员当然没有任何问题,因此它可以轻松地表示树和树上的算法。

相反,每个列表都可以被视为具有特定形状的树(以各种方式)。

【讨论】:

  • 使用树作为其基本数据结构的语言的深度是有效的并行性。当然,一旦将列表放入列表中,您就会得到一棵树。你也可以反过来说 Lisp 真的是关于“cons cell processing”...
  • 我同意……但我想“Consp”或“Pairp”这个名字不太好。
  • 顺便说一句:看看 PostScript。它是基于堆栈的(如 Forth),并以字典作为基本数据结构。
  • 另一种有趣的语言是Fortress,它的“隐式并行性”...
【解决方案3】:

我想说 Lisp 语言的主要数据结构是 cons 单元格。您可以使用 cons 单元轻松构建的东西之一是链表,但这绝不是唯一的数据结构。

cons 单元格是一对数据项,但没有任何内容表明值必须在左侧单元格中,而指针必须在右侧单元格中(如在链表中)。如果您允许两个单元格本身包含值或指针,则很容易构建二元(或更多工作,n-ary)树结构。在这些结构的基础上,您可以构建字典或 B 树或您可能想到的任何其他数据结构。

【讨论】:

  • 确实,正如我在 reinierpost 的评论中所说,Lisp 真的是关于“cons cell processing”。
【解决方案4】:

OP 似乎对处理树的语言感兴趣并且有一些并行性支持。

我们的DMS Software Reengineering Toolkit 是一个通用的程序分析和转换引擎。它将编程语言源文本解析为树(OP 的第一个兴趣),能够分析和处理这些树,并从这些树中重新生成源文本。 DMS 由描述正在处理的语言的显式语法驱动,并且它有许多可用的生产质量语言定义。

DMS 的树处理机制在两个不同级别提供并行支持,一个由 DMS 的底层并行编程语言 PARLANSE 直接支持,该语言受 LISP 启发,但几乎没有那么动态。

PARLANSE 提供了称为“谷物”的并行活动的“团队”(就像在沙滩上的沙子中,想法是有很多谷物)。团队可以通过(经典)分叉新颗粒并将它们添加到(动态)团队来动态构建;这很有用,但速度不是特别快。团队可能是静态结构的,包括“将这个固定大小的颗粒集分叉为纯并行”:

(|| a b c)

和“创建一组执行顺序由指定的部分顺序控制的颗粒”(!| ...)。你直接在fork调用中写偏序:

(!| step1 a
    step2 b
    step3 (>> step1 step2) c
    step4 (>> step2) d )

表示动作 c 发生在动作 ab 之后(后来 >> )强>完整。静态形成的团队由 PARLANSE 编译器预编译成非常有效的结构,因为可以非常快速地启动和杀死颗粒,从而允许非常小的颗粒大小(几百条指令)。标准并行库的开销比这要高得多。

处理树的基本方法非常传统:有一个 PARLANSE 库,用于检查树节点、在树上上下移动、创建新节点并将它们拼接到位。递归过程通常用于访问/更新树。

这里的关键观察是,访问某些子集的树访问可以按顺序编码,也可以轻松编码为静态并行团队。因此,手动编写并行树访问代码非常容易,但代价是为每种树节点类型编写大量特殊情况到并行分叉。 OP似乎对“分而治之”感兴趣。 (您当然可以枚举节点的子节点,并使用动态团队为每个子节点分叉,但这并不那么快)。这是用于在 DMS 中处理树的第一级并行性。

第二级并行性来自 DMS 提供的 DSL,该 DSL 实现了属性语法 (AG)。

AG 是用一组计算来装饰 BNF 的函数式语言。可以用 DMS 中的 AG 编写一个简单的计算器:

   sum = sum + product;
        <<Calculator>>:  sum[0].result = sum[1].result + product.result;

这会通过组合第一个孩子 (sum[1]) 和第二个孩子 (product.result) 的结果属性来为根 (sum[0]) 计算一个属性“结果”。 所谓的综合属性将信息从叶子向上传播;继承的属性从父母那里传播信息。一般的属性文法和 DMS 的 AG 允许混合这些,因此信息可以以任意顺序在树上上下流动。

大多数 AG 都是纯功能性的,例如,没有副作用; DMS 允许出现使符号复杂化但在实践中非常有用的副作用。一个很好的例子是通过属性评估构建符号表。 current-scope 向下传递树,local-declaration 块创建新的 current scope 并将它们向下传递,并且各个声明将符号表数据存储到从 parent 接收到的符号表条目中。

DMS 的 AG 编译器分析属性计算,确定信息如何在整个树中流动,然后生成并行 PARLANSE 程序来实现每个树节点类型的信息流。它可以对每个 AG 规则进行数据流分析,以确定信息流以及先发生、后发生和最后发生的事情。对于我们上面的简单求和规则,应该清楚的是,必须先计算子节点的属性,然后才能计算根的属性。事实证明,PARLANSE 的偏序构造是对这些信息进行编码的完美方式,甚至可以很好地处理我们添加到 AG 的副作用。

结果是 DMS 将 AG 规范编译成高度并行的 PARLANSE 程序。我们的 C++ 前端名称/类型解析器被实现为大约 150K 行 DMS AG(是的,描述如何使用 C++ 类型信息需要这么多),它编译 到大约 700K SLOC 的并行 PARLANSE 代码。而且它工作(并在 x86 多核机器上并行运行),无需任何思考或调试,而且它似乎可以很好地扩展。

【讨论】:

    【解决方案5】:

    同音树处理语言的典型示例是 XSLT。但您可能不想在其中写(或读)任何实质性内容。

    【讨论】:

      【解决方案6】:

      我认为闭包有树而不是列表,并在您为并发目的编写时使用它们。

      【讨论】:

        【解决方案7】:

        我也在寻找处理同音语言的树(或更好的图),仍然没有任何要点。让我们列出一些语言所需的元素,也许我们会发现一些变体:

        • 同调性:基于树(或更好的图)解释
        • 语言核心中的属性语法支持
        • 结构模式匹配统一
        • 全套典型图算法
        • 具有丰富可视化支持的类似于 SmallTalk 的交互环境
        • 语言核心中用于任何文本数据加载的词法分析器/解析器引擎
        • 嵌入式(基于 LLVM)编译器框架,用于低级代码生成和针对密集计算任务的优化

        【讨论】:

          【解决方案8】:

          “Lisp”只是一个名字,一个古老的名字。它没有描述在 Lisp 中所做的一切。就像 Fortran 不仅仅是一个公式翻译器一样,Cobol 中的所有内容也不是“面向业务的”。

          “Lisp”中提到的处理实际上是树形处理,因为它是嵌套列表的处理。它是嵌套列表处理。只是“嵌套”没有包含在名称中。

          ANSI Common Lisp 标准实际上是词汇表中的normatively defines "tree" and "tree structure"

          Lisp 列表是树结构中的约定:右倾递归(通过 cons 单元的cdr 槽)表示一个列表。它有一个符号:即树符号结构((((a . b) . c) . d) . nil)可以根据符号规则缩短为(a b c d),写为(anything . nil)的cons单元也可以打印为(anything),以及规则那(foo . (bar))可以写成(foo bar)

          强调“列表处理”一词可能不是因为排除了树,而是因为树中的大部分生长是在被理解为水平方向的:也就是说,嵌套列表的处理。

          在典型的 Lisp 程序中处理的大多数基于列表的数据结构,即使是嵌套的,在 cdr 维度中也比在 car 维度中更深。

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 2010-11-25
            • 2016-11-03
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2013-01-21
            相关资源
            最近更新 更多