Лисп для Обработки Списка. Есть ли язык для обработки дерева? - PullRequest
5 голосов
/ 18 сентября 2010

Название для Lisp происходит от LIS t P обработки.Связанные списки являются основной структурой данных языков Lisp, а исходный код Lisp состоит из списков.В результате программы на Лиспе могут манипулировать исходным кодом как структурой данных (это называется гомоконичностью).

Однако список по определению является последовательной конструкцией.Это побуждает нас решать проблемы, используя последовательные языковые идиомы (алгоритмы, которые обрабатывают одну вещь за раз и накапливают результаты).Например, в Лиспе, где для реализации односвязных списков используются cons ячеек, операция car возвращает первый элемент списка, а cdr возвращаетостальная часть списка.Мое видение - это функциональный язык для параллельного выполнения, который разбивает проблемы на примерно равные подзадачи, рекурсивно решает их и объединяет подрешения.

Практически каждый код языка программирования уже разбит на деревья;существует ли гомоиконичный язык, такой как Лисп, но с деревьями в качестве основной структуры данных?Кстати, я бы назвал это Treep, для TREE P Обработка.

Обновление: Интересная презентация (PDF) от 2009 года от ГаяСтил на параллельных алгоритмах и структурах данных, Организация функционального кода для параллельного выполнения: или, foldl и foldr Считается слегка вредным .

Ответы [ 8 ]

6 голосов
/ 18 сентября 2010

Списки Lisp являются деревьями, а код Lisp - это дерево, как и любой другой код.

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

- это дерево:

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

И это не просто двоичные деревья.

(+ 1 2 3)

   +
  /|\
 / | \
1  2  3

Так что, возможно, Лисп - это ваш ответ, а также ваш вопрос.

6 голосов
/ 18 сентября 2010

Я не вижу, чтобы это изменение было очень глубоким. У Lisp определенно нет проблем с тем, чтобы списки были членами других списков, поэтому он может легко представлять деревья и алгоритмы на деревьях.

И наоборот, каждый список можно рассматривать как дерево определенной формы (по-разному).

1 голос
/ 30 сентября 2010

OP, кажется, интересуется языками, которые обрабатывают деревья и имеют некоторую поддержку параллелизма.

Наш набор инструментов для реинжиниринга программного обеспечения DMS - это анализ программ общего назначения идвигатель трансформации.Он анализирует исходный текст программирования на деревьях (первый интерес OP), позволяет анализировать и обрабатывать эти деревья, а также восстанавливать исходный текст из этих деревьев.В основе DMS лежат явные грамматики, описывающие обрабатываемый язык, и для него доступно множество определений языка производственного качества.

Механизм обработки дерева DMS обеспечивает поддержку параллелизма на двух разных уровнях, один из которых поддерживается напрямую.базовым языком параллельного программирования DMS, PARLANSE , который вдохновлен LISP, но не настолько динамичен.

PARLANSE предусматривает «команды» параллельных действий, называемых «зернами» (как в песке на пляже, идея заключается в том, что зерна много).Команды могут быть структурированы динамически, путем (классически) разветвления новых зерен и добавления их в (динамическую) команду;это полезно, но не очень быстро.Команды могут быть структурированы статически, включая «разделить этот набор зерен фиксированного размера как чистую параллель»:

(|| a b c)

и «создать набор зерен, порядок выполнения которых контролируется указанным частичным порядком» (! | ...) .Частичный порядок вы записываете непосредственно в вызове fork:

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

, который кодирует тот факт, что действие c происходит после (позднее >> во времени)) действий a и b завершено.Статически сформированные команды прекомпилируются компилятором PARLANSE в довольно эффективные структуры, в которых зерна могут быть запущены и уничтожены очень быстро, что позволяет довольно маленький размер зерна (несколько сотен инструкций).У стандартных библиотек параллелизма намного больше издержек, чем у этого.

Основной метод обработки деревьев довольно обычен: есть библиотека PARLANSE для проверки узлов дерева, обхода дерева вверх и вниз, создания новых узлов и их объединения.на месте.Рекурсивные процедуры часто используются для посещения / обновления дерева.

Ключевое наблюдение здесь заключается в том, что посещение дерева, которое посещает некоторый набор детей, может быть закодировано последовательно или легко закодировано как статическая параллельная команда.Так что довольно легко вручную кодировать параллельные посещения дерева, за счет написания множества особых случаев для параллельной ветвления для каждого типа узла дерева.Есть «разделяй и властвуй», который кажется интересным для ОП.(Конечно, вы можете перечислить childern узлов и использовать динамическую команду, чтобы разбить зерна для каждого ребенка, но это не так быстро).Это первый уровень параллелизма, используемый для обработки деревьев в DMS.

Второй уровень параллелизма осуществляется через DSL, поставляемый DMS, который реализует грамматику атрибутов (AG).

AG - это функциональные языки, которые украшают BNF набором вычислений.Можно написать простой калькулятор с AG в DMS:

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

Это приводит к вычислению атрибута «result» для корня (sum [0]) путем объединения атрибута result из первого дочернего элемента(сумма [1]) и второй ребенок (product.result).Так называемые синтезированные атрибуты распространяют информацию вверх по дереву из листьев;Унаследованные атрибуты распространяют информацию от родителей.Грамматики атрибутов вообще и AG DMS позволяют смешивать их, поэтому информация может перемещаться вверх и вниз по дереву в произвольном порядке.

Большинство АГ являются чисто функциональными, например, без побочных эффектов;DMS допускает побочные эффекты, которые усложняют обозначения, но довольно полезны на практике.Хорошим примером является построение таблиц символов путем оценки атрибута;current-scope передается по дереву, блоки локальных объявлений создают новые текущие области и передают их, а отдельные объявления сохраняют данные таблицы символов в записи таблицы символов, полученной от родителя.

Компилятор DMS AG анализирует вычисления атрибутов, определяет, как информация перемещается по всему дереву, а затем генерирует параллельную программу PARLANSE для реализации потока информации по типу узла дерева.Он может выполнить анализ потока данных по каждому правилу AG, чтобы определить поток информации и то, что должно произойти сначала по сравнению с последним по сравнению с последним.Для нашего простого правила суммирования, приведенного выше, должно быть ясно, что атрибуты потомков должны быть вычислены до того, как атрибут для корня может быть вычислен.Оказывается, что создание частичного порядка в PARLANSE является идеальным способом кодирования этой информации и даже прекрасно справляется с побочными эффектами, которые мы добавили в AG.

В результате DMS компилирует спецификацию AG в высокопараллельную PARLANSE.программа.Наш распознаватель имен / типов внешнего интерфейса C ++ реализован в виде примерно 150 тыс. Строк DMS AG (да, для описания того, как используется информация о типах C ++, требуется столько времени), который компилируется в приблизительно 700 тыс. SLOC параллельного кода PARLANSE.И он работает (и работает параллельно на многоядерных машинах x86) без какой-либо мысли или отладки, и, похоже, он хорошо масштабируется.

1 голос
/ 18 сентября 2010

Я бы сказал, что основной структурой данных языков Lisp является cons-ячейка . Одна из вещей, которую вы можете легко создать с помощью cons-ячеек, - это связанный список, но это ни в коем случае не единственная структура данных.

Минус ячейка - это пара элементов данных, но нет ничего, что говорит о том, что значение должно быть в левой ячейке, а указатель - в правой (как в связанном списке). Если вы позволите обеим ячейкам содержать либо значения, либо сами указатели, легко построить бинарные (или с немного большим количеством работы, n-арные) древовидные структуры. Основываясь на этих структурах, можно создавать словари, B-деревья или любую другую структуру данных, о которой вы только можете подумать.

0 голосов
/ 03 августа 2017

«Лисп» - это только имя и древний. Он не описывает все, что делается в Лиспе. Точно так же, как Фортран не был исключительно переводчиком формул, и не все в Коболе «ориентировано на бизнес».

Обработка, упомянутая в "Лиспе" , на самом деле обработка дерева, потому что это обработка вложенных списков. Это вложенная обработка списка. Просто «вложенный» не был включен в название.

Стандарт ANSI Common Lisp фактически нормативно определяет "дерево" и "древовидную структуру" в глоссарии.

Списки Lisp являются соглашением в древовидной структуре: правосторонняя рекурсия (через слот cdr в ячейке cons) представляет список. здесь есть обозначение: а именно, структура древовидного обозначения ((((a . b) . c) . d) . nil) может быть сокращена до (a b c d) в соответствии с правилом обозначения, согласно которому ячейка cons, записанная как (anything . nil), может быть напечатана как (anything), а правило что (foo . (bar)) можно записать (foo bar).

Термин «обработка списка», вероятно, подчеркивался не потому, что деревья исключены, а потому, что большая часть роста деревьев идет в направлении, понимаемом как горизонтальное: то есть обработка вложенных списков .

Большинство структур данных на основе списка, обрабатываемых в типичных программах на Лиспе, даже если они вложенные, гораздо глубже в измерении cdr, чем в измерении car.

0 голосов
/ 06 апреля 2017

Я также ищу дерево (или лучший график), обрабатывающий гомоиконический язык, все еще не имеет никаких точек зрения. Давайте составим список обязательных элементов языка, и, возможно, мы найдем какой-то вариант:

  • гомойконичность: на основе древовидной (или более точной диаграммы) интерпретации
  • поддержка грамматики атрибута в языковом ядре
  • структурное сопоставление с унификацией
  • полный набор типовых графовых алгоритмов
  • SmallTalk-подобная интерактивная среда с богатой поддержкой визуализации
  • движок лексера / анализатора в языковом ядре для любой загрузки текстовых данных
  • встроенная (основанная на LLVM) структура компилятора для низкоуровневой генерации кода и оптомизации для интенсивных вычислительных задач
0 голосов
/ 20 апреля 2012

Я думаю, что у замыкания есть деревья вместо списков, и они используются так, как вы написали для целей параллелизма.

0 голосов
/ 18 сентября 2010

Каноническим примером языка обработки гомо-звукового дерева является XSLT. Но вы, вероятно, не хотите писать (или читать) что-нибудь существенное в этом.

...