Рефал-5, Рефал Плюс и форматы

30 views
Skip to first unread message

Александр Коновалов a.v.konovalov87_AT_mail.ru

unread,
Dec 15, 2020, 4:07:39 PM12/15/20
to re...@botik.ru

Добрый вечер всем!

На сколько я знаю, когда-то были планы реализации front-end’а Рефала-5 в компиляторе Рефала Плюс. Т.е. предполагалось использовать компилятор Рефала Плюс для компиляции исходных текстов Рефала-5.

(Дальше пишу подробно, поскольку не все подписчики знакомы с рассматриваемой проблемой. Те, кто знакомы, могут сразу промотать письмо до конца.)

Но есть один нюанс. Рефал Плюс использует массивное представление данных с дорогой конкатенацией. А это значит, что традиционный способ передавать параметры в функцию, используя N−1 скобок для N e-параметров будет приводить к избыточной конкатенации, а значит, и увеличению порядка сложности.

Пример, замена символов A на B:

Fab { e.X = <Loop () e.X> }

Loop {
  (
e.Acc) 'A' e.Rest = <Loop (e.Acc 'B') e.Rest>;
  (
e.Acc) s.X e.Rest = <Loop (e.Acc s.X) e.Rest>;
  (
e.Acc) /* пусто */ = e.Acc;
}

Здесь есть две конкатенации, с которыми столкнётся Рефал Плюс.

Первая — конкатенация символа с аккумулятором e.Acc 'B' и e.Acc s.X. Если длина аккумулятора N, то потребуется создать новый массив длины N+1, скопировать в него содержимое e.Acc и дописать туда символ ('B' или s.X). На каждом шаге аккумулятор вырастает на единицу, а значит, затраты времени на копирования элементов будут N×(N+1)/2 = O(N²), где — исходная длина строки.

Вторая — конкатенация скобочного терма с остатком строки (…) e.Rest. В ней затраты те же: нужно создать массив длины N+1 (где — длина e.Rest), скопировать туда e.Rest и скобочный терм. Тоже сложность будет O(N²).

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

А вот вторую конкатенацию дыры не спасут, т.к. их там нет. В массиве-аргументе слева от e.Rest уже находится символ, вписать на его место круглую скобку нельзя, т.к. участком массива 'A' e.Rest может пользоваться другая часть программы.

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

Теперь программист вынужден для каждой функции указывать формат, образцы всех предложений должны этот формат уточнять, результат работы функции в этот формат тоже обязан вкладываться. Аргументы функций также должны соответствовать входному формату.

Для функций выше в программе должны быть написаны следующие строчки:

$func Fab e.X = e.X;
$
func Loop (e.Acc) e.X = e.Acc;

Для каждого вызова Loop компилятор проверит, что фактический аргумент вкладывается в формат, после чего аккумулятор и остаток строки передаст в виде двух отдельных параметров. Конкатенации не будет. Сложность функции будет амортизированно линейной.

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

 

Так вот, к чему я пишу. На Рефале-5 конкатенация дешёвая, форматов на уровне синтаксиса нет, встречаются функции с несколькими форматами. Как быть с такими программами? Если функциям неявно приписывать формат e.X = e.X, то программы для Рефала-5, скомпилированные Рефалом Плюс, будут работать заведомо медленно. Причём медленнее не на константу, а на порядок алгоритма.

А что же тогда предполагалось делать, чтобы программы для Рефала-5 были приемлемо эффективны, будучи скомпилированы Рефалом Плюс?

 

В соседней ветке мы обсуждаем плохие приёмы программирования, и одна из мыслей была — борьба с недостатком представления данных протекает в стиль программирования. Так вот, в Рефале Плюс борьба с недостатком представления данных протекла аж в дизайн языка.

 

С уважением,
Александр Коновалов

 

Александр Коновалов a.v.konovalov87_AT_mail.ru

unread,
Dec 24, 2020, 3:35:58 PM12/24/20
to re...@botik.ru

Доброй ночи всем!

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

 

С уважением,
Александр Коновалов

Arkady Klimov arkady.klimov_AT_gmail.com

unread,
Dec 25, 2020, 5:36:38 AM12/25/20
to re...@botik.ru
Александр, Вы же сами пишете, что частью языка Рефал Плюс являются форматы, - это и есть то решение, которое и предполагалось, и осуществлено в Рефале Плюс. 
Что касается компиляции Рефала-5 в бэкенд Рефала Плюс, то именно предполагалось, что форматы будут по возможности выявляться динамически, по крайней мере, так я себе это представлял. А разве не вы с дипломниками эту проблему уже рассматривали и вроде даже как бы решили в прошлом году? Или там было что-то другое? Тогда уточните.
В принципе, аналогичная работа производилась в рамках полусуперкомпилятора Рефала-6 Н.Кондратьевым. А при отображении в С эти форматы использовались (к сожалению, уже четверть века это лежит без употребления).
Аркадий

чт, 24 дек. 2020 г. в 22:33, Александр Коновалов a.v.konovalov87_AT_mail.ru <re...@botik.ru>:


--
_______________
С уважением,
Аркадий Климов,
с.н.с. ИППМ РАН,
+7(499)135-32-95
+7(916)072-81-48

Александр Коновалов a.v.konovalov87_AT_mail.ru

unread,
Dec 26, 2020, 5:58:38 PM12/26/20
to re...@botik.ru

Добрый вечер, Аркадий! Добрый вечер всем остальным!

В письме я сначала отвечу на реплики Аркадия, а потом приведу свои соображения по поводу вывода форматов.

 

«Александр, Вы же сами пишете, что частью языка Рефал Плюс являются форматы, — это и есть то решение, которое и предполагалось, и осуществлено в Рефале Плюс.»

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

Конфликт в том, что системе Рефал Плюс форматы нужны для построения эффективного кода, но в некоторых режимах компиляции во входных файлах этих форматов нет. А значит, или форматы должны рождаться в системе, или должны быть всё-таки как-то указаны пользователем. Иначе программы для Рефала-5 будут выполняться неприемлемо медленно.

(Внимательные читатели обратили внимание на предлог. Я пишу не «на Рефале-5», а «для Рефала-5», подразумевая, что программист пишет код для конкретной реализации. Этот код будет эффективен на данной реализации, однако может быть медленен на альтернативных реализациях.)

 

От Андрея Петровича в частной переписке я узнал, что реализованный фронтэнд Рефала-5 в Рефале Плюс просто приписывает всем функциям формат e = e. Т.е. описанная мною задача решена не была.

 

«Что касается компиляции Рефала-5 в бэкенд Рефала Плюс, то именно предполагалось, что форматы будут по возможности выявляться динамически, по крайней мере, так я себе это представлял.»

А я вообще не представлял, как изначально предполагалось, поэтому и спросил. Вообще существует два варианта решения, а вернее три. Нулевое решение — сунуть голову в песок и приписывать всем функциям формат e = e, оно и было реализовано. Два других: выводить форматы автоматически или требовать от пользователя псевдокомментариев с корректными форматами. Впрочем, возможна комбинация этих подходов.

 

«А разве не вы с дипломниками эту проблему уже рассматривали и вроде даже как бы решили в прошлом году? Или там было что-то другое? Тогда уточните.»

Это другое, как модно сейчас писать в интернете. Вернее, этот вывод форматов решает другую задачу.

 

«В принципе, аналогичная работа производилась в рамках полусуперкомпилятора Рефала-6 Н.Кондратьевым. А при отображении в С эти форматы использовались (к сожалению, уже четверть века это лежит без употребления).»

Любопытно узнать детали.

 

 

А теперь про то, что я сам об этом думаю. А думаю вот что:

·         Для entry- и extern-функций формат задаёт сам пользователь, используя, например, псевдокомментарии. Или пишет отдельный файл с форматами всех entry-функций, который скармливается компилятору. Здесь важно обеспечить консистентность для случаев раздельной трансляции, чтобы форматы, указанные для entry-функции в одном файле и extern-функции с тем же именем в другом совпадали. Но это технический вопрос.

·         Форматы не-entry-функций выводятся компилятором. А это уже вопрос принципиальный.

 

Дальше про вывод форматов. Для простоты я буду рассматривать базисный Рефал.

Но нужно сначала уточнить требования к форматам в Рефале Плюс, вернее те, которые существенны для дальнейшего обсуждения. Требования следующие:

1.    Аргумент каждого вызова функции должен соответствовать формату. Т.е. если ARG — аргумент, а INFMT — входной формат вызываемой функции, то сопоставление ARG : INFMT должно быть успешным и без сужений (ограничений на переменные в ARG).

2.    Правые части предложений каждой функции должны соответствовать выходному формату. Т.е. если RES — выражение в правой части предложения, а OUTFMT — выходной формат функции, то RES : OUTFMT должно быть успешным и без сужений.

3.    Левые части предложений каждой функции должны соответствовать входному формату функции. Т.е. если PAT — выражение в левой части, а INFMT — входной формат, то PAT : INFMT успешно и без сужений.

Известно два алгоритма вывода форматов функций:

·         Алгоритм, разработанный Сергеем Анатольевичем Романенко для повышения местности в самоприменимом «московском специализаторе» в 1987 году.
http://dx.doi.org/10.1007/3-540-52592-0_73

·         Алгоритм, предложенный автором письма и реализованный вместе со студентом Георгием Ивановым в рамках выпускной квалификационной работы в 2019 году.
https://github.com/bmstu-iu9/refal-5-arity-raiser-and-verifier
https://github.com/bmstu-iu9/refal-5-arity-raiser-and-verifier/blob/master/report/diploma/ДипломЗапискаВКР.pdf
(надеюсь, когда-нибудь будет и здесь
DOI)

Целью алгоритма Романенко является повышение местности функций в остаточных программах, построенных специализатором. Выходные форматы функций выводятся на основе анализа определений функций, однако входные форматы — только на основе аргументов всех вызовов данной функции. Т.е. если аргументы всех вызовов функции F можно описать как список из трёх термов, то таковым будет и входной формат функции F независимо от её фактического определения в программе. Более того, формат выведенный для функции может даже не пересекаться с объединением множеств левых частей предложений функции, т.е. вызов такой функции всегда будет фатален.

Применительно к задаче вывода форматов для массивного представления алгоритм обеспечивает только выполнение первых двух требований. При выводе входных форматов не учитываются левые части предложений, поэтому входной формат может не соответствовать определению функции.

Целью алгоритма Коновалова-Иванова (нескромно назовём его так) является проверка корректности программы. Алгоритм выводит и входные, и выходные форматы основываясь на определениях функций (причём анализ делается довольно глубокий), вызовы проверяет только на допустимость. Если существуют такие значения переменных, что все вызовы функций в правой части могут быть выполнены на один шаг, значит, предложение корректное. Иначе (нет таких значений переменных) — в предложении ошибка.

Применительно к рассматриваемой задаче алгоритм обеспечивает только выполнение последних двух требований. В размеченной программе могут быть вызовы функций с аргументами, не вкладывающимися во входные форматы. Например, входной формат функции F может иметь вид (e.1) e.2, в то время как она будет вызываться с аргументом <F e.X s.Y>. Пересечение множеств (e.1) e.2 и e.X s.Y непустое, поэтому верификатор форматов об ошибке не сообщит. Однако, сопоставление e.X s.Y : (e.1) e.2 возможно только с сужением e.X → (e.3) e.4, что нарушает требование 1.

Так что оба алгоритма не подходят для повышения местности для компиляции в массивное представление. Нужна доработка напильником одного из алгоритмов.

 

На этом письмо заканчиваю. В следующем письме я расскажу, какой алгоритм нужно доработать напильником, чтобы удовлетворить все три требования массивного представления. А пока можете делать ставки.

На самом деле, доработать можно оба, но один из них предпочтительнее.

Yuri Klimov yuri_AT_klimov.net

unread,
Dec 27, 2020, 2:41:26 PM12/27/20
to re...@botik.ru
Добрый вечер, коллеги!

Но есть один нюанс. Рефал Плюс использует массивное представление данных с дорогой конкатенацией.
...

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

Мне видится, что было немного не так. Не "язык Рефал Плюс такой, потому что он использует массивное представление", а наоборот: "он использует массивное представление, как наиболее подходящее (с точки зрения авторов в тот момент времени) для реализации возможностей языка Рефала Плюс". А возможности и особенности языка проистекают из цели: сделать язык, замкнутым относительно суперкомпиляции.

На сколько я знаю, когда-то были планы реализации front-end’а Рефала-5 в компиляторе Рефала Плюс.

Да, планы были, но, как я помню, в прямом виде осуществлены не были (Сергей Михайлович, Антон, поправьте, если ошибаюсь).

Однако, в 2000г. был другой проект. У SCP4 результат суперкомпиляции сначала строится в виде графа, а затем уже транслируется к Рефал 5. Был проект поменять backend SCP4 и генерировать из графа не Рефал 5, а Рефал Плюс. Этот проект назывался CGRp (http://rfp.botik.ru/cgrp) и был выполнен Антоном Орловым и мной (в нашем студенчестве). Тут многие возможности Рефала Плюс и пригодились, т.к. в этом графе есть и форматы функций, и другие особенности.

Поэтому компилировать (вернее суперкомпилировать) Рефал 5 в Рефал Плюс можно с помощью SCP4 ;).

Но есть один нюанс. Рефал Плюс использует массивное представление данных с дорогой конкатенацией.

Возвращаясь к конкатенации. В языке две основные операции с выражениями: разбор (взятие подвыражений, копирование) и сбор (контакетанция) . По сути следует рассматривать одну обобщенную операцию: разобрать выражение на части, а потом из частей собрать новое выражение (говорю в первую очередь про разбор-сбор на одном уровне выражения, без "спуска" в скобки). Если какая-то часть размножается или нужно сохранить исходное выражение (чтобы, например, использовать в другой ветке программы), то копирование той или иной части будет необходимо независимо от представления. Поэтому массивные представления Рефала Плюс или Рефала 6 показывают сравнимые результаты с другими представлениями (правда, не знаю глубоких исследований).


И небольшой оффтоп о представлениях. Мне было бы интересно, если бы студенты поисследовали "необычные" представления данных: Rope и Finger Tree. Если я правильно помню, то на их основе разбор-сбор выражений будет по сложности всегда логарифмический.

Мы узнали об этих представлениях на одном контесте. Каждый год проводится ICFP Programming Contest - соревнования при конференции по функциональному программированию. Это три дня (72 часа) на одну необычную Задачу (студентам рекомендую! там задачи очень необычные: из условия обычно совершенно непонятно, что же в итоге придется делать). В 2007 году была задача http://save-endo.cs.uu.nl/ - спасти инопланетянина, переписывая его ДНК. На поверхности этой задачи был язык для изменения ДНК, очень похожий на Рефал. Мы перепробовали несколько подходов, но в итоге скорости работы этой части программы оказалось недостаточно, чтобы продвинуться на уровне победителей. Как потом оказалось, если бы использовали представления данных Rope или Finger Tree, то скорость работы программы была бы существенно выше. Поэтому мне интересно посмотреть эти представления в Рефалах на больших задачах.

С уважением,
    Юрий Климов

Sergei M. Abramov abram_AT_botik.ru

unread,
Dec 28, 2020, 2:26:00 AM12/28/20
to Yuri Klimov yuri_AT_klimov.net
День добрый, всем!

>> Но есть один нюанс. Рефал Плюс использует массивное представление
>> данных с дорогой конкатенацией.
>> ...
>> Эту проблему создатели языка решили жёстко: форматы функций
>> (которые, вообще-то, идиома, рекомендация) сделали частью языка.

> Мне видится, что было немного не так. Не "язык Рефал Плюс такой,
> потому что он использует массивное представление", а наоборот: "он
> использует массивное представление, как наиболее подходящее (с точки
> зрения авторов в тот момент времени) для реализации возможностей
> языка Рефала Плюс". А возможности и особенности языка проистекают из
> цели: сделать язык, замкнутым относительно суперкомпиляции.

Последнее предложение самое важное и наиболее часто забываемое во всех
обсозрных материалах про историю рефала.

У С.А.Романенко перед Рефалом Плюс был препринт, про диалект Рефала, в
котором выразимы результаты разных оптимизаций (например, отсечения
удлинений, КУД-ы), включая суперкомпиляцию.

Мне нестерпимо горько, что массово так и не понято, что любая разумная
суперкомпиляция из любого диалекта Рефала, в котором арнострь и
коарность равна единички, строит результат, в котором арности и
коарности базовых функций (конфигураций) остаточной программы
оказываются любыми, не обязательно единицами.

Это и только это и есть форматы фуннкций. Арности и коарности.

И для меня было знаково, что Рефал Плюс был (как мне известно) первым
(а на мой вкус -- и единственным) функциональным языком, с внятной
реализацией не только арности, но и коарности.

Как результат, в рамках Обнинского семинара мною и Рутиком была
написана программка "глюкало", которая брала вывод тогдашнего
суперкомпилятора Турчина (это был S-граф) и преобразовывала его в
Рефал Плюс програму. С арностью и коарностью.

Вот так. На входе в Турчинский суперкомпилятор Рефял-5, на выходе
S-граф и по нему Рефал Плюс, нашей "глюкалой".

А до того, сам Турчин как-то и не брался откинуть S-граф обратно в
Рефал-5. Ну, мол рук не хватало. Вот он рефал-мальчиков и просил
поучаствовать... ;-)

Но, на мой вкус, не рук не хватало, а проблемы были с тем, что Рефал-5
не совсем пригоден для изображемия результата своей суперкомпиляции...
В силу ровно указанных сложностей.

>> На сколько я знаю, когда-то были планы реализации front-end’а
>> Рефала-5 в компиляторе Рефала Плюс.

> Да, планы были, но, как я помню, в прямом виде осуществлены не были
> (Сергей Михайлович, Антон, поправьте, если ошибаюсь).

Планов было много, увы, не все сделано...


> Однако, в 2000г. был другой проект. У SCP4 результат
> суперкомпиляции сначала строится в виде графа, а затем уже
> транслируется к Рефал 5. Был проект поменять backend SCP4 и
> генерировать из графа не Рефал 5, а Рефал Плюс. Этот проект
> назывался CGRp (http://rfp.botik.ru/cgrp) и был выполнен Антоном
> Орловым и мной (в нашем студенчестве). Тут многие возможности
> Рефала Плюс и пригодились, т.к. в этом графе есть и форматы
> функций, и другие особенности.

Это уже была взрослая и зрелая реинкарнация "глюкалы".

Да, про имя: наша первая программка была названа в честь Роберта
Глюка, который написал перед этим рабпту "В нутре суперкомпилятора" и
изложил некие технические детали, которые помогали понимать, что же
там происходят.

Читать S-граф было не легко. И перевод из него в человеческий язык --
это была работа того же плана, который сделал Роберт в своей
публикации...

> Поэтому компилировать (вернее суперкомпилировать) Рефал 5 в Рефал
> Плюс можно с помощью SCP4 ;).

;-) В точку

>> Но есть один нюанс. Рефал Плюс использует массивное представление
>> данных с дорогой конкатенацией.

> Возвращаясь к конкатенации. В языке две основные операции с
> выражениями: разбор (взятие подвыражений, копирование) и сбор
> (контакетанция) . По сути следует рассматривать одну обобщенную
> операцию: разобрать выражение на части, а потом из частей собрать
> новое выражение (говорю в первую очередь про разбор-сбор на одном
> уровне выражения, без "спуска" в скобки). Если какая-то часть
> размножается или нужно сохранить исходное выражение (чтобы,
> например, использовать в другой ветке программы), то копирование той
> или иной части будет необходимо независимо от представления.
> Поэтому массивные представления Рефала Плюс или Рефала 6 показывают
> сравнимые результаты с другими представлениями (правда, не знаю
> глубоких исследований).

> И небольшой оффтоп о представлениях. Мне было бы интересно, если бы
> студенты поисследовали "необычные" представления данных: Rope и
> Finger Tree. Если я правильно помню, то на их основе разбор-сбор
> выражений будет по сложности всегда логарифмический.

Вот, хорошая постановка проблемы.

> Мы узнали об этих представлениях на одном контесте. Каждый год
> проводится ICFP Programming Contest - соревнования при конференции
> по функциональному программированию. Это три дня (72 часа) на одну
> необычную Задачу (студентам рекомендую! там задачи очень необычные:
> из условия обычно совершенно непонятно, что же в итоге придется
> делать). В 2007 году была задача http://save-endo.cs.uu.nl/ -
> спасти инопланетянина, переписывая его ДНК. На поверхности этой
> задачи был язык для изменения ДНК, очень похожий на Рефал. Мы
> перепробовали несколько подходов, но в итоге скорости работы этой
> части программы оказалось недостаточно, чтобы продвинуться на уровне
> победителей. Как потом оказалось, если бы использовали
> представления данных Rope или Finger Tree, то скорость работы
> программы была бы существенно выше. Поэтому мне интересно
> посмотреть эти представления в Рефалах на больших задачах.

Интересно.

Всего доброго,

Сергей Абрамов
С уважением,
Абрамов С.М. mailto:ab...@botik.ru

Александр Коновалов a.v.konovalov87_AT_mail.ru

unread,
Feb 9, 2021, 1:52:19 AM2/9/21
to re...@botik.ru

Доброе утро всем!

Сначала отвечу на письма Юрия и Сергей Михайловича, а потом закончу свою мысль, начатую в письме от 27.12.2020.

 

«Этот проект назывался CGRp (http://rfp.botik.ru/cgrp) и был выполнен Антоном Орловым и мной (в нашем студенчестве). Тут многие возможности Рефала Плюс и пригодились, т.к. в этом графе есть и форматы функций, и другие особенности.»

Видел эту страничку, знаю о ней, но саму программу не пробовал.

 

«Поэтому компилировать (вернее суперкомпилировать) Рефал 5 в Рефал Плюс можно с помощью SCP4 ;).»

Смайлик тут уместен, т.к. SCP4 пока не может служить заменой компилятору. SCP4 не умеет работать с программами, состоящими из нескольких файлов, и поддерживает далеко не все возможности входного языка (например, функцию Mu). Некоторые конструкции, например, вызовы функций в условиях при образцах с открытыми e-переменными, сделаны через жуткие костыли (тут я не уверен, что CGRp не споткнётся на такой программе). Сами открытые переменные SCP4 на входе поддерживает, но предложения с ними оставляет на выходе без трансформаций, как есть.

 

«И небольшой оффтоп о представлениях. Мне было бы интересно, если бы студенты поисследовали „необычные“ представления данных: Rope и Finger Tree.»
«Поэтому мне интересно посмотреть эти представления в Рефалах на больших задачах.»

Попробую предложить на диплом в этом году. Переделывать будем Рефал-05 (который Станислав Санталов пробовал распараллеливать), а для него самая крупная программа — сам Рефал-05 (в нём нет операции Implode, поэтому запустить SCP4 и MSCP-A на нём нельзя).

 

«У С.А.Романенко перед Рефалом Плюс был препринт, про диалект Рефала, в котором выразимы результаты разных оптимизаций (например, отсечения удлинений, КУД-ы), включая суперкомпиляцию.»

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

Рефал Плюс фактически наследует семантике Рефала-4: усиления и ослабления неуспехов, заборы, отсечения, ветвления («результатные блоки»). Однако, в этих препринтах не было ничего про повышение местности и коместности.

 

«Мне нестерпимо горько, что массово так и не понято, что любая разумная суперкомпиляция из любого диалекта Рефала, в котором арнострь и коарность равна единичке, строит результат, в котором арности и коарности базовых функций (конфигураций) остаточной программы оказываются любыми, не обязательно единицами.»

То, что суперкомпиляция сама по себе повышает входную местность, это было ещё у Турчина в курантовском отчёте. Местности конфигураций равных числу параметров в них. А вот про коместность вопрос не очевиден.

Инструмент построения выходных форматов в SCP4 не является непосредственной частью процесса суперкомпиляции, а является дополнительным инструментом оптимизации. Повышатель коместности вызывается к уже профакторизованной, самодостаточной части графа и её анализирует.

Наверное, чтобы местность и коместность естественным путём повышались в ходе суперкомпиляции, нужно функции рассматривать не как преобразования входа в выход, а как предикаты, связывающие входное и выходное значение. Т.е. суперкомпилировать Пролог. Но, к сожалению, с частичной дедукцией я не знаком, поэтому дальше рассуждать не берусь. Либо строить форматные гипотезы онлайн, в ходе суперкомпиляции.

Так что, почему разумная суперкомпиляция диалекта Рефала, в котором местность и коместность — единички, даст коместность базовых функций не обязательно единичную, мне пока не очевидно.

 

 

А теперь продолжу своё старое письмо. Я там написал, что мне известны два способа повышения местности в Рефале, но они оба не дают той разметки форматов, которая требуется Рефалу Плюс. Один способ: подход Романенко, другой: подход Иванова-Коновалова. Первый не гарантирует того, что входные форматы будут соответствовать образцам, второй — то, что аргументы вызовов не будут соответствовать входным форматам вызываемых функций.

Для компиляции Рефала-5 в Рефал Плюс, на мой взгляд, нужно использовать подход Романенко, т.к. несоответствие входных форматов образцам легко устранимо. Для этого достаточно выполнить обобщённое сопоставление выведенного входного формата с фактическими образцами предложений. Поскольку входной формат всегда описывается жёстким выражением, сопоставление вида He : P всегда можно выразить в виде набора сужений и присваиваний.

Собственно, всё. Мысль, начатую в прошлом году, завершил.

 

С уважением,
Александр Коновалов

 

-----Original Message-----
From: Sergei M. Abramov abram_AT_botik.ru [mailto:re...@botik.ru]
Sent: Monday, December 28, 2020 10:23 AM
To: Yuri Klimov yuri_AT_klimov.net <re...@botik.ru>
Subject: Re:
Рефал-5, Рефал Плюс и форматы

 

День добрый, всем!

Александр Гусев gusev_aleksandr_AT_mail.ru

unread,
Mar 11, 2021, 5:53:45 AM3/11/21
to re...@botik.ru
Добрый день, коллеги!
 
Поделюсь мыслью, показавшейся мне интересной.
 
Читая как-то информацию о Рефале в сети, наткнулся на упоминание отсутствия вложенных функций как недостатка языка. По ходу реализации оказалось, что это не вполне соответствует действительности и такой механизм есть, хотя он не вполне явный и требует некоторой доработки.
Я добавлю здесь небольшой текст из своего описания. Возможно, это будет интересно ещё кому-то.
 
Позволил себе поупражняться в изобретении наименований, если что-то уже было сделано на этот счёт до меня, но я не знаю об этом.
«Авторекурсия» — это вызов функцией самой себя, синтаксически выделяемой как «<<» вместо «<имя_функции». Никаких других «вольностей» в синтаксисе тут нет.
 
Отрывок:

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

Под клозом понимается группа строк паттерна, начинающаяся с одного и того же символа, предпочтительно идентификатора. При вызове функции с указанием конкретного идентификатора, набор обрабатываемых паттернов сократится до строк, начинающихся с этого идентификатора. Если каждый паттерн начинается с идентификатора, то функция будет натуральной кавер — функцией (НКФ, natural cover) с гарантированной ясной логикой использования клозов.

 

Пример печати квадратов цепочки макроцифр:

Cover {

        Square s.1 = <Mul s.1 s.1>;

        Line = <Prout 'Конец списка'>;

        Line e.1 = <Prout '=' e.1>;

        = <<Line>;

        s.1 = <<Line <<Square s.1>>;

        s.1 e.1 = << s.1> << e.1>;

};

То же, но в «классическом» варианте:

Square {

        s.1 = <Mul s.1 s.1>;

};

Line {

        = <Prout 'Конец списка'>;

        e.1 = <Prout '=' e.1>;

};

Cover {

        = <Line>;

        s.1 = <Line <Square s.1>>;

        s.1 e.1 = <Cover s.1> <Cover e.1>;

};

НКФ можно даже оптимизировать на уровне выполнения — сократить перебор вариантов без участия программиста на Рефале. Это вопрос на перспективу.

С уважением,
Александр Гусев
gusev_a...@mail.ru
 

Александр Коновалов a.v.konovalov87_AT_mail.ru

unread,
Mar 11, 2021, 4:24:55 PM3/11/21
to re...@botik.ru
Добрый вечер, Александр!
 
«Читая как-то информацию о Рефале в сети, наткнулся на упоминание отсутствия вложенных функций как недостатка языка.»
 
Интересно понять, что конкретно имелось ввиду, потому что «вложенная функция» — понятие растяжимое. В языках программирования, где вложенные функции есть (как функции высших порядков в функциональных языках или как вложенные процедуры в классическом Паскале), они характеризуются следующими свойствами: синтаксически они расположены внутри определения другой функции, область видимости ограничена той функцией, где они определены, и вложенные функции могут видеть локальные переменные окружающей функции.
 
Вариант с клозами реализует только первые два свойства. Классический Рефал-5 содержит блоки — конструкции вида
 
, Res
: {
    Sent;
    Sent;
    Sent;
  }
 
Их вполне можно считать вложенными функциями, хоть они и вызываются только один раз. Они действительно синтаксически находятся внутри другой функции, недоступны извне и, главное, в них доступны связанные снаружи переменные.
 
Max {
  s.X s.Y
    , <Sub s.X s.Y>
    : {
        '−' s.d = s.Y;
        s.d = s.X;
      };
}
 
Вложенные функции как функции высших порядков предложены Сергеем Скоробогатовым в Рефале-7:
 
Скоробогатов С. Ю., Чеповский А. М. Разработка нового диалекта языка Refal // Информационные технологии. 2006. 9. C. 31-38.
 
Ограниченная поддержка вложенных функций высшего порядка есть в Рефале-5λ — доступны только безымянные вложенные функции.
 
 
«Под клозом понимается группа строк паттерна, начинающаяся с одного и того же символа, предпочтительно идентификатора. При вызове функции с указанием конкретного идентификатора, набор обрабатываемых паттернов сократится до строк, начинающихся с этого идентификатора.»
 
На самом деле всё наоборот. Если почитать первый препринт Турчина о Рефале:
 
 
то можно узнать следующее. Изначально, программа на Рефале была просто набором предложений, а функциональные скобки (скобки конкретизации) были «безымянными». Левая обозначалась к, правая — . (точка). (Знаки < и > Турчин стал использовать уже в Америке, там их ему на конференции предложил МакКарти.)
 
Уже после определения скобок конкретизации на странице 35 препринта (по ссылке выше) Турчин вводит понятие детерминатива — символ после левой скобки конкретизации. А группу предложений с общим детерминативом — как функцию. Вообще, на сколько я понимаю, детерминативы введены отчасти ради эффективной реализации. В этом случае при вычислении конкретизации будут просматриваться не все предложения программы, а только несколько.
 
Вводить кавер-функцию с несколькими подфункциями-клозами можно, такой стиль программирования на Рефале существует. Правда, иногда отдельные клозы не именуют, а просто пользуются различными непересекающимися (или что хуже, пересекающимися) форматами. Такой стиль опасен тем, что ошибившись при вызове, можно случайно вызвать не ту «подфункцию» функции.
 
 
«„Авторекурсия“ — это вызов функцией самой себя, синтаксически выделяемой как „<<“ вместо „<имя_функции“. Никаких других „вольностей“ в синтаксисе тут нет.»
 
На мой вкус, знак «<< …>» неудачный. Глаз привыкает, что знаки < и > являются парными скобками и всегда должны быть сбалансированы, их число должно быть одинаково. Я бы предпочёл какой-нибудь другой, выделяющийся знак для этой цели, например «<@ …>». Сам я когда-то подумывал о слове $REC для аналогичной цели, но сначала поленился, а потом забил — будет потерян один удобный приём отладки (см. здесь пример отладки DoFib).
 
 
С уважением,
Александр Коновалов

Александр Гусев gusev_aleksandr_AT_mail.ru

unread,
Mar 12, 2021, 2:53:06 AM3/12/21
to re...@botik.ru
Добрый день, Александр!
 
Спасибо за реакцию.
 
По моему мнению важным аспектом развития языка является лёгкость вхождения и достаточная лёгкость чтения чужих программ. Поэтому я активно интересуюсь такими вроде незначительными деталями реализации как внешний вид программы и форматирование её текста.
 
Интересно понять, что конкретно имелось ввиду, потому что «вложенная функция» — понятие растяжимое. В языках программирования, где вложенные функции есть (как функции высших порядков в функциональных языках или как вложенные процедуры в классическом Паскале), они характеризуются следующими свойствами: синтаксически они расположены внутри определения другой функции, область видимости ограничена той функцией, где они определены, и вложенные функции могут видеть локальные переменные окружающей функции.
 
Я понимаю под вложенными функциями то же самое.
Что касается блоков и, соответственно, области видимости переменных, то блоки я как раз пока что не принял. Мне кажется, что они сильно усложняют чтение и понимание чужих программ. Мой прежний практический опыт использования Рефала был основан на Рефале-2 на БЭСМ-6 как раз со старой нотацией скобок и отсутствием блоков. Эти программы легко читались несмотря на несколько архаичный по теперешним меркам ситаксис. Это прямо как по старо-славянски читать. Но понятно притом. ))
 
Вообще, на сколько я понимаю, детерминативы введены отчасти ради эффективной реализации. В этом случае при вычислении конкретизации будут просматриваться не все предложения программы, а только несколько.
 
Предлагаемая реализация (т.е. клозы внутри нормальной кавер-функции) позволяет выполнить ещё одну оптимизацию поиска вариантов при выполнении функции. И при этом не производится никаких дополнительных изменений (усложнений) в синтаксисе.
 
Что касается формата скобок при авторекурсии, то я рассматривал разные варианты, начиная со специального имени $SELF и, конечно, с разными символами. И смотрел, насколько читаем полученный текст. Как раз сдваивание «<<» хорошо выделяется, но глаз не «спотыкается» на таком фрагменте, что хорошо. Поскольку кодировка теперь UTF-8, то ассортимент допустимых символов принципиально расширился (и я их использую в режиме просмотра текста), но набирать их на клавиатуре затруднительно, поэтому от разной «экзотики» я отказался. Время покажет насколько всё выбрано удачно.
 
Вообще синтаксической выделение авторекурсии возникло при копировании функций. Если функция сложная, требуются некоторые дополнительные усилия, чтобы «вытравить» из неё использование своего же имени во избежании трудновылавливаемых ошибок.
 
Спасибо за ссылки, это интересно.
Пятница, 12 марта 2021, 0:24 +03:00 от Александр Коновалов a.v.konovalov87_AT_mail.ru <re...@botik.ru>:

Sergei M. Abramov abram_AT_botik.ru

unread,
Mar 12, 2021, 4:26:21 AM3/12/21
to Александр Коновалов a.v.konovalov87_AT_mail.ru
> Знаки < и > Турчин стал использовать уже в Америке, там их ему на
> конференции предложил МакКарти.

Что-то мне запомнилось, что это был Бэкус. И понятно почему именно
Бэкус. Есть связь между граматиками и Рефалом

С уважением,

Абрамов С.М.
ab...@botik.ru
мобильный: +7(903)2928308

Александр Коновалов a.v.konovalov87_AT_mail.ru

unread,
Mar 12, 2021, 4:31:11 AM3/12/21
to Александр Гусев, re...@botik.ru
Добрый день, Александр!
 
«Что касается блоков и, соответственно, области видимости переменных, то блоки я как раз пока что не принял. Мне кажется, что они сильно усложняют чтение и понимание чужих программ.»
 
Многое зависит от форматирования кода. Я встречал программы с блоками и условиями, которые из-за форматирования разбирать трудно — приходится буквально распутывать структуру кода. И встречал программы, где, напротив, код читается легко, т.к. структура из-за форматирования очевидна.
 
Синтаксис Рефала-2 в этом смысле лучше — её сложнее запутать кривым форматированием. Синтаксис языка ограничивает возможности запутать. Первое предложение функции должно начинаться с имени функции, остальные — с пробела. Длинные предложения разбиваются явным знаком переноса «+» в конце строки. Так что всё равно поймёшь, где предложение начинается, а где кончается. К тому же из-за коротких имён переменных сами предложения зачастую оказываются короткими.
 
 
«Вообще синтаксической выделение авторекурсии возникло при копировании функций. Если функция сложная, требуются некоторые дополнительные усилия, чтобы „вытравить“ из неё использование своего же имени во избежание трудновылавливаемых ошибок.»
 
Я подумывал о ключевом слове $REC в связи с необходимостью переименования функции при рефакторинге. Но потом освоил Vim, в котором удобно аккуратно переименовывать все вхождения имени (последовательность нажатий клавиш: *cwНовоеИмя<Escape>n.n.n.n). К тому же Vim умеет автодополнять имена в исходном файле на любом языке программирования, в том числе и на Рефале. Благодаря автодополнению вводить одно и то же имя в нескольких рекурсивных вызовах становится довольно просто.
 
Теперь я начинаю понимать потребность и смысл кавер-функций и авторекурсии. Предметная область Вашего диалекта Рефала подразумевает написание шаблонного кода — когда новый код часто строится путём копирования стандартного шаблона и внесения в него изменений, характерных для задачи. Реализация не поддерживает средства, позволяющие вынести общую логику в библиотеку/фреймворк, либо хотя бы разнести функции по разным пространствам имён (в противном случае можно было скопировать файл, локальные функции переименовывать не потребовалось бы, достаточно переименовать entry-функции). И тогда роль группировки различных функций в одну сущность берёт на себя сама функция — отдельные функции отображаются в группы предложений-клозы, а для вызова самой себя используется синтаксический сахар.
 
Сами клозы, как я понимаю, копировать и переименовывать приходится редко.
 
Я предпочитаю избегать копирование кода. Если нужно напечатать две похожие строчки, то я лучше напечатаю вторую строчку вручную, чем скопирую и поправлю. По своему опыту, когда я копирую кусок кода, то позже обнаруживаю ошибку, которая оказывается в обеих копиях и обе приходится править.
С уважением,
Александр Гусев
wlmailhtml:/compose?To=gusev_a...@mail.ru
 

Александр Коновалов a.v.konovalov87_AT_mail.ru

unread,
Mar 12, 2021, 4:38:32 AM3/12/21
to Александр Коновалов a.v.konovalov87_AT_mail.ru
Добрый день, Сергей Михайлович!

Про знаки < и > мне рассказал Андрей Петрович Немытых и он упоминал
МакКарти. Цитирую переписку:

Я: «Рефал-4 был предложен Романенко в 1987 году, когда Турчин уже
обосновался в Америке и даже написал «The Concept of a Supercompiler».
Кстати, в этой статье он уже использует угловые скобки (вместо k и .).»

А.П.: «Угловые скобки появились в Рефале после разговора Турчина с Маккарти
(автором Лиспа) на одной из конференций. Собственно Маккрати и предложил
Турчину использовать угловые скобки в качестве конструктора вызова функций.»


С уважением,
Александр Коновалов


-----Исходное сообщение-----
From: Sergei M. Abramovabram_AT_botik.ru
Sent: Friday, March 12, 2021 12:25 PM
To: Александр Коновалов a.v.konovalov87_AT_mail.ru
Subject: Re: Изобретение велосипеда

Andrei Klimov andrei_AT_klimov.net

unread,
Mar 12, 2021, 5:06:31 AM3/12/21
to re...@botik.ru
On Fri, Mar 12, 2021 at 12:25 PM Sergei M. Abramov abram_AT_botik.ru <re...@botik.ru> wrote:
> Знаки < и > Турчин стал использовать уже в Америке, там их ему на
> конференции предложил МакКарти.

Что-то мне запомнилось, что это был Бэкус.  И понятно почему именно
Бэкус.  Есть связь между граматиками и Рефалом

Да, мне тоже запомнилось, что Турчин говорил про Бэкуса. И помнится, что зафиксировал в памяти по такому же мнемоническому правилу, как сказал Сергей Михайлович. Хотя я сам слышал из уст ВФ, но память может и изменить, и, может, то, что вам, Александр, сказал Андрей Петрович и правда. Про то, что это было на какой-то конференции, в разговоре со мной не звучало, и я тогда подумал, что это было в частном обсуждении. Но вполне возможно, что это было на какой-то конференции, воркшопе или семинаре.

С МакКарти у Турчина тоже были контакты. Помню его рассказ о другой истории. МакКарти как-то рекомендовал Турчина в какой-то авторитетный комитет и очень удивился, когда ВФ отказался (не хотелось отвлекаться от работы). ВФ привел мне этот сюжет из его жизни в США как пример того, как он не понимал, что принимать такие приглашения нужно для его "адаптации", вхождения в американскую научную среду. Тамошние профессора заседают в таких органах, чтобы "тусоваться" и наводить связи (это мой пересказ по смыслу, а не цитата Турчина); американцы такой возможности никогда не упустят. МакКарти считал, что оказывает Турчину большую услугу, "проталкивая" его в этот орган, и специально звонил Турчину, уточняя, правда ли, что он отказывается и понял ли, о чем речь. 

Всего наилучшего,
Андрей Климов

Александр Коновалов a.v.konovalov87_AT_mail.ru

unread,
Mar 12, 2021, 6:13:19 AM3/12/21
to re...@botik.ru
Добрый день, Андрей Валентинович!
 
Может быть, Турчин, Бэкус и МакКарти втроём на какой-нибудь конференции встретились и идея синтаксиса родилась в ходе совместной беседы. В общем, теперь я буду знать две версии происхождения угловых скобок.
 
 
С уважением,
Александр Коновалов
 
 
Sent: Friday, March 12, 2021 1:05 PM
Subject: Re: Изобретение велосипеда
 

Andrei Klimov andrei_AT_klimov.net

unread,
Mar 12, 2021, 6:38:57 AM3/12/21
to re...@botik.ru
On Fri, Mar 12, 2021 at 2:12 PM Александр Коновалов a.v.konovalov87_AT_mail.ru <re...@botik.ru> wrote:
Добрый день, Андрей Валентинович!
 
Может быть, Турчин, Бэкус и МакКарти втроём на какой-нибудь конференции встретились и идея синтаксиса родилась в ходе совместной беседы. В общем, теперь я буду знать две версии происхождения угловых скобок.

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

Вряд ли это было втроем. Наверняка Турчина рассказывал однозначно, но, пройдя через наши разные уши, перепуталось.

Всего наилучшего,
Андрей
 
Reply all
Reply to author
Forward
0 new messages