*1. Выбор термов, подвергающихся преобразованию на выходе из "линзированной" функции* On Thu, Nov 14, 2024 at 5:59 PM Александр Коновалов a.v.konovalov87_AT_mail.ru <[email protected]> wrote:
> Вопрос по семантике примерно такой: если мы в результатной части > линзированной функции написали (Ident e.Name), то это имеется ввиду > залинзированный терм из аргумента или совершенно новый независимый терм > (который разлинзировать не нужно)? Ведь та же функция Parse может > из цепочки термов порождать синтаксическое дерево, в котором буквально > присутствует узел (Ident e.Name) без координат, и приписывание координат > к нему будет ошибкой. > Если функция Parse добавит в дерево новый узел (Ident e.Name), то он при выходе из функции Parse не будет преобразован. Это, в принципе, логично: функция Parse взяла его с потолка, а не из входного потока токенов, и координат он не имеет. Чтобы с такими деревьями, у которых часть узлов имеет координаты, а часть -- не имеет, было удобнее работать, надо, наверное, переместить координаты в конец выражения, описывающего токен, а имя взять в скобки: (Ident t.Name t.Pos). *2. Соответствие термов в образцах и результатных выражениях "линзированной" функции* On Thu, Nov 14, 2024 at 5:59 PM Александр Коновалов a.v.konovalov87_AT_mail.ru <[email protected]> wrote: > И второй вопрос, который лучше проиллюстрировать примером: > > Parse { > … > Let (Ident e.Name) Assign e.Expr1 Let (Ident e.Name) Assign e.Expr2 > = ERROR (Ident e.Name) ': double definition'; > … > } > > Вхождение (Ident e.Name) соответствует первому вхождению в образец или > второму? > Для сопоставления слева направо логично будет взять первое вхождение, т.е. ваш пример будет работать не так, как хочется. Чтобы он стал работать правильно, его придётся переписать, заменив вхождения e.Name в образец на e.Name1 и e.Name2, и добавив условие, сравнивающее e.Name1 с e.Name2. *3. Ограничения, накладываемые на функцию-линзу* Должен быть ещё и третий вопрос: какие термы на выходе линзы будут иметь ссылки на оригинальные термы? А четвёртый вопрос должен уточнять, как именно термы на выходе линзы ставятся в соответствие с оригинальными термами? Ответ на первый вопрос -- все термы. Ответ на второй вопрос -- тривиально. Дело в том, что на функцию-линзу должно быть наложено следующее ограничение: результатные выражения в ней и во всех функциях, которые из неё вызываются, должны быть составлены только из фрагментов соответствующих этим результатным выражениям образцов. При этом фрагменты образцов в результатных выражениях линзы не могут повторяться и должны сохранять своё взаимное расположение. Другими словами: линза всегда возвращает поддерево того упорядоченного дерева, которое передаётся ей в качестве аргумента. Это приводит к тому, что все термы на выходе линзы имеют ссылки на оригинальные термы, и эти ссылки назначаются тривиальным образом. *4. Направления развития линз* On Thu, Nov 14, 2024 at 5:59 PM Александр Коновалов a.v.konovalov87_AT_mail.ru <[email protected]> wrote: > А как эту фичу предполагалось развивать? > 4.1. Основное, что мне хотелось бы от линз, -- это ослабление указанного в предыдущем пункте ограничения. Например, я хочу линзу, которое преобразует арифметическое выражение из инфиксной записи в префиксную. 4.2. Хотелось бы передавать линзам гиперпараметры, управляющие их работой. Как их передавать, в принципе, понятно. Вот так, например: <Purify SkipComments | Parse e.tokens>. Но не совсем понятно, как отделить гиперпараметры от обрабатываемого дерева в реализации линзы -- мешает накладываемое ограничение. 4.3. Хотелось бы уметь переходить к оригинальным версиям термов в функциях, вызываемых из "линзированной" функции. Как это сделать красиво, я не придумал. При этом всё, конечно, можно реализовать, если наплодить кучу нового синтаксиса, но расширять синтаксис совершенно не хочется, потому что это уменьшит соотношение "выразительность/сложность". Желательно ограничиться расширением синтаксиса вызова функции: <линза | функция аргументы>.
