На каком языке (ах) устанавливается возвращаемое значение путем присвоения имени функции?
В этом вопросе о переполнении стека исходный код допустил ошибку, использовав имя функции в качестве переменной и присвоив ей возвращаемое значение. Комментатора отметил , что он когда - то использовал язык , где это было так , как вы вернули значение из функций. Комментарий гласит: «Я знаю, что когда-то использовал язык, на котором возвращаемое значение функции нужно было присвоить имени функции. Он настолько древний и устаревший, что я даже не могу вспомнить, на каком языке это было».
Мне это тоже кажется знакомым, но я также не могу вспомнить, на каком языке это было.
У кого-нибудь память лучше, чем у нас, и может ли он сказать нам, на каком это языке?
Ответы
Это делает Паскаль, других я не знаю. Не знаю, продвинется ли практика с другими языками вирта.
Языки семейства Visual Basic делают именно это. Сюда входят VBScript, VBA, Visual Basic и более ранние версии. Я считаю, что они наследуют "особенность" QBASIC. Например
Public Function AddTwo(something as Integer)
AddTwo = something + 2
End Function
Фортран, точно:
PROGRAM TRIANG
WRITE(UNIT=*,FMT=*)'Enter lengths of three sides:'
READ(UNIT=*,FMT=*) SIDEA, SIDEB, SIDEC
WRITE(UNIT=*,FMT=*)'Area is ', AREA3(SIDEA,SIDEB,SIDEC)
END
FUNCTION AREA3(A, B, C)
*Computes the area of a triangle from lengths of sides
S = (A + B + C)/2.0
AREA3 = SQRT(S * (S-A) * (S-B) * (S-C))
END
(из Руководства профессионального программиста Клайва Г. Пейджа по Fortran77 ).
Это также определено таким образом в стандарте Fortran ANSI X 3.9 1966 Fortran 66 .
Самые ранние такие языки, которые мне удалось найти, - это FORTRAN II и ALGOL 58, оба опубликованные в одном 1958 году; хотя оригинальный FORTRAN (1956), возможно, также может быть включен.
Для FORTRAN первая страница главы руководства, посвященной функциям, содержит этот пример (стр. 27):
FUNCTION AVRG (ALIST, N)
DIMENSION ALIST (500)
SUM = ALIST (1)
DO 10 I=2, N
SUM = SUM + ALIST (I)
AVRG = SUM / FLOATF (N)
RETURN
END (2, 2, 2, 2, 2)
FORTRAN II также включает другой синтаксис функции (стр. 10), однострочное определение функции, унаследованное от своего предшественника:
FIRSTF(X) = A*X + B
Нетрудно понять, что первый синтаксис является естественным продолжением второго, в свою очередь, из математического использования.
АЛГОЛ 58 , как и ФОРТРАН, определяет обе однострочные "функции":
Объявление функции объявляет данное выражение функцией некоторых его переменных. Таким образом, объявление дает (для некоторых простых функций) правило вычисления для присвоения значений функции (см. Функции ) всякий раз, когда эта функция появляется в выражении.
Форма: Δ ~ I n (I, I, ~, I): = E, где I - идентификаторы, а E - выражение, которое среди своих составляющих может содержать простые переменные, названные идентификаторами, указанными в скобках.
и «процедуры», эквивалентные сегодняшнему определению функции (по крайней мере, в императивных / процедурных языках программирования). Возвращаемое значение указывается следующим образом (стр. 19):
Для каждой отдельной процедуры вывода I (P i ), указанной в заголовке, значение должно быть присвоено внутри процедуры с помощью оператора присваивания «I: = E», где I - идентификатор, называющий эту процедуру.
Эти синтаксисы позже были приняты некоторыми диалектами BASIC (в форме DEF FN
и позже FUNCTION
) и потомком ALGOL Pascal: в компиляторах Borland Pascal присвоение имени функции было единственным поддерживаемым синтаксисом до введения Result
переменной в Delphi 1.0.
Вероятно, упомянутый комментатор запомнил Паскаль; некоторые университеты до сих пор преподают на нем программирование и обычно придерживаются оригинального стандартного набора вместо современных расширенных диалектов, таких как Object Pascal. (На самом деле это не часть вопроса, но я предполагаю, что недоразумение автора StackOverflow также произошло из-за этого.)
TL; DR:
Я бы сказал, что, скорее всего, это PASCAL, который вы помните, поскольку он был довольно популярен в начале 80-х, использовался на университетских курсах с 80-х до 90-х годов, и после этого у него все еще были стипендии, в первую очередь Delphi.
Немного истории
Основная идея состоит в том, что имя функции не только уже зарезервировано, поэтому нет необходимости придумывать что-то другое, и его использование является четким утверждением, что это результат. Это также упрощает конструкцию компилятора, поскольку в соглашении о вызовах можно выделить специальный элемент данных.
По сути, существует две линии наследия: FORTRAN и ALGOL.
Для обоих некоторые из их потомков сохранили его, например
- некоторые варианты BASIC от FORTRAN и
- Паскаль и Модула из Алгола.
Другие бросили это, например, продолжение ALGOL
- BCPL, который ввел
return()
синтаксис,
что довольно распространено сегодня, поскольку C взял его из BCPL.
Языковые идеи подобны генам, прыгающим между хозяевами. Например, ADA, во многих отношениях внучка ALGOL / PASCAL, также обратилась к использованию return
элемента.
Дедушка FORTRAN с годами изменил способ возврата результатов функции.
- Первоначально результат функции был назначен идентификатору функции.
- в FORTRAN 90 было введено явное определение возвращаемого имени в заголовке функции.
Хотя это, по сути, просто синтаксический сахар, в нем есть изменение в стиле. Применяемая аргументация заключалась в том, что с рекурсивными конструкциями вроде Foo = Foo(x-1)
бы выглядело странно. Но я предполагаю, что это вопрос интерпретации.
Интересно и то, что FORTRAN II 1958 года вводил RETURN
оператор в своем стремлении добавить процедурное программирование, но его использование было просто для возврата выполнения вызывающей стороне, возвращаемое значение должно было быть установлено отдельно.
Фортран использовал этот синтаксис с самой ранней версии, которая вообще имела функции, вплоть до Фортрана 2008 года и позже.
Однако в Fortran 2008 есть (еще более запутанная?) Опция, в которой вы можете объявить другое имя переменной, которое используется для возврата значения функции! Например
function xyz(argument) result(answer)
...
answer = 42
...
end function xyz
вместо старого стиля
...
xyz = 42
...
Алгол 60 за одного.
Вот соответствующие слова из Пересмотренного отчета по алгоритмическому языку Algol 60 .
5.4.4. Значения функциональных обозначений.
Чтобы объявление процедуры определяло значение указателя функции, в теле объявления процедуры должны присутствовать один или несколько явных операторов присваивания с идентификатором процедуры в левой части; по крайней мере один из них должен быть выполнен, а тип, связанный с идентификатором процедуры, должен быть объявлен через появление декларатора типа как самый первый символ объявления процедуры. Последнее присвоенное таким образом значение используется для продолжения вычисления выражения, в котором встречается указатель функции.
Любое появление идентификатора процедуры в теле процедуры, кроме левой части оператора присваивания, означает активацию процедуры.
Последнее предложение имеет важное значение - оно показывает, что имя типа процедура (функция) не обрабатывается «так же, как» переменная в теле процедуры (функции); скорее, это только назначение, которое носит особый характер.
В Algol 60 за вызовом функции, которая не принимает аргументов, не ставятся пустые круглые скобки: n := read
скорее, чем n := read()
.
Последнее предложение также известно как предложение, которое содержит рекурсивные процедуры в языке. Но это не имеет отношения к этому ответу.
BASIC - это еще один язык с функциями, где в некоторых диалектах используется присвоение имени функции для предоставления возвращаемого значения. Самые ранние диалекты были похожи на однострочные функции Фортрана:
DEF FND(x) = x*x
Но более поздние диалекты допускали более сложные варианты, подобные многострочным функциям Fortran :
DEF FNPeekWord& (A&)
FNPeekWord& = PEEK(A&) + 256& * PEEK(A& + 1)
END DEF
MATLAB / Octave также делает это.
Это с 1984 года; так что не такой старый, как некоторые другие.
Вероятно, он имитировал Фортран, поскольку изначально задумывался как инструмент высокого уровня. Поверх библиотек Fortran, таких как Linpack и Eispack.
Я считаю, что это сделал СНОБОЛ4. http://berstis.com/greenbook.pdf
Ниже приводится пример определения и использования функции для вычисления факториалов чисел:
DEFINE('FACT(N)') :(SKIPFCN) * Set value to 1 FACT FACT = 1 * Return 1 if N<2 * Return N*((N-1)!) with recursive call FACT = GT(N,1) FACT(N - 1) * N :(RETURN) SKIPFCN OUTPUT = '5 factorial is ' FACT(5)
http://berstis.com/s4ref/prim3e.htm
Verilog (1995/2001) также возвращается путем присвоения неявной переменной. SystemVerilog добавил оператор «return», но классическое присваивание все еще доступно.
Haskell (с 1990 г.) также делает это:
doubleMe x = x + x
определяет функцию doubleMe
одного параметра x
и присваивает ей тело функции x+x
, см. отличный Learn You A Haskell For Great Good
Я лично использовал Паскаль для этого. Common Lisp вроде как-то вроде-но-не-на самом деле делает это, поскольку возвращаемые значения почти всегда неявны (т.е. каждый оператор имеет значение, а последнее значение в блоке является возвращаемым значением блока), поэтому вы очень редко видите явный оператор возврата, но если вам необходимо вернуть значение и не может использовать неявный способ, способ сделать это с помощью RETURN-FROM
[*] заявление, например , так: (return-from function-name value)
.
[*] Также есть RETURN
оператор, но он является сокращением (return-from nil value)
и не влияет VALUE
на значение функции, в которой он был выполнен. Это отличная ловушка для новичков, пришедших из C и его потомков.