На каком языке (ах) устанавливается возвращаемое значение путем присвоения имени функции?

Jan 18 2021

В этом вопросе о переполнении стека исходный код допустил ошибку, использовав имя функции в качестве переменной и присвоив ей возвращаемое значение. Комментатора отметил , что он когда - то использовал язык , где это было так , как вы вернули значение из функций. Комментарий гласит: «Я знаю, что когда-то использовал язык, на котором возвращаемое значение функции нужно было присвоить имени функции. Он настолько древний и устаревший, что я даже не могу вспомнить, на каком языке это было».

Мне это тоже кажется знакомым, но я также не могу вспомнить, на каком языке это было.

У кого-нибудь память лучше, чем у нас, и может ли он сказать нам, на каком это языке?

Ответы

50 WillHartung Jan 18 2021 at 22:45

Это делает Паскаль, других я не знаю. Не знаю, продвинется ли практика с другими языками вирта.

50 OmarL Jan 18 2021 at 23:14

Языки семейства Visual Basic делают именно это. Сюда входят VBScript, VBA, Visual Basic и более ранние версии. Я считаю, что они наследуют "особенность" QBASIC. Например

Public Function AddTwo(something as Integer)
    AddTwo = something + 2
End Function
29 scruss Jan 18 2021 at 23:03

Фортран, точно:

      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 .

22 user3840170 Jan 18 2021 at 23:54

Самые ранние такие языки, которые мне удалось найти, - это 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 также произошло из-за этого.)

17 Raffzahn Jan 19 2021 at 00:28

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оператор в своем стремлении добавить процедурное программирование, но его использование было просто для возврата выполнения вызывающей стороне, возвращаемое значение должно было быть установлено отдельно.

12 alephzero Jan 18 2021 at 23:02

Фортран использовал этот синтаксис с самой ранней версии, которая вообще имела функции, вплоть до Фортрана 2008 года и позже.

Однако в Fortran 2008 есть (еще более запутанная?) Опция, в которой вы можете объявить другое имя переменной, которое используется для возврата значения функции! Например

function xyz(argument) result(answer)
...
answer = 42
...
end function xyz

вместо старого стиля

...
xyz = 42
...
9 another-dave Jan 19 2021 at 01:02

Алгол 60 за одного.

Вот соответствующие слова из Пересмотренного отчета по алгоритмическому языку Algol 60 .

5.4.4. Значения функциональных обозначений.

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

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

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

В Algol 60 за вызовом функции, которая не принимает аргументов, не ставятся пустые круглые скобки: n := readскорее, чем n := read().

Последнее предложение также известно как предложение, которое содержит рекурсивные процедуры в языке. Но это не имеет отношения к этому ответу.

6 StephenKitt Jan 18 2021 at 23:03

BASIC - это еще один язык с функциями, где в некоторых диалектах используется присвоение имени функции для предоставления возвращаемого значения. Самые ранние диалекты были похожи на однострочные функции Фортрана:

DEF FND(x) = x*x

Но более поздние диалекты допускали более сложные варианты, подобные многострочным функциям Fortran :

DEF FNPeekWord& (A&)
  FNPeekWord& = PEEK(A&) + 256& * PEEK(A& + 1)
END DEF
5 LyndonWhite Jan 19 2021 at 20:38

MATLAB / Octave также делает это.

Это с 1984 года; так что не такой старый, как некоторые другие.

Вероятно, он имитировал Фортран, поскольку изначально задумывался как инструмент высокого уровня. Поверх библиотек Fortran, таких как Linpack и Eispack.

5 chasly-supportsMonica Jan 19 2021 at 21:29

Я считаю, что это сделал СНОБОЛ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

4 d3jones Jan 19 2021 at 07:12

Verilog (1995/2001) также возвращается путем присвоения неявной переменной. SystemVerilog добавил оператор «return», но классическое присваивание все еще доступно.

1 arne Jan 21 2021 at 03:02

Haskell (с 1990 г.) также делает это:

doubleMe x = x + x  

определяет функцию doubleMeодного параметра xи присваивает ей тело функции x+x, см. отличный Learn You A Haskell For Great Good

mathrick Jan 19 2021 at 13:08

Я лично использовал Паскаль для этого. Common Lisp вроде как-то вроде-но-не-на самом деле делает это, поскольку возвращаемые значения почти всегда неявны (т.е. каждый оператор имеет значение, а последнее значение в блоке является возвращаемым значением блока), поэтому вы очень редко видите явный оператор возврата, но если вам необходимо вернуть значение и не может использовать неявный способ, способ сделать это с помощью RETURN-FROM[*] заявление, например , так: (return-from function-name value).

[*] Также есть RETURNоператор, но он является сокращением (return-from nil value)и не влияет VALUEна значение функции, в которой он был выполнен. Это отличная ловушка для новичков, пришедших из C и его потомков.