Что такое «передача по имени» и как она работает? - PullRequest
33 голосов
/ 08 мая 2009

Я проверил Википедию и погуглил, но все еще не могу понять, как работает передача по имени в ALGOL 60.

Ответы [ 8 ]

36 голосов
/ 08 мая 2009

Я нашел хорошее объяснение в Передача параметра по имени . По сути, тело функции интерпретируется во время вызова после текстовой подстановки фактических параметров в тело функции. В этом смысле метод оценки похож на метод макроса препроцессора C.

Подставляя фактические параметры в тело функции, тело функции может как читать, так и записывать данные параметры. В этом смысле метод оценки похож на передачу по ссылке. Различие состоит в том, что, поскольку при передаче по имени параметр оценивается внутри функции, такой параметр, как a[i], зависит от текущего значения i внутри функции, а не ссылается на значение в a[i] до вызова функции.

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

15 голосов
/ 08 мая 2009

Я предполагаю, что вы имеете в виду вызов по имени в ALGOL 60.

Call-by-name похож на call-by-reference в том, что вы можете изменить значение переданного параметра. Он отличается от вызова по ссылке тем, что параметр не вычисляется до вызова процедуры, а вместо этого оценивается лениво. То есть он оценивается тогда и только тогда, когда параметр фактически используется.

Например, предположим, что у нас есть процедура f(x, y), и мы передаем ее i и i/2, где i изначально равно 10. Если f устанавливает x в 42, а затем оценивает y, он увидит значение 21 (тогда как при вызове по ссылке или вызове по значению он все равно увидит 5). Это связано с тем, что выражение i/2 не выполняется до тех пор, пока не будет оценено значение y.

Во многих отношениях это похоже на буквальную текстовую подстановку параметров (с переименованием, чтобы избежать конфликтов имен). На практике, однако, это реализуется с использованием "thunks" (в основном замыканий) для переданных выражений.

Статья в Википедии о Устройство Дженсена показывает некоторые интересные примеры использования вызова по имени. Вот один из них:

real procedure Sum(k, l, u, ak)
     value l, u;
     integer k, l, u;
     real ak;
     comment k and ak are passed by name;
 begin
     real s;
     s := 0;
     for k := l step 1 until u do
         s := s + ak;
     Sum := s
 end;

В процедуре индексная переменная k и сумма суммирования ak равны прошло по имени. Вызов по имени позволяет процедуре изменить значение индексной переменной во время выполнения цикла for. Звонок по имени также вызывает переоценку аргумента ak во время каждой итерации петля. Как правило, ak будет зависеть от изменения (побочный эффект) k.

Например, код для вычисления суммы первых 100 слагаемых реального массив V[] будет:

Sum(i, 1, 100, V[i]).
3 голосов
/ 08 мая 2009

Для тех, кто в будущем:

Основные понятия в языках программирования Джон С. Митчелл был также полезным.

Pass-по-имени . Возможно, самый странный Особенностью Algol 60, оглядываясь назад, является использование пароля по имени. В передача по имени, результат вызов процедуры такой же, как если бы формальный параметр был подставлен в Тело процедуры. Это правило для определения результата процедуры позвонить, скопировав процедуру и замена формальных параметров называется правилом копирования Algol 60. Хотя правило копирования работает хорошо для чисто функциональные программы, а проиллюстрировано β снижение лямбда исчисление, взаимодействие со стороной эффекты к формальному параметру являются немного странно. Вот пример программа, показывающая технику как устройство Дженсена: прохождение выражение и переменная, которую он содержит к процедуре, чтобы процедура можно использовать один параметр, чтобы изменить местоположение, на которое ссылается другой:


 begin integer i;
        integer procedure sum(i, j);
            integer i, j;
                comment parameters passed by name;
            begin integer sm; sm := 0;
                for i := 1 step 1 until 100 do sm := sm + j;
                sum := sm
            end;
        print(sum(i, i*10 ))
 end

В этой программе процедура sum (i, j) складывает значения j как i идет от 1 до 100. Если вы посмотрите на код, вы поймете, что процедура не имеет смысла, если изменения я вызываю некоторые изменения в значение j; в противном случае процедура просто вычисляет 100 * j. В вызове сумма (я, я * 10) показано здесь, цикл for в теле процедуры сумма складывается значение I * 10, как я идет от 1 до 100.

2 голосов
/ 01 января 2015

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

call :assign x 1
exit /b
:assign
setlocal enabledelayedexpansion
(endlocal
:: Argument 1 is the name of the variable
set %1=%2
)
exit /b
1 голос
/ 17 октября 2017

Я знаю, что опаздываю в клуб, и это не обязательно ответ, но я хотел бы добавить одну вещь, которая могла бы помочь прояснить немного. Я всегда думал о передаче имени Algol как процесс, подобный тому, когда директивы препроцессора C ++ (в частности, макросы) заменяют имя некоторой функции / переменной на реальный кусок кода во время компиляции. Передача по имени по существу заменяет имя формального параметра фактическим параметром и выполняется. Я никогда не писал на Алголе, но слышал, что передача по имени будет иметь тот же результат, что и передача по С ++.

1 голос
/ 12 сентября 2014

ALGOL был разработан для математических алгоритмов. Мне нравится функция суммирования в качестве примера вызова по имени.

Извините, мой Алгол немного заржавел, синтаксис, вероятно, неправильный.

.FUNCTION SUM(var,from,to,function)
.BEGIN
  .REAL sum =0;
  .FOR var = from .TO to .DO sum = function;
  return sum;
.END

Вы могли бы использовать сумму как

  Y = sum(x,1,4,sum(y,3,8,x+y));

В приведенном выше примере внутренняя сумма (y, 3,8, x + y) будет генерировать безымянную функцию для передачи на вызов внешней суммы. Переменные x и y передаются не по значению, а по имени. В случае переменных вызов по имени эквивалентен вызову по ссылке на адрес в Си. При использовании рекурсии это немного сбивает с толку.

Занимается изготовлением машин ALGOL. У них была 48-битная память слов с 3 флагами. Биты флага реализовали вызов по имени ALGOL. это была машина стека, поэтому, когда функция загружалась в стек, вызов по имени fag вызывал ее вызов. Компилятор генерирует безымянные функции, когда выражения используются в качестве аргументов. Переменная будет простой косвенной ссылкой. Произошла ошибка при записи в функцию.

1 голос
/ 15 сентября 2011

Вы можете передать «имя» в символической форме переменной, которая позволяет одновременно обновлять и получать к ней доступ. В качестве примера предположим, что вы хотите утроить переменную x типа int:

start double(x);
real x;
begin
x : = x * 3
end;
1 голос
/ 08 мая 2009

Flatlander имеет яркий пример того, как он работает в Scala здесь . Предположим, вы хотели реализовать , а :

def mywhile(condition: => Boolean)(body: => Unit): Unit =
  if (condition) {
    body
    mywhile(condition)(body)
  }

Мы можем назвать это следующим образом:

var i = 0
mywhile (i < 10) {
  println(i)
  i += 1
}

Скала - это не Алгол 60, но, возможно, он проливает свет.

...