пятница, 13 апреля 2012 г.

Есть ли operator присваивания в Паскале?

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

В ходе подготовки учебника к экспертизе у редактора возникли сомнения по поводу моей фразы: «Оператор «:=» — это оператор присваивания». По её мнению, оператор присваивания — это всё выражение вида «переменная := выражение;», а символы «:=» — это знак присваивания.

Как оказалось, этот терминологический вопрос совсем не прост. Изучение источников как на русском, так и на английском языках, даёт противоречивые результаты.

Поскольку речь идет о Паскале, обратимся, прежде всего, к отчёту «The Programming Language Pascal», который написал Никлаус Вирт, создатель этого языка. Он пишет:

«The most fundamental statement is the assignment statement. It specifies that a newly computed value be assigned to a variable (or a component of a variable).»

«Assignment statement» — это оператор присваивания, здесь слово «statement» действительно переводится на русский как оператор в значении «инструкция», «команда».

Но вопрос в другом — как назвать символ «:=»? Вирт в своих работах не дает ему никакого названия, такой же подход принят и в стандарте ISO7185.

Часто утверждается, в Паскале вообще нет оператора присваивания, такого как в Си и Си++, потому что присваивание — «это утверждение, а не выражение». Однако существует и другое мнение. Например, в книге М. Канту «Essential Pascal» видим термин «colon-equal operator». А Н. Дейл прямо использует термин «assignment operator» (см. «Programming in Pascal», глава 2).

Итак, мы добрались до сути: «:=» — это оператор или не оператор? Чтобы ответить на этот вопрос, нужно понять, какое значение слова «оператор» имеется в виду. В английском языке используется два совершенно разных слова, которые переводятся на русский одним и тем же словом «оператор» — это «statement» и «operator». С оператором-statement вроде бы всё понятно. Оператор-operator — это другой термин, который связан с математическим понятие оператора — правила преобразования одного объекта в другой.

Выражение «assignment operator» широко используется в таких языках, как Си и Си++, где оператор присваивания обозначается знаком «=». Его суть в том, что оператор присваивания создает новый объект на основе двух существующих объектов, записывая новое значение в переменную.

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

Считается, что в «классическом» Паскале оператора присваивания (в смысле operator) нет. Но это не совсем верно. Вот пример программы, которая работает во всех современных версиях Паскаля:
var a: integer;
    b: longint;
begin
  a := 5;
  b := a;
  b := 25;
  a := b;
end.
Очевидно, что здесь перед записью значения в переменную некоторые преобразования данных (приведение к другому типу) автоматически выполняются.

Кроме того, в современной версии Free Pascal символ «:=» вполне законно называется оператором присваивания, потому что его можно перегружать, как и в Си++. В программе, приведенной ниже, показан пример такой перегрузки.
type
  complex = record re,im: real; end;
var z: complex;
  operator :=(r: double) z: complex;
  begin
    z.re:=r;
    z.im:=0;
  end;
begin
  z:=3;
end.
Выводы: Таким образом, в современном Паскале «X:=Y;»  — это оператор присваивания (statement), а «:=» — это тоже оператор присваивания (operator).

Автор благодарит О.А. Полежаеву за интересное обсуждение, в результате которого появилась эта заметка.

Ярлыки: , , ,

Комментарии: 2:

В 30 мая 2012 г., 12:38 , Anonymous tech сказал(а)...

Напишите, пожалуйста, заметку о том, как правильно по отношению к переменным:
"присваивание, присваивать" или "присвоение, присвоить". Везде по разному.

 
В 23 июня 2012 г., 19:34 , Blogger Б.Б. сказал(а)...

В том, что у «:=» нет отдельного имени по сравнению с «переменная := выражение» (без точки с запятой – она частью оператора не является) нет ничего странного. И знак «:=», и указанная грамматическая конструкция присваивания, и конкретные ее овеществления как «x := a+b» – все три и есть «оператор присваивания». Конечно, речь идет о разных сторонах данного понятия, но нужды именовать их по разному нет. Впрочем, точно так же и «<=», и «выражение<=выражение», и «p<=q» называют операцией «меньше или равно», и никакой путаницы из-за этого не возникает. Конечно, иногда все-таки лучше сказать более конкретно «знак чего-то».

Далее, Ваше утверждение «Часто утверждается, в Паскале вообще нет оператора присваивания, такого как в Си и Си++ …» вводит в заблуждение: на самом деле цитированный Вами текст утверждает, что у Паскаля нет «operator»-а, т.е. операции присваивания. Что и верно – операцией «:=» в Паскале не является, тогда как «=» в Си есть как раз операция. И неряшливость того или иного англоязычного – точно так же как и любого другого – автора, назвавшего «:=» operator, суть дела не меняет. В стандарте же языка таких оплошностей не найти.

Еще далее, Ваше утверждение «В английском языке используется два совершенно разных слова, которые переводятся на русский одним и тем же словом „оператор“» неточно. Английское слово operator в литературе на русском по программированию принято переводить как «операция». Не заметили? По этому поводу отмечу, что в учебниках и монографиях советского времени я ни разу не видел путаницы между операциями и операторами – они так же четко отличаются друг от друга, как и operator и statement в английском. (С другой стороны, возможно, термины тогда были выбраны неудачно. Может, лучше называть operator оператором, а statement – командой. Будь то так или иначе, но важнее всего понимать и соблюдать различие между понятиями.)

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

Кроме того, злосчастная заметка Листера отношения к затронутому Вами вопросу не имеет, да и Вы ее неправильно толкуете. Присваивание в Си является операцией (operator) не потому что оно допускает выполнение преобразований. Присваивание в Си (в отличие от Паскаля) выдает в свой контекст значение, подобно +, < и т.д. Можно написать, скажем, такое выражение: 3*(b=x+y). Вот поэтому «=» в Си и числится среди операций, а «:=» в Паскале – нет.

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

Кстати, по поводу вашего примера «программы, которая работает во всех версиях Паскаля». Там используется тип чисел longint, которого в Паскале, строго говоря, нет. У языка два стандарта – Pascal (ISO 7185:1990), т.е. Паскаль Н.Вирта, и Extended Pascal (ISO 10206:1990) – Расширенный Паскаль. Ни один из этих стандартов longint не определяет. Правда, есть еще и такое понятие как «Object Pascal», но оно не стандартизовано и вообще весьма расплывчато – скорее, это семейство реализаций чем язык, так что сказать что в нем есть в принципе невозможно. В частности, в отношении longint можно говорить лишь о реализациях того или иного нестандартного расширения языка Паскаль.

 

Отправить комментарий

Подпишитесь на каналы Комментарии к сообщению [Atom]

<< Главная страница