wiki:CharactersInIdentifiers

Имена функций в Рефале+

Имена функций в Рефале+ от 1991 года

Согласно книге по Рефалу+ 1991 года в качестве имен функций могут использоваться любые символы-слова.

Для символов-слов существует две формы записи:

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

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

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

Откуда взялись правила записи имен функций в Рефале+ от 1991 года?

Проблемы с большими и малыми буквами

Сейчас многие странности трудно понять, если не знать некоторые особенности оборудования, на котором работали советские программисты в 1991 году.

А именно, дисплеи/мониторы, которые умели показывать строчные (маленькие) буквы, уже были, а большинство принтеров печатать маленькие буквы еще не умели!

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

Отсюда и появилось странное соглашение по поводу использования бльших и малых букв в идентификаторах.

Использование знаков -, ? и ''' в идентификаторах

Это соглашение тоже выглядит странно. Почему - можно испльзовать, а + - нельзя? И почему ? и ''' могут появляться в начале идентификатора, а - не может?

И откуда вообще взялась идея разрешить использовать -, ? и ''' в идентификаторах?

Ответ простой: эти правила были позаимствованы из языка Схема (Scheme). (Кстати, слово scheme в английском языке может еще и иметь такие смыслы, как "махинация", "афера", "коварный замысел", что свидетельствует о том, что его разработчики были не лишены чувства юмора. А "замысел" был, видимо, направлен в сторону Лиспа, который был чем-то вроде "священной-коровы", на которую нельзя было посягать. :-) )

А откуда взялось такое соглашение в Схеме? А появилось оно от того, что когда-то малых букв не было ни на клавиатурах, ни на мониторах, на у принтеров. А идентификаторы, состоящие из нескольких слов, нужно было как-то разбивать на части. Например, если фразу "get value" записать "сплошняком" как GETVALUE, то нехорошо получается... Вот в Лиспе и Схеме и разрешили вставлять минус. Тогда получается GET-VALUE, что уже лучше.

Однако, в языках, в которых используется инфиксная форма записи операций (Фортран, C, C++, Java, C#, SML), вставлять минус в середину идентификатора не разрешается (по понятным причинам).

Ну вот, в 1991 году Гурин и Романенко взяли да и бездумно позаимствовали из Схемы правило, что -, ? и ''' можно вставлять в идентификаторы!

Нехорошие последствия использования -, ? и ''' в идентификаторах

Усложняется введение инфиксных операций (если захочется это сделать)

Если захочется разрешить использование инфиксных операций в Рефале, то получится, что такие важные знаки, как -, ? и ''' уже заняты для других целей!

Проблемы при стыковке с другими языками

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

При этом нужно обеспечить не только "принципиальную" возможность стыковки, но и добиваться того, чтобы это можно было делать на практике, и при этом чрезмерно не напрягаясь. Т.е., если какая-то ерунда (в особенности, искусственно "высосанная из пальца") осложняет стыковку, то нужно эту ерунду безжалостно искоренять!

А между тем, при компиляции Рефал-программ на такие языки, как C++, Java, C#, и им подобные, сразу же возникает "проблема кодировки идентификаторов". Приходится "идентификатор" Get-Value превращать во что-нибудь наподобие Get_m_Value. Ну зачем нужна эта лишняя морока?

Почему проблемой именования функций пришлось заняться именно сейчас

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

Предложения по изменению во входном языке

Нужно различать большие и малые буквы

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

Лучше выкинуть экзотические знаки из идентификаторов

-, ? и ''' лучше вообще не разрешать в идентификаторах.

Вместо -, очевидно, лучше использовать большие и малые буквы. Например, GET-VALUE заменить на GetValue?.

''' вообще мало где используется. А где используется, легко заменяется на что-то более вразумительное и понятное. Например WRITE и WRITE''' можно заменить на Write и WriteCh? (или ChWrite?).

? в идентификаторах реально используется только для записи предикатов. Без проблем заменяется на что-то более конкретное. Например, INT? заменяется на IsInt? (как в большинстве других языков).

Есть еще одна функция, состоящая из одного ? (которая достает содержимое ящика). Её можно переименовать в Get. Все равно ведь две другие функции называются по-простому: Box и Store.

? в ключевых словах можно и оставить

Поскольку ключевые слова вроде $func? не являются "идентификаторами", и перекодировать их никуда не нужно, то их можно оставить как есть.

Лучше запретить символы-слова в двойных кавычках

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

В настоящее время в библиотеке функций есть 9 экзотических имен функций: "*", "+", "-", "/=", "<", "<=", "=", ">", ">=". Наглядность записи программ они не очень-то и повышают (поскольку их вызовы пишутся не в инфиксном виде, а в префиксном). Так отчего бы не переименовать их во что-то вроде Mul, Add, Sub, Neq, Le, Le, Eq, Gt, Ge.

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

Что делать?

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

В данный момент нужно принять принципиальное решение...

Сергей Романенко 4 октября 2006


Что сделано в текущей реализации

Большие и маленькие буквы в символах-словах

Большие и маленькие буквы различаются по умолчанию. Для того чтобы запустить программу, написанную без учёта этого различия, надо указать компилятору опцию -u -- тогда все символы-слова, записанные без кавычек, будут переведены в верхний регистр (а имена объектов будут приведены к тому виду, как они давались при объявлении этих объектов).

Произвольные символы внутри кавычек

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

Есть программка rfp-filt.rf, которая преобразует идентификаторы между Refal+ и C++.

Механизм кодирования в принципе рассчитан на работу с любыми символами (в частности, с русскими, японскими, арабскими буквами), однако на данный момент реализовано только преобразование ASCII-символов. Идея заключается в том, каждый символ, особый для целевого языка, записывается как _код_, где код -- некое уникальное обозначение символа (например, его номер в какой-нибудь из Unicode-кодировок). Для ASCII-символов код -- это, обычно, буквенное обозначение символа, как m для минуса. Сам _ кодируется как __.

Действительно, если запретить идентификаторы в кавычках, и символы -, ? и ''', то жизнь станет намного проще. Можно, опять же, сделать опцию, которая возвращает старое поведение для компиляции старых программ или для желающих писать имена по-русски.

Однако, пара соображений:

  1. Символы-слова используются не только как идентификаторы. Полностью запретить символы-слова в двойных кавычках -- не слишком ли сильный ход?
  2. Для того чтобы не было сложностей с использованием функций, написанных на Java или C++, в именах было бы правильно разрешить использовать _, а также разрешить именам начинаться с маленькой буквы.

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

Антон Орлов -- Wed Oct 4 17:38:49 2006


Разъяснения и комментарии

Большие и маленькие буквы различаются по умолчанию. Для того чтобы запустить программу, написанную без учёта этого различия, надо указать компилятору опцию -u -- тогда все символы-слова, записанные без кавычек, будут переведены в верхний регистр (а имена объектов будут приведены к тому виду, как они давались при объявлении этих объектов).

Другими словами, часть из моих предложений уже реализована? Вот и хорошо...

Символы-слова используются не только как идентификаторы. Полностью запретить символы-слова в двойных кавычках -- не слишком ли сильный ход?

Имел в виду, что следует запретить символы-слова в кавычках в качестве имен функций. Т.е. что имена функций должны быть идентификаторами. А символы-слова сами по себе - это просто неизменяемые (immutable) строки, которые никому не мешают.

Для того, чтобы не было сложностей с использованием функций, написанных на Java или C++, в именах было бы правильно разрешить использовать _, а также разрешить именам начинаться с маленькой буквы.

Подчеркивание разрешить, вроде, можно. И это будет соответствовать общепринятой практике (C++, Java, C#).

Насчет маленьких букв в начале идентификаторов возникает проблема: как отличать символы-слова в тексте программы от переменных? Что такое sX: имя функции или переменная? Наверное, тогда нужно договориться, что если сразу после < или & появляется идентификатор с маленькой буквой вначале, то это - имя функции. Но если захочется написать символ-слово не после < или &, и он начинается с маленькой буквы, то тогда его уже следует заключать в двойные кавычки.

Сергей Романенко -- Wed Oct 4 21:05:00 2006


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

Идентификаторы -- это имена функций и других объектов (ящиков, таблиц, и т.д.). В программе они встречаются либо при объявлении объекта (после $func, $box, $const, ...), либо при ссылке на него (после & и <), либо как имя определяемой функции. Ничто, кроме идентификаторов, в указанных позициях встречаться не может.

Идентификатор не является рефал-символом, он не может входить в объектное выражение. Никакого способа получить новый идентификатор во время исполнения программы нет (на самом деле, во время исполнения никаких идентификаторов вообще не существует).

Записываются идентификаторы без кавычек, по правилам Явы (они, вроде, совпадают с Си).

А сужать множество символов-слов, записываемых без кавычек, необязательно. Наоборот, можно его расширить. Например, добавив _ в качестве разрешённого символа.

Антон Орлов Wed Oct 4 21:37:29 2006


Предварительные итоги дискуссии

(Сама дискуссия происходила по э-почте.)

  • Опускание точек в записи переменных запрещать не следует.
  • При записи "символов-слов" двойные кавычки можно опускать, только если "слово" является "идентификатором" и начинается с большой буквы или подчеркивания.
  • В именах функций можно использовать буквы, цифры и подчеркивания. Начинаться они могут с буквы или подчеркивания. Малые буквы в начале не запрещены, поскольку контекст всегда позволяет отличать имена функций от символов слов.
  • Имена rfi- и rf-файлов должны удовлетворять тем же ограничениям, что и имена функций.
  • При записи символов-слов без кавычек, они должны удовлетворять тем же требованиям, что и имена функций, и начинаться с большой буквы.

Обоснование

  • Запрет на опускание точки расходится с некоторыми другими разновидностями Рефала и дополнительно провоцирует раскол Рефал-сообщества. Поэтому, возможность опускания точек следует сохранить.
  • Изгнание значков '-', '?' и '!' из имен функций - дело хорошее, поскольку они являются "вывертом" именно Рефала+. Стало быть, их изгнание способствует сближению Рефала+ с другими разновидностями Рефала.
  • Если имена rfi- и rf-файлов будут удовлетворять тем же ограничениям, что и имена функций, то подмена имен файлов понадобится только в тех случаях, когда имя файла будет совпадать с ключевым словом того языка, на который производится компиляция. В этом случае желательно, чтобы компилятор испускал предупреждение, чтобы пользователь не ломал голову, отчего Build Manager ведет себя неадекватно. А в реализациях, делающих прямую компиляцию в JVM или CIL, эта проблема вообще исчезнет.
  • Символы-слова без кавычек не должны начинаться с малой буквы, чтобы их можно было отличить от переменных. Т.е. это - следствие того, что в записи переменных разрешается опускатиь точку.
  • Смысл запрета на опускание кавычек для слов, содержащих ?!-, в настоящее время не "технический", а "политический".
    • Непонятно, почему нужно разрешать ?!-, но при этом запрещать, например +* ?
    • А если разрешить слишком много, то потом может случиться так, что захочется расширить синтаксис Рефала+, а все "хорошие" значки уже заняты.

Сергей Романенко -- Sat Oct 7 15:45:20 2006


Дополнение к итогам дискуссии

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

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

А если разрешить малые буквы в начале идентификаторов, то, глядя на лексему eA, уже нельзя распознать, является ли она переменной или идентификатором?

А это плохо по двум причинам.

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

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

Сергей Романенко -- Sun Oct 22 17:25:51 2006

Last modified 14 years ago Last modified on Oct 22, 2006, 5:26:45 PM