Присваивание функции результата

Присваивание функции результата

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

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

Введенное в данной лекции соглашение использует специальную сущность Result. Она рассматривается как локальная сущность, инициализируется соответствующим значением по умолчанию, а возвращаемое значение равно окончательному значению Result. В соответствии с правилами инициализации это значение всегда определено, даже если в теле функции нет присваивания Result значения. Так функция

f: INTEGER is

do

if some_condition then Result := 10 end

end

возвратит 10 при выполнении условия some_condition на момент вызова и 0 (значение по умолчанию при инициализации INTEGER) в противном случае. Насколько известно автору, техника использования Result была впервые предложена в данной книге. С момента выхода первого издания она была включена по крайней мере в один язык - Borland Delphi. Надо заметить, что она неприемлема для языков, допускающих объявление функций внутри других функций, поскольку имя Result становится двусмысленным. В различных языках наиболее часто используются следующие приемы:

[x]. (A) Заключительные инструкции return (C, C++/Java, Ada, Modula-2).

[x]. (B) Использование имени функции в качестве переменной (Fortran, Algol 60, Simula, Algol 68, Pascal).

Соглашение A основано на инструкции вида return e , выполнением которой завершается функция, возвращая e в качестве результата. Преимущество этого метода в его ясности, поскольку возвращаемое значение четко выделено в тексте функции. Однако он имеет и отрицательные стороны:

[x]. (A1) На практике результат часто определяется в процессе вычислений, включающих инициализацию и ряд промежуточных изменений значения. Возникает необходимость во временной переменной для хранения промежуточных результатов.

[x]. (A2) Методика имеет тенденцию к использованию модулей с несколькими точками завершения. Это противоречит принципам хорошего структурирования программ.

[x]. (A3) В языке должна быть предусмотрена ситуация, когда последняя инструкция, выполненная при вызове функции, не является return. В программах Ada в этом случае возбуждается исключение времени выполнения.

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

function name (arguments): TYPE is

do

...

return

expression

end

Это решение развивает идею инструкции return и устраняет ее наиболее серьезные недостатки. Тем не менее, ни один язык его не использует, оставляя проблему A1 открытой.

Методика B использует имя функции как переменную в тексте функции. Возвращаемое значение совпадает с окончательным значением этой переменной. Это избавляет от необходимости объявления временной переменной, упомянутой в A1.

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

f := x

а если f является частью выражения, то подразумевается рекурсивный вызов функции

x := f

который допустим только при отсутствии у f параметров. Однако присваивания вида

f := f + 1

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

Соглашение, основанное на предопределенной сущности Result, устраняет проблемы приемов A и B. В языках, предусматривающих инициализацию по умолчанию всех сущностей, включая Result, достигается дополнительное преимущество. Упрощается написание функций, так как часто функция должна во в всех случаях, кроме специально обусловленных, возвращать значение по умолчанию. Например, функция

do

if some_condition then Result := "Some specific value" end

end

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

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

prefix "|_": INTEGER is

-- Целая часть числа

do

... Реализация опущена ...

ensure

no_greater: Result <= Current

smallest_possible: Result + 1 > Current

end

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

Поделитесь на страничке

Следующая глава >

Похожие главы из других книг

Присваивание

Из книги Давайте создадим компилятор! автора Креншоу Джек


Обозначение результата функции

Из книги Основы объектно-ориентированного программирования автора Мейер Бертран

Обозначение результата функции Для понимания текстов функций rho, theta и distance в классе POINT необходимо еще одно соглашение.Любой язык программирования, поддерживающий функции (подпрограммы, возвращающие результат) должен предусматривать нотацию, позволяющую установить в


11.9.1 Присваивание IP-адресов

Из книги TCP/IP Архитектура, протоколы, реализация (включая IP версии 6 и IP Security) автора Фейт Сидни М

11.9.1 Присваивание IP-адресов В DHCP поддерживаются три типа присвоения адресов:? Ручное, когда IP-адрес вводится на сервере и назначается клиенту постоянно? Автоматическое, когда IP-адрес выбирается сервером из пула доступных адресов и назначается клиенту


7. Когда требуется редактирование результата в fb2-редакторах

Из книги Описание работы пакета OOoFBTools Создание книг FB2 автора Кузнецов Вадим

7. Когда требуется редактирование результата в fb2-редакторах 1. Когда вы хотите внести в полученный fb2 документ тэги и возможности, пока отсутствующие в конвертере (см. п.1.4.)2. Когда вы конвертировали документ с выключенной опцией «Обработка «проблемных» символов»: amp;, › и


Элементы буквального результата

Из книги XSLT автора Хольцнер Стивен

Элементы буквального результата Если элемент в теле шаблона не является инструкцией XSL или элементом расширения, процессор XSLT должен рассматривать его в качестве элемента буквального результата. Это означает, что элемент должен трактоваться буквально и копироваться в


Литеральные элементы результата

Из книги Технология XSLT автора Валиков Алексей Николаевич

Литеральные элементы результата Как мы уже видели из множества примеров, преобразования состоят не только из элементов языка XSLT. Например, в шаблоне<xsl:template match="b"> <В/></xsl:template>элемент B не принадлежит пространству имен XSLT и, следовательно, не считается


Присваивание значений

Из книги VBA для чайников автора Каммингс Стив

Присваивание значений Значения переменным присваиваются с помощью обыкновенного знака равенства. Например, чтобы поместить число 3 в переменную с именем intC, напечатайте intC = 3В VBA оператор присваивания представляет собой связанную знаком равенства конструкцию, с


Простое присваивание

Из книги Язык программирования Си для персонального компьютера автора Бочков C. О.

Простое присваивание Операция простого присваивания обозначается знаком =. Значение правого операнда присваивается левому операнду. Левый операнд должен быть модифицируемым L-выражением. При присваивании выполняются правила преобразования типов, описанные в разделе


Составное присваивание

Из книги QNX/UNIX [Анатомия параллелизма] автора Цилюрик Олег Иванович

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


Возврат результата потока

Из книги Инфобизнес за один день автора Ушанов Азамат

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


7. Программа на месяц до результата

Из книги Цифровой журнал «Компьютерра» № 201 автора Журнал «Компьютерра»

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


История с астрономией, или процесс важнее результата Дмитрий Вибе

Из книги Linux и UNIX: программирование в shell. Руководство разработчика. автора Тейнсли Дэвид

История с астрономией, или процесс важнее результата Дмитрий Вибе Опубликовано 01 декабря 2013 После одной из недавних лекций я услышал упрёк, что слишком много внимания уделил истории вопроса, из-за чего у меня меньше времени осталось на описание


12.1.2. Сохранение выходного результата

Из книги Учись программировать (на Ruby) автора Пайн Крис

12.1.2. Сохранение выходного результата Если нужно сохранить полученные результаты, следует переадресовать их в файл. В приведенном ниже примере выходной результат перенаправляется в файл с именем results.txt. В качестве входного используется файл oops.txt.$ tr -s "[a?z]" < oops.txt >


18.3.5. Проверка результата копирования файла

Из книги автора

18.3.5. Проверка результата копирования файла А теперь осуществим проверку того, успешно ли прошло копирование файла. Если команда cp не скопировала файл myfile в файл myfile.bak, отображается сообщение об ошибке. Обратите внимание, что в сообщении об ошибке фигурирует команда `basename