Что такое ссылочная прозрачность?

Что означает термин ссылочная прозрачность? Я слышал, что это описано как "это означает, что вы можете заменить equals равными", но это кажется неадекватным объяснением.

Ответ 1

Термин "ссылочная прозрачность" происходит от аналитической философии, отрасли философии, которая анализирует конструкции, утверждения и аргументы естественного языка, основанные на методах логики и математики. Другими словами, это самый близкий предмет вне компьютерной науки к тому, что мы называем семантикой языка программирования. Философ Уиллард Куайн был ответственен за инициирование концепции ссылочной прозрачности, но это также подразумевалось в подходах Бертрана Рассела и Альфреда Уайтхеда.

По своей сути "ссылочная прозрачность" - очень простая и понятная идея. Термин "референт" используется в аналитической философии, чтобы говорить о том, на что ссылается выражение. Это примерно то же самое, что мы подразумеваем под "значением" или "обозначением" в семантике языка программирования. Используя пример Эндрю Биркетта (сообщение в блоге), термин "столица Шотландии" относится к городу Эдинбургу. Это простой пример "референта".

Контекст в предложении является "ссылочно-прозрачным", если замена термина в этом контексте другим термином, относящимся к той же сущности, не меняет смысла. Например

Шотландский парламент собирается в столице Шотландии.

означает так же, как

Парламент Шотландии встречается в Эдинбурге.

Таким образом, контекст "Шотландский парламент встречается в..." является референтно прозрачным контекстом. Мы можем заменить "столицу Шотландии" на "Эдинбург", не меняя смысла. Другими словами, контекст заботится только о том, к чему относится этот термин, и ничего более. В этом смысле контекст "ссылочно прозрачен".

С другой стороны, в предложении

Эдинбург был столицей Шотландии с 1999 года.

мы не можем сделать такую замену. Если бы мы это сделали, мы бы получили "Эдинбург был Эдинбургом с 1999 года", что является сумасшедшей вещью, и не передает того же значения, что и первоначальное предложение. Таким образом, может показаться, что контекст "Эдинбург был... с 1999 года" является косвенно непрозрачным (противоположность ссылочно-прозрачным). По-видимому, он заботится о чем-то большем, нежели термин Что это?

Такие вещи, как "столица Шотландии", называются определенными терминами, и в течение долгого времени они не причиняли головной боли логикам и философам. Рассел и Куайн разобрались с ними, сказав, что они на самом деле не являются "ссылочными", т.е. Ошибочно думать, что приведенные выше примеры используются для обозначения сущностей. Правильный способ понять, что "Эдинбург был столицей Шотландии с 1999 года", это сказать

Столица Шотландии существует с 1999 года, и эта столица - Эдинбург.

Это предложение не может быть преобразовано в сумасшедшее. Задача решена! Суть Куайна состояла в том, чтобы сказать, что естественный язык является грязным или, по крайней мере, сложным, потому что он сделан удобным для практического использования, но философы и логики должны вносить ясность, правильно понимая их. Ссылочная прозрачность - это инструмент, который используется для придания такой ясности значения.

Какое отношение все это имеет к программированию? Не очень, на самом деле. Как мы уже говорили, ссылочная прозрачность - это инструмент, который используется для понимания языка, т.е. При назначении значения. Кристофер Стрейчи, который основал семантику языка программирования, использовал его в своем исследовании значения. Его основополагающая статья " Основные понятия в языках программирования " доступна в Интернете. Это красивая бумага, и каждый может ее прочитать и понять. Поэтому, пожалуйста, сделайте это. Вы будете очень просветленным. Он вводит термин "ссылочная прозрачность" в этом параграфе:

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

Использование "по существу" предполагает, что Стрейчи перефразирует его, чтобы объяснить его простыми словами. Функциональные программисты, кажется, понимают этот абзац по-своему. Есть 9 других случаев "ссылочной прозрачности" в статье, но они, кажется, не беспокоятся ни о каких других. Фактически вся статья Стрейчи посвящена объяснению значения императивных языков программирования. Но сегодня функциональные программисты утверждают, что императивные языки программирования не являются ссылочно прозрачными. Стрейчи будет превращаться в его могилу.

Мы можем спасти ситуацию. Мы сказали, что естественный язык "грязный или, по крайней мере, сложный", потому что он сделан удобным для практического использования. Языки программирования одинаковы. Они "грязные или, по крайней мере, сложные", потому что они сделаны так, чтобы их было удобно использовать на практике. Это не значит, что они должны нас смущать. Они просто должны быть поняты правильно, используя мета-язык, который является ссылочно прозрачным, чтобы у нас была ясность смысла. В статье, которую я цитировал, Стрейчи делает именно это. Он объясняет значение императивных языков программирования, разбивая их на элементарные понятия, нигде не теряя ясности. Важной частью его анализа является указание на то, что выражения в языках программирования имеют два вида "значений", называемых l-значениями и r-значениями. До статьи Стрейчи это не было понято, и воцарилась путаница. Сегодня определение C упоминает об этом регулярно, и каждый программист C понимает это различие. (Понимают ли программисты на других языках это одинаково хорошо, трудно сказать.)

И Куайн, и Стрейчи были обеспокоены значением языковых конструкций, которые включают некоторую форму зависимости от контекста. Например, наш пример "Эдинбург является столицей Шотландии с 1999 года" означает тот факт, что "столица Шотландии" зависит от времени, в которое она рассматривается. Такая зависимость от контекста является реальностью, как на естественных языках, так и на языках программирования. Даже в функциональном программировании свободные и связанные переменные должны интерпретироваться с учетом контекста, в котором они появляются. Зависимость от контекста любого вида так или иначе блокирует ссылочную прозрачность. Если вы попытаетесь понять значение терминов без учета контекста, от которого они зависят, вы снова получите путаницу. Куайна интересовало значение модальной логики. Он считал, что модальная логика была непрозрачной в отношении ссылок, и ее следует очистить, переведя ее в референтно прозрачную структуру (например, рассматривая необходимость как доказуемость). Он в значительной степени проиграл эту дискуссию. Логики и философы одинаково находили, что возможная мировая семантика Крипке вполне адекватна. Подобная ситуация также царит с императивным программированием. Зависимость от состояния, объясненная Стрейчи, и зависимость от запаса, объясненная Рейнольдсом (аналогично возможной мировой семантике Крипке), вполне адекватны. Функциональные программисты мало знают об этом исследовании. Их идеи относительно ссылочной прозрачности следует воспринимать с большой долей соли.

[Дополнительное примечание: Приведенные выше примеры иллюстрируют, что простая фраза, такая как "столица Шотландии", имеет несколько уровней значения. На одном уровне мы можем говорить о столице в настоящее время. На другом уровне мы могли бы говорить о всех возможных столицах, которые Шотландия могла иметь с течением времени. Мы можем "увеличить" конкретный контекст и "уменьшить", чтобы довольно легко охватить все контексты в обычной практике. Эффективность естественного языка использует нашу способность сделать это. Императивные языки программирования эффективны практически так же. Мы можем использовать переменную x в правой части присваивания (значение r), чтобы говорить о ее значении в определенном состоянии. Или мы можем говорить о его l-значении, которое охватывает все состояния. Людей редко смущают такие вещи. Однако они могут или не могут точно объяснить все слои значения, присущие языковым конструкциям. Все такие слои значения не обязательно являются "очевидными", и это вопрос науки, чтобы изучить их должным образом. Однако неспособность обычных людей объяснять такие многоуровневые значения не означает, что они смущены ими.]

Отдельный "постскриптум" ниже связывает это обсуждение с проблемами функционального и императивного программирования.

Ответ 2

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

Ниже приведен пример ссылочной прозрачной функции:

int plusOne(int x)
{
  return x+1;
}

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

Другим хорошим примером является математика в целом. В математике с заданной функцией и входным значением она всегда будет сопоставляться с тем же выходным значением. f (x) = x + 1. Поэтому функции в математике являются ссылочно прозрачными.

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

Ссылочная прозрачность всегда используется в таких функциональных языках, как Haskell.

-

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

//global G
int G = 10;

int plusG(int x)
{//G can be modified externally returning different values.
  return x + G;
}

Другим примером является функция-член в объектно-ориентированном языке программирования. Функции-члены обычно работают с переменными-членами и поэтому будут непрозрачными. Функции членов, но могут, конечно, быть ссылочно прозрачными.

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

Ответ 3

Референциально прозрачная функция - это функция, которая зависит только от ее ввода.

Ответ 4

[Это постскриптум к моему ответу от 25 марта, чтобы ближе обсудить обсуждение проблем функционального/императивного программирования.]

Идея функциональных программистов относительно ссылочной прозрачности, по-видимому, отличается от стандартного понятия тремя способами:

  • В то время как философы/логики используют термины, такие как "ссылка", "обозначение", "десигнат" и "простыня" (термин Фреге), функциональные программисты используют термин "ценность" . (Это не совсем так. Я замечаю, что Ландин, Страхи и их потомки также использовали термин "ценность" , чтобы говорить о ссылке/обозначении. Это может быть просто терминологическое упрощение, введенное Ландином и Стрехи, но, похоже, большая разница при использовании наивным образом.)

  • Функциональные программисты, похоже, считают, что эти "ценности" существуют внутри языка программирования, а не снаружи. При этом они отличаются от философов и семантистов языка программирования.

  • Они, похоже, считают, что эти "ценности" должны быть получены путем оценки.

Например, статья Википедии о ссылочной прозрачности говорит сегодня утром:

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

Это полностью противоречит тому, что говорят философы/логики. Они говорят, что контекст является ссылочным или ссылочно прозрачным, если выражение в этом контексте может быть заменено другим выражением, которое ссылается на одно и то же (выражение для основного выражения). Кто эти философы/логики? Они включают Frege, Russell, Whitehead, Carnap, Quine, Church и бесчисленное множество других. Каждый из них - возвышающаяся фигура. Объединенная интеллектуальная сила этих логиков, по меньшей мере, разрушает мир. Все они единодушны в том, что референты/обозначения существуют вне формального языка, и выражения внутри языка могут говорить только о них. Таким образом, все, что можно сделать в языке, - это заменить одно выражение другим выражением, которое относится к одной и той же сущности. Референты/обозначения сами по себе не существуют в пределах языка. Почему функциональные программисты отклоняются от этой устоявшейся традиции?

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

Landin:

(a) каждое выражение имеет структура подвыражения вложенности, (б) каждое подвыражение обозначает что-то (обычно число, значение истины или численная функция), (в) вещь, обозначаемая выражением, то есть его "значение" , зависит только от значений его под- а не по другим свойствам их. [Добавлен упор]

Stoy:

Единственное, что имеет значение для выражения, это его значение, и любое подвыражение может быть заменяется любым другим равным по величине [Добавленный упор]. Более того, значение выражения в определенных пределах одинаково, когда оно происходит ".

Птица и Вадлер:

значение выражения зависит только от значений его составляющей выражения (если таковые имеются), и эти подвыражения могут свободно заменяться другими обладая тем же значением [Добавленный упор].

Итак, ретроспективно, усилия Ландина и Стрехи по упрощению терминологии путем замены "ссылки" / "обозначения" на "ценность" могли быть вредными. Как только кто-то слышит "ценность" , возникает соблазн подумать о процессе оценки, который ведет к нему. В равной степени соблазнительно думать о том, что оценка дает как "ценность" , хотя может быть совершенно ясно, что это не обозначение. Это то, что я собираюсь сделать с концепцией "ссылочной прозрачности" в глазах функциональных программистов. Но "ценность" , о которой говорили ранние семантики, не является результатом оценки или вывода функции или любой такой вещи. Это обозначение термина.

Как только мы понимаем так называемое "значение" выражения ( "ссылка" или "обозначение" в дискурсе классических философов) как сложный математический/концептуальный объект, открываются всевозможные возможности.

  • Strachey интерпретировал переменные на языках императивного программирования как L-значения, как упоминалось в ответе от 25 марта, который представляет собой сложный концептуальный объект, который не имеет прямого представления в синтаксисе языка программирования.
  • Он также интерпретировал команды на таких языках, как функции "состояние в государстве", еще один экземпляр сложного математического объекта, который не является "значением" в синтаксисе.
  • Даже вызов функции побочных эффектов в C имеет четко определенное "значение" как трансформатор состояния, который отображает состояния в пары состояний и значений (так называемая "монада" в терминологии функциональных программистов).

Нежелание функциональных программистов называть такие языки "ссылочно прозрачными" просто означает, что они неохотно допускают такие сложные математические/концептуальные объекты, как "ценности" . С другой стороны, они кажутся совершенно готовыми называть трансформатор состояния "ценностью", когда он помещается в свой собственный любимый синтаксис и наряжается словом buzz вроде "монада". Я должен сказать, что они совершенно непоследовательны, даже если мы дадим им понять, что их идея "ссылочной прозрачности" имеет некоторую согласованность.

Немного истории может немного рассказать о том, как возникли эти путаницы. Период между 1962 и 1967 годами был очень интенсивным для Кристофера Стрехи. Между 1962-65 годами он занимал неполную рабочую должность в качестве научного сотрудника с Морисом Уилксом для разработки и внедрения языка программирования, получившего название CPL. Это был императивный язык программирования, но он также имел мощные возможности функционального программирования. Ландин, который был сотрудником Strachey в своей консалтинговой компании, оказал огромное влияние на взгляд Strachey на языки программирования. В знаменательной статье 1965 года "Следующие 700 языков программирования", Ландин беззастенчиво продвигает языки функционального программирования (называя их денотативными языками) и описывает императивные языки программирования как их "антитезу". В последующем обсуждении мы находим, что Стрэчи вызывает сомнения в сильной позиции Ландина.

... DL формы подмножество всех языков. Они представляют собой интересное подмножество, но одно что неудобно использовать, если вы к этому не привыкли. Нам нужно потому что на данный момент мы не знаем, как построить доказательства с языками, которые включают в себя императивы и прыжки. [Добавлен упор]

В 1965 году Стрэчи занял позицию читателя в Оксфорде и, похоже, работал по существу на полную ставку по разработке теории императивов и прыжков. К 1967 году он был готов к теории, которую он преподавал в своем курсе "Основные понятия в языках программирования" в летней школе в Копенгагене. Предполагалось, что лекции будут опубликованы, но "к сожалению, из-за дилятивных редактирование, судебное разбирательство никогда не осуществлялось; как большая часть работы Страхиса в Оксфорде, однако, бумага имела влиятельный частный тираж ". (Мартин Кэмпбелл-Келли)

Трудность получения трудов Страхи могла привести к распространению разломов, когда люди полагались на вторичные источники и слухи. Но теперь, когда "Основные понятия" легко доступны в Интернете, нет необходимости прибегать к угадыванию работы. Мы должны прочитать его и составить собственный разум относительно того, что имел в виду Стрэчи. В частности:

  • В разделе 3.2 он рассматривает "выражения", где он говорит о "ссылочной прозрачности R-ценности".
  • Его раздел 3.3 посвящен "командам", где он говорит о "ссылочной прозрачности L-ценности".
  • В разделе 3.4.5 он говорит о "функциях и процедурах" и заявляет, что "любое отклонение ссылочной прозрачности R-ценности в контексте R-ценности должно либо быть устранены путем разложения выражения на несколько команд и более простого выражения, или, если это окажется трудным, субъект комментария. "

Любые разговоры о "ссылочной прозрачности" без понимания различия между значениями L, R-значениями и другими сложными объектами, которые заполняют концептуальную вселенную императивного программиста, в корне ошибочны.

Ответ 5

Выражение является ссылочно прозрачным, если его можно заменить его значением, не изменяя алгоритм, давая алгоритм, который имеет одинаковые эффекты и выводит на один и тот же вход.

Ответ 6

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

Ответ 7

Если вы заинтересованы в этимологии (т.е. почему эта концепция имеет это конкретное имя), посмотрите мой сообщение в блоге по теме. Терминология исходит от философа/логика Куайна.

Ответ 8

Для тех, кто нуждается в кратком объяснении, я буду угрожать одному (но прочитайте ниже).

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

f x = x + x,

легкость, с которой вы можете (безопасно) заменить f (foo) на foo + foo в рамках этого определения, не имея слишком большого количества ограничений на то, где вы можете выполнить это сокращение, является хорошим показателем того, сколько ссылочной прозрачности ваш язык программирования.

Например, если foo был x ++ в смысле программирования C, вы не смогли бы выполнить это снижение безопасно (то есть, если бы вы выполнили это сокращение, вы бы закончили с той же программой, с которой вы начали).

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

(Полное раскрытие: я являюсь функциональным программистом, поэтому по верхнему ответу вы должны принять это объяснение с помощью соли).

Ответ 9

  • Denotational-semantics основана на языках моделирования, создавая домены, которые представляют собой обозначенные значения.
  • Функциональные программисты используют значение термина для описания конвергенции вычисления на основе правил перезаписи языка, т.е. его операционная семантика.

В 1 есть ясность двух языков:

  • тот, который моделируется, язык объектов
  • язык моделирования, метаязык

В 2, благодаря близости объекта и метаязыков, их можно путать.

Как разработчик языка, я считаю, что мне нужно постоянно помнить это различие.

Итак, профессор Редди, могу перефразировать вас так: -)

В контексте функционального программирования и семантики термин Ссылочный Прозрачность не является ссылочной прозрачностью.

Ответ 10

Следующий ответ, который я надеюсь добавить и квалифицировать спорные 1-й и 3-й ответы.

Допустим, что выражение обозначает или ссылается на некоторые референент. Однако возникает вопрос, могут ли эти референты изоморфно кодироваться как часть самих выражений, вызывая такие выражения "значения". Например, значения литерального числа являются подмножеством набора арифметических выражений, значения истинности являются подмножеством множества булевых выражений и т.д. Идея состоит в том, чтобы оценить выражение для его значения (если оно есть). Таким образом, слово "значение" может относиться к значению или к выделенному элементу набора выражений. Но если существует изоморфизм (биекция) между референтом и значением, мы могут сказать, что они одно и то же. (При этом нужно быть осторожным, чтобы определить референты и изоморфизм, доказанные полем денотационного семантика. Чтобы привести пример, упомянутый в ответах на 3-й ответ, определение типа алгебраических данных data Nat = Zero | Suc Nat не соответствуют ожидаемому набору натуральных чисел.)

Запишем E[·] для выражения с дыркой, также известной в некоторых кругах как "контекст". Два контекстных примера для C-подобных выражений: [·]+1 и [·]++.

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

Приспособим определение Quine несколько формально следующим образом: контекст E[·] является ссылочно прозрачным, если заданы любые два выражения E1 и E2 (без отверстий там) такие, что [[E1]] = [[E2]] (т.е. выражения обозначают/относятся к тот же референт), то это имеет место, если [[E[E1]]] = [[E[E2]]] (т.е. заполнение отверстие с помощью E1 или E2 приводит к выражениям, которые также обозначают один и тот же референт).

Правило Лейбница подстановки равных для равных обычно выражается как "if E1 = E2, то E[E1] = E[E2] ', в котором говорится, что E[·] является функцией. Функция (или, в этом случае, программа, вычисляющая функцию) является отображением из источника к цели, так что для каждого источника имеется не более одного целевого элемента элемент. Недетерминированные функции являются неверными, они либо являются отношениями, функции, передающие множества и т.д. Если в правиле Лейбница равенство = денотационные, тогда двойные скобки просто воспринимаются как должное и опущены. Таким образом, контекстно-прозрачный контекст является функцией. И правило Лейбница является основным компонентом эквациональных рассуждений, поэтому эквациональное мышление, безусловно, связано с ссылочной прозрачностью.

Хотя [[·]] является функцией от выражений до обозначений, это может быть от выражений до "значений", понимаемых как ограниченное подмножество выражения и [[·]] можно понимать как оценку.

Теперь, если E1 - это выражение, а E2 - это значение, которое, как мне кажется, подразумевается большинством людей при определении ссылочной прозрачности с точки зрения выражений, значений и оценки. Но, как проиллюстрировано 1-м и 3-м ответами на этой странице, это неявное определение.

Проблема с контекстами, такими как [·]++, не является побочным эффектом, но ее значение не определено в C изоморфно ее значению. Функции а не значения (ну, указатели на функции), тогда как на языках функционального программирования они есть. Приземлиться, Стрэчи и пионеры денотационной семантики были довольно умны в используя функциональные миры для обеспечения смысла.

Для императивных C-подобных языков мы можем (грубо) предоставить семантику выражения с использованием функции [[·]] : Expression -> (State -> State x Value).

Value является подмножеством Expression. State содержит пары (Идентификатор, значение). Семантическая функция принимает выражение и его значение означает функцию из текущего состояния в пару с обновленным состояние и значение. Например, [[x]] - это функция из текущего состояния к паре, первой составляющей которой является текущее состояние, а вторая компонентом является значение x. Напротив, [[x++]] - это функция из текущее состояние к паре, первой компонентой которой является состояние, в котором значение от x увеличивается, а второй компонент - это очень большое значение. В этом смысл, контекст [·]++ является ссылочно прозрачным, если он удовлетворяет определение выше.

Я думаю, что функциональные программисты имеют право использовать ссылочную прозрачность в смысл, что они, естественно, восстанавливают [[·]] как функцию от выражений до значений. Функции являются первоклассными значениями, и состояние также может быть значением, а не денотат. Государственная монада (частично) - чистый механизм для прохождения (или threading) состояние.

Ответ 11

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

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

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

Ответ 12

В функциональном программировании ссылочная прозрачность обычно определяется как факт, что выражение в программе может быть заменено его значением (или всем, имеющим одно и то же значение) без изменения результата программы. Это означает, что методы всегда должны возвращать одно и то же значение для данного аргумента без какого-либо другого эффекта. Однако эта концепция функционального программирования также применима к обязательному программированию и может помочь вам сделать код более понятным.

Референциальная прозрачность

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

Ссылочная прозрачность в математике В математике ссылочная прозрачность является свойством выражений, которые могут быть заменены другими выражениями, имеющими одинаковое значение, без какого-либо изменения результата. Рассмотрим следующий пример:

x = 2 + (3 * 4)

Мы можем заменить подвыражение (3 * 4) любым другим выражением, имеющим одно и то же значение, без изменения результата (значение x). Наиболее очевидное выражение для использования, конечно, 12:

x = 2 + 12

Любое другое выражение, имеющее значение 12 (возможно (5 + 7)), может быть использовано без изменения результата. Как следствие, подвыражение (3 * 4) является ссылочно прозрачным.

Мы также можем заменить выражение 2 + 12 другим выражением, имеющим одно и то же значение, без изменения значения x, поэтому оно также является трансляционно прозрачным:

x = 14

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

Ссылочная прозрачность в программировании В программировании ссылочная прозрачность применяется к программам. Поскольку программы состоят из подпрограмм, которые являются самими программами, это относится и к этим подпрограммам. Подпрограммы могут быть представлены, среди прочего, методами. Это означает, что метод может быть ссылочным прозрачным, что имеет место, если вызов этого метода может быть заменен его возвращаемым значением:

int add(int a, int b) {
        return a + b
    }

int mult(int a, int b) {
        return a * b;
    }

int x = add(2, mult(3, 4));

В этом примере метод mult является ссылочно прозрачным, поскольку любой вызов его может быть заменен соответствующим возвращаемым значением. Это можно наблюдать, заменив mult (3, 4) на 12:

int x = add(2, 12)

Точно так же добавление (2, 12) может быть заменено соответствующим возвращаемым значением, 14:

int x = 14;

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

С другой стороны, рассмотрим следующую программу:

int add(int a, int b) {
    int result = a + b;
    System.out.println("Returning " + result);
    return result;
}

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

public static void main(String... args) {
    printFibs(10);
}

public static void printFibs(int limit) {
    Fibs fibs = new Fibs();
    for (int i = 0; i < limit; i++) {
        System.out.println(fibs.next());
    }
}

static class Fibs {
    private int previous = -1;
    private int last = 1;

    public Integer next() {
        last = previous + (previous = last);
        return previous + last;
    }
}

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

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

Референциальная прозрачность в императивном программировании. Функции использования императивного и функционального программирования. Хотя функциональное программирование использует только функции, императивное программирование использует:

  • чистые функции: методы, возвращающие значения и не имеющие других эффектов
  • чистые эффекты: методы, возвращающие ничего, кроме изменения чего-либо вне их)
  • функции с побочными эффектами: методы, возвращающие значение и изменяющие что-то

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

Ответ 13

Я нашел определение ссылочной прозрачности в книге " Структура и реализация компьютерных программ " (книга мастеров) полезным, потому что оно дополняется объяснением того, как ссылочная прозрачность нарушается введением операции присваивания. Проверьте следующую слайд-колоду, которую я сделал по этому вопросу: https://www.slideshare.net/pjschwarz/introduction-assignment-invalidates-the-substitution-model-of-evaluation-and-violates-referential-transparency-as- объяснены в-SICP-на-мастер-книги

Ответ 14

Ссылочная прозрачность может быть просто сформулирована как:

  • Выражение, всегда оценивающее один и тот же результат в любом контексте [1],
  • Функция, если заданы одни и те же параметры дважды, должна давать один и тот же результат дважды [2].

Например, язык программирования Haskell является чисто функциональным языком; Это означает, что он является прозрачным.