Как мне отформатировать дерево, чтобы оно работало с молнией Clojure?
Я создаю деревья s-выражений для проблемы генетического программирования, и мне нужно изменить части деревьев в процессе эволюции. Я столкнулся с функцией молнии Clojure, которая, кажется, должна быть идеальной, но я не могу понять, как ее использовать.
Например, скажем, я создаю молнию с
(def zipped (zip/seq-zip `(+ (- 1 2) 3)))
Я понимаю, что это представляет дерево с + в корне, которое выглядит так:
+
- 3
1 2
Моя молния, однако, не согласна с этим: если я попрошу первый узел с (-> zipped zip/down zip/node)
это дает мне +
(что правильно) но это (-> zipped zip/down zip/down)
не берет меня -
вместо этого он возвращает nil
, В самом деле, (-> zipped zip/down zip/rights)
дает остальную часть дерева как братьев и сестер справа от корня, что подсказывает мне, что у меня вообще нет дерева:
user> (-> zipped zip/down zip/rights)
((clojure.core/- 1 2) 3)
Я почти уверен, что правильно представляю свои деревья, потому что когда я их выполняю, я получаю правильный ответ. Молния ожидает другого макета?
2 ответа
Проблема в том, что здесь есть две разные идеи дерева. Ваше дерево представляет собой график того, как значения просачиваются через оценку, но LISP думает о списках списков и использует префиксную нотацию:
'(+ (- 1 2) 3) также (list + (list - 1 2) 3), что на самом деле это дерево:
+ . 3
- 1 2
(-> zipped down node)
дает вам первый элемент, +, атом.(-> zipped down down)
таким образом, вы получаете ноль, потому что первый элемент, +, является атомом.(-> zipped down right down node)
дает вам знак минус, который вы хотите, потому что это первый элемент второго элемента выражения.
Дерево не так, как вы его изобразили. Корневой узел имеет 3 детей: +
, (- 1 2)
, а также 3
, Когда вы делаете down
от корневого узла, по умолчанию это самый левый дочерний элемент, поэтому вы видите +
,
Чтобы добраться до -
вам нужно позвонить:
user => (-> zip zip/down zip/right zip/down zip/node) clojure.core/-