Ссылка Date.now прозрачна?
DateTime.Now или Date.now прозрачны для ссылок?
Это одна из спорных тем в статье о функциональном программировании в Qiita.
Прежде всего, мы должны быть очень осторожны, так как слово "прозрачный по ссылкам" является в некотором смысле хитрым словом / концепцией, и в
Что такое ссылочная прозрачность?
Спрашивающий заявляет:
Что означает термин ссылочная прозрачность? Я слышал, что это описывается как "это означает, что вы можете заменить равные равными", но это выглядит как неадекватное объяснение.
Очень типичное объяснение, но идея, которая обычно приводит нас к недоразумению, заключается в следующем: (#2 ответ на вышеупомянутой странице @Brian R. Bondy)
Ссылочная прозрачность, термин, обычно используемый в функциональном программировании, означает, что при наличии функции и входного значения вы всегда будете получать один и тот же результат. То есть в функции не используется внешнее состояние.
Типичные заявления, которые я всегда слышал и считал неправильными, таковы:
На языке программирования Date.now
всегда возвращает другое значение, соответствующее текущему времени, и в соответствии с
учитывая функцию и входное значение, вы всегда получите один и тот же вывод.
следовательно, Date.now
Не ссылочный прозрачный!
Я знаю, что некоторые (функциональные) программисты твердо верят в то, что приведенное выше утверждение заслуживает доверия, однако, ответы № 1 и № 3 @Uday Reddy объясняют следующим образом:
Любой разговор о "ссылочной прозрачности" без понимания различия между L-значениями, R-значениями и другими сложными объектами, которые населяют концептуальную вселенную императивного программиста, в корне ошибочен.
Представление функциональных программистов о ссылочной прозрачности, кажется, отличается от стандартного понятия тремя способами:
В то время как философы / логики используют такие термины, как "ссылка", "обозначение", "designatum" и "bedeutung" (немецкий термин Фреге), функциональные программисты используют термин "значение". (Это не совсем их работа. Я замечаю, что Лэндин, Стрейчи и их потомки также использовали термин "ценность", чтобы говорить об упоминании / обозначении. Это может быть просто терминологическое упрощение, которое представили Ландин и Стрейчи, но, похоже, оно делает большая разница при использовании наивно.)
Функциональные программисты, похоже, считают, что эти "ценности" существуют внутри языка программирования, а не снаружи. При этом они отличаются как от философов, так и от семантиков языка программирования.
Кажется, они считают, что эти "ценности" должны быть получены путем оценки.
Если подумать, "внешнее состояние" - это тоже хитрое слово / понятие.
Ссылочная прозрачность, термин, обычно используемый в функциональном программировании, означает, что при наличии функции и входного значения вы всегда будете получать один и тот же результат. То есть в функции не используется внешнее состояние.
Является ли "текущее время" "внешним состоянием" или "внешним значением"?
Если мы называем "текущее время" "внешним состоянием", как насчет "события мыши"?
"Событие мыши" - это не состояние, которым нужно управлять с помощью контекста программирования, это скорее внешнее событие.
учитывая функцию и входное значение, вы всегда получите один и тот же вывод.
Итак, мы можем понять следующее:
"текущее время" не является ни "входным значением", ни "внешним значением", ни "внешним состоянием" и Date.now
всегда возвращает один и тот же выход, соответствующий текущему событию "текущее время".
Если кто-то все еще настаивает или хочет назвать "текущее время" как "значение", снова
- Функциональные программисты, похоже, считают, что эти "ценности" существуют внутри языка программирования, а не снаружи. При этом они отличаются как от философов, так и от семантиков языка программирования.
Значение "текущего времени" никогда не существует в языке программирования, а только снаружи, и значение "текущего времени" снаружи явно обновляется не в контексте программирования, а в реальном потоке времени.
Поэтому я понимаю, что Date.now прозрачен по ссылкам.
Я хотел бы прочитать вашу идею. Благодарю.
EDIT1
В чем заключается (функциональное) реактивное программирование?
Конал Эллиотт @Conal также объясняет функционально-реактивное программирование (FRP).
Он является одним из первых, кто разработал FRP, и объясняет так:
FRP о - "типы данных, которые представляют значение с течением времени"
Динамические / развивающиеся значения (то есть значения "со временем") сами по себе являются первоклассными значениями.
В этой перспективе FRP,
Date
можно рассматривать как первоклассное значение "со временем", которое является неизменным объектом на оси времени..now
это свойство / функция для адресации "текущее время" в пределахDate
Следовательно
Date.time
возвращает неизменяемое и ссылочное прозрачное значение, которое представляет наше "текущее время".
EDIT2
(в JavaScript)
ссылочная непрозрачная функция
let a = 1;
let f = () => (a);
ввод Function:f
нет ни одного; вывод Function:f
зависит от a
это зависит от контекста вне f
ссылочная прозрачная функция
let t = Date.now();
let f = (Date) => (Date.now());
Хотя, Date
ценность находится в нашем физическом мире, Date
можно рассматривать как неизменное первоклассное значение FRP "со временем".
поскольку Date
Ссылка из любого контекста программирования идентична, мы обычно неявно можем опустить Date
в качестве входного значения и просто как
let f = () => (Date.now());
EDIT3
На самом деле я отправил письмо Коналу Эллиотту @Conal, одному из первых разработчиков FRP. Он любезно ответил и сообщил мне, что здесь есть похожий вопрос.
Как может существовать функция времени в функциональном программировании?
Спрашивающий заявляет:
Поэтому мой вопрос: может ли функция времени (которая возвращает текущее время) существовать в функциональном программировании?
Если да, то как оно может существовать? Не нарушает ли это принцип функционального программирования? Это особенно нарушает ссылочную прозрачность, которая является одним из свойств функционального программирования (если я правильно понимаю).
А если нет, то как узнать текущее время в функциональном программировании?
и ответ Конала Эллиотта @Conal в stackru:
Да, для чистой функции возможно вернуть время, если оно указано в качестве параметра. Другой аргумент времени, другой результат времени. Затем формируйте и другие функции времени и объединяйте их с простым словарем функций (-временных)-преобразующих (высших порядков) функций. Поскольку подход не использует состояние, время здесь может быть непрерывным (не зависящим от разрешения), а не дискретным, что значительно повышает модульность. Эта интуиция является основой функционально-реактивного программирования (FRP).
Edit4 Моя благодарность за ответ @Roman Sausarnes .
Пожалуйста, позвольте мне представить мою точку зрения на функциональное программирование и FRP.
Прежде всего, я думаю, что программирование - это, в основном, математика, а функциональное программирование преследует этот аспект. С другой стороны, императивное программирование - это способ описать этапы работы машины, а это не обязательно математика.
Чистое функциональное программирование, такое как Haskel, испытывает определенные трудности с обработкой "состояния" или ввода-вывода, и я думаю, что вся проблема связана с "временем".
"состояние" или "время" для нас, людей, в значительной степени субъективно. Мы, естественно, верим, что "время" течет или проходит, а "состояние" меняется, то есть наивный реализм.
Я думаю, что наивный реализм "времени" - это фундаментальная опасность и причина всей путаницы в сообществе программистов, и очень немногие обсуждают этот аспект. В современной физике, или даже в физике Ньютона, мы относимся ко времени чисто математическим образом, поэтому, если мы рассматриваем наш мир с точки зрения физики, нет ничего сложного в том, чтобы относиться к нашему миру с помощью чисто математического функционального программирования.
Итак, я рассматриваю наш мир / вселенную неизменным, как предварительно записанный DVD, и только наше субъективное представление изменчиво, включая "время" или "состояние".
В программировании единственной связью между неизменной вселенной и нашим изменчивым субъективным опытом является "событие". Чистый функциональный язык программирования, такой как Haskell, в основном не имеет этого представления, хотя некоторые проницательные исследователи, включая Корнеля Эллиота, продолжают FRP, но большинство все еще думает, что метод FRP все еще незначителен или труден в использовании, и многие из них рассматривают изменяемое состояние как само собой разумеющееся.
Естественно, FRP является единственным разумным решением, и особенно Корнель Эллиотт, как основатель, применил эту философскую точку зрения и объявил - первоклассную ценность "со временем". Возможно, к сожалению, многие программисты не поймут, что он на самом деле имел в виду, так как они пойманы в ловушку Наивного реализма, и им трудно рассматривать "время" как философскую или физически неизменную сущность.
Таким образом, если они обсуждают " чисто функциональный " или " ссылочную прозрачность " в пользу математической целостности / согласованности, для меня "Date.now" естественно ссылочно-прозрачный в чисто функциональном программировании, просто потому, что "Date.time" обращается к определенному точка неизменной временной линии неизменной вселенной.
Так что насчет спекулятивной прозрачности в денотационной семантике, такой как @Reddy или @Roman Sausarnes?
Я рассматриваю ссылочную прозрачность в FP, особенно в сообществе Haskell, это все о математической целостности / согласованности.
Конечно, может быть, я мог бы следовать обновленному определению "ссылочной прозрачности" сообщества Haskell, и практически мы считаем, что код математически несовместим, если мы считаем, что он не является ссылочно-прозрачным, правильным?
На самом деле, опять же,
Как может существовать функция времени в функциональном программировании?
Программист задал следующий вопрос:
Поэтому мой вопрос: может ли функция времени (которая возвращает текущее время) существовать в функциональном программировании?
Если да, то как оно может существовать? Не нарушает ли это принцип функционального программирования? Это особенно нарушает ссылочную прозрачность, которая является одним из свойств функционального программирования (если я правильно понимаю).
А если нет, то как узнать текущее время в функциональном программировании?
консенсус
нарушать принцип функционального программирования
= нарушает ссылочную прозрачность, которая является одним из свойств функционального программирования
= Математически противоречиво!
Это наше общее восприятие, верно?
В этом вопросе многие ответили, что "функция, возвращающая текущее время" не является ссылочно-прозрачной, особенно в определении "ссылочной прозрачности" сообществом Haskell, и многие упоминали, что речь идет о математической согласованности.
Однако лишь немногие ответили, что "функция, возвращающая текущее время" является прозрачной по ссылкам, и один из ответов с точки зрения FRP - Конал Эллиотт @Conal.
IMO, FRP, перспектива для обработки потока времени как первоклассного неизменного значения "во времени" - это правильный подход с математическим принципом, подобным физике, как я упоминал выше.
Тогда почему функция "Date.now"/"возвращающая текущее время" стала ссылочно-непрозрачной в контексте Haskell?
Что ж, единственное объяснение, которое я могу придумать, это то, что обновленное определение "ссылочной прозрачности" сообществом Haskell несколько неверно.
Событийная и математическая целостность / последовательность
Я упомянул - в программировании единственная связь между неизменной вселенной и нашим изменчивым субъективным опытом - это "событие" или "управляемый событиями".
Функциональное программирование оценивается управляемым событиями образом, с другой стороны, императивное программирование оценивается с помощью шагов / процедуры работы машины, описанной в коде.
"Date.now" зависит от "события", и в принципе "событие" неизвестно контексту кода.
Итак, разрушает ли управляемый событиями математическую целостность / последовательность? Точно нет.
Отображение синтаксиса в значение - индексный (указательный палец)
CS Peirce ввел термин "индексный", чтобы предложить идею указания (как в "указательном пальце"). "Я",[[здесь]],[[сейчас]] и т. Д.
Вероятно, это математически идентичное понятие "монад", "функтор" вещей в Хаскеле. В денотационной семантике даже в Хаскеле [[сейчас]] как "указательный палец" ясно.
Индексальный (указательный палец) субъективен, как и Событийный
[[I]],[[здесь]],[[сейчас]] и т. Д. Субъективны, и опять же, в программировании единственная связь между неизменной объективной вселенной и нашим изменчивым субъективным опытом - это "событие" или "событие" управляемое общество"
Поэтому, пока [[сейчас]] привязан к объявлению события "управляемого событиями" программирования, я думаю, что субъективная (зависящая от контекста) математическая несогласованность никогда не возникает.
Edit5
@ Берги дал мне отличный комментарий:
Да,
Date.now
, внешнее значение, является ссылочно прозрачным. Это всегда означает "текущее время".Но
Date.now()
это не так, это вызов функции, возвращающий разные номера в зависимости от внешнего состояния. Проблема с относительно прозрачной "концепцией текущего времени" состоит в том, что мы не можем ничего с ней вычислить.@KenOKABE: похоже, тот же случай, что и
Date.now()
, Проблема в том, что это не означает текущее время в одно и то же время, но в разное время - программе требуется время для выполнения, и это делает ее нечистой.Конечно, мы могли бы разработать референсную прозрачность
Date.now
функция / получатель, которая всегда возвращает время начала программы (как если бы выполнение программы было немедленным), но это не такDate.now()/Date.Now
Работа. Они зависят от состояния выполнения программы. - Берги
Я думаю, что мы должны обсудить это.
Date.now
, внешнее значение, является ссылочно прозрачным.
[[Date.now]], как я упоминаю в #Edit4, является индексным (указательный палец), который является субъективным, но до тех пор, пока он остается в индексной области (без выполнения / оценки), он референтно прозрачен, что мы согласились на.
Тем не менее, @ Берги предлагает Date.now()
(с выполнением / оценкой) возвращает "разные значения" в разное время, и это больше не является ссылочно прозрачным. С этим мы не договорились.
Я думаю, что эта проблема, которую он показал, конечно, но существует только в императивном программировании:
console.log(Date.now()); //some numeric for 2016/05/18 xx:xx:xx ....
console.log(Date.now()); //different numeric for 2016/05/18 xx:xx:xx ....
В этом случае, Date.now()
Я не согласен с этим.
Однако в парадигме функционального программирования / декларативного программирования мы никогда не будем писать так, как описано выше. Мы должны написать это:
const f = () => (Date.now());
и это f
оценивается в каком-то "управляемом событиями" контексте. Вот как ведет себя функционально-программный код.
Да, этот код идентичен
const f = Date.now;
Поэтому в парадигме функционального программирования / декларативного программирования Date.now
или же Date.now()
(с выполнением / оценкой) никогда не возникает проблем с возвратом "разных значений" в разное время.
Итак, опять же, как я упоминал в EDIT4, пока [[сейчас]] привязан к объявлению события "управляемого событиями" программирования, я думаю, что субъективная (зависящая от контекста) математическая несогласованность никогда не возникает, я думаю.
2 ответа
Хорошо, я собираюсь сделать удар в этом. Я не эксперт в этом деле, но я потратил некоторое время на размышления об ответах @UdayReddy на этот вопрос, с которым вы связались, и я думаю, что мне это обернулось.
Ссылочная прозрачность в аналитической философии
Я думаю, вы должны начать с того, что сделал мистер Редди в своем ответе на другой вопрос. Мистер Редди написал:
Термин "референт" используется в аналитической философии, чтобы говорить о том, на что ссылается выражение. Это примерно то же самое, что мы подразумеваем под "значением" или "обозначением" в семантике языка программирования.
Обратите внимание на использование слова "обозначение". Языки программирования имеют синтаксис или грамматику, но они также имеют семантику или значение. Денотационная семантика - это практика перевода синтаксиса языка в его математическое значение.
Насколько я могу судить, денотационная семантика не совсем понятна, хотя это один из самых мощных инструментов для понимания, проектирования и анализа компьютерных программ. Я должен потратить немного времени на это, чтобы заложить основу для ответа на ваш вопрос.
Денотационная семантика: отображение синтаксиса в значение
Идея денотационной семантики заключается в том, что каждый синтаксический элемент в компьютерном языке имеет соответствующий математический смысл или семантику. Денотационная семантика - это явное отображение между синтаксисом и семантикой. Возьмите синтаксическую цифру 1
, Вы можете сопоставить его с математическим значением, которое является просто математическим числом 1
, Семантическая функция может выглядеть так:
syntax
↓
⟦1⟧ ∷ One
↑
semantics
Иногда двойные квадратные скобки используются для обозначения "значения", и в этом случае число 1
на смысловой стороне прописано как One
, Это всего лишь инструменты для указания, когда мы говорим о семантике и когда мы говорим о синтаксисе. Вы можете прочитать эту функцию, чтобы означать, "Значение синтаксического символа 1
это число One
".
Пример, который я использовал выше, выглядит тривиально. Конечно 1
средства One
, Что еще это будет значить? Это не должно, однако. Вы могли бы сделать это:
⟦1⟧ ∷ Four
Это было бы глупо, и никто не использовал бы такой тупой язык, но все равно это был бы действительный язык. Но дело в том, что денотационная семантика позволяет нам быть явным о математическом значении программ, которые мы пишем. Вот обозначение для функции, которая возводит в квадрат целое число x
используя лямбда-нотацию:
⟦square x⟧ ∷ λx → x²
Теперь мы можем двигаться дальше и говорить о ссылочной прозрачности.
Ссылочная прозрачность - это смысл
Позвольте мне повторить ответ мистера Удея снова. Он пишет:
Контекст в предложении является "ссылочно-прозрачным", если замена термина в этом контексте другим термином, относящимся к той же сущности, не меняет смысла.
Сравните это с ответом, который вы получите, когда спросите среднего программиста, что означает ссылочная прозрачность. Они обычно говорят что-то вроде ответа, который вы цитировали выше:
Ссылочная прозрачность, термин, обычно используемый в функциональном программировании, означает, что при наличии функции и входного значения вы всегда будете получать один и тот же результат. То есть в функции не используется внешнее состояние.
Этот ответ определяет ссылочную прозрачность в терминах значений и побочных эффектов, но он полностью игнорирует смысл.
Вот функция, которая согласно второму определению не является ссылочно прозрачной:
var x = 0
func changeX() -> Int {
x += 1
return x
}
Он читает некоторое внешнее состояние, изменяет его, а затем возвращает значение. Он не требует ввода, возвращает новое значение каждый раз, когда вы его вызываете, и зависит от внешнего состояния. Мех. Большое дело
При правильной денотационной семантике она по-прежнему прозрачна по ссылкам.
Зачем? Потому что вы можете заменить его другим выражением с таким же смысловым значением.
Теперь семантика этой функции намного более запутанная. Я не знаю, как это определить. Это как-то связано с преобразованиями состояния, учитывая состояние s
и функция, которая производит новое состояние s'
, обозначение может выглядеть примерно так, хотя я понятия не имею, математически ли это правильно:
⟦changeX⟧ ∷ λs → (s → s')
Это правильно? Я понятия не имею. Стрейчи выяснил смысловую семантику императивных языков, но она сложная, и я пока не понимаю ее. Однако, установив денотативную семантику, он установил, что императивные языки настолько же прозрачны, как и функциональные языки. Зачем? Потому что математический смысл может быть точно описан. И как только вы узнаете точное математическое значение чего-либо, вы можете заменить его любым другим термином, имеющим такое же значение. Так что, хотя я не знаю, какова истинная семантика changeX
Я знаю, что если бы у меня был другой термин с таким же семантическим значением, я мог бы поменять один на другой.
Так что насчет Date.now
?
Я ничего не знаю об этой функции. Я даже не уверен, с какого это языка, хотя подозреваю, что это может быть Javascript. Но кого это волнует. Какова его денотационная семантика? Что это значит? Что бы вы могли вставить на его место, не меняя смысла вашей программы?
Уродливая правда в том, что большинство из нас не имеет ни малейшего понятия! С самого начала денотационная семантика не так широко использовалась, а денотационная семантика императивных языков программирования действительно сложна (по крайней мере, для меня - если вам будет легко, я бы хотел, чтобы вы мне это объяснили). Возьмите любую императивную программу, состоящую из более чем 20 строк нетривиального кода, и скажите мне, каково ее математическое значение. Я бросаю вам вызов.
В отличие от этого денотационная семантика Хаскелла довольно проста. У меня очень мало знаний о Хаскеле. Я никогда не делал никакого кодирования, кроме как возиться с ghci, но что делает его настолько мощным, так это то, что синтаксис отслеживает семантику более тесно, чем любой другой язык, который я знаю. Будучи чистым, строгим функциональным языком, семантика находится прямо на поверхности синтаксиса. Синтаксис определяется математическими понятиями, которые определяют значение.
На самом деле, синтаксис и семантика настолько тесно связаны, что функциональные программисты начали их объединять. (Я смиренно высказываю это мнение и жду ответной реакции.) Вот почему вы получаете определения ссылочной прозрачности от FPers, которые говорят о значениях вместо значения. В языке, подобном Хаскеллу, они почти неразличимы. Поскольку нет изменяемого состояния и каждая функция является чистой функцией, все, что вам нужно сделать, это посмотреть на значение, которое создается при оценке функции, и вы в основном определили ее значение.
Может также случиться так, что объяснение референтной прозрачности в новой версии FPer, в некотором смысле, более полезно, чем то, которое я суммировал выше. И это нельзя игнорировать. В конце концов, если то, что я написал выше, верно, то все, что имеет денотационную семантику, является прозрачным по ссылкам. Нет такой вещи как нереферентно прозрачная функция, потому что каждая функция имеет математическое значение (хотя это может быть неясным и трудным для определения), и вы всегда можете заменить ее другим термином с тем же значением. Что хорошего в этом?
Ну, это хорошо по одной причине. Это дало нам знать, что мы не знаем Джека о математике, стоящей за тем, что мы делаем. Как я уже говорил выше, я понятия не имею, что такое денотационная семантика Date.now
есть или что это значит в математическом смысле. Это референтно прозрачно? Да, я уверен, что это так, поскольку его можно заменить другой функцией с той же семантикой. Но я понятия не имею, как оценивать семантику для этой функции, и поэтому ее ссылочная прозрачность бесполезна для меня как для программиста.
Итак, если есть одна вещь, которую я узнал из всего этого, это гораздо меньше сосредоточиться на том, соответствует ли что-то определению "ссылочной прозрачности", и гораздо больше на попытках сделать программы из маленьких, математически компонуемых. части, которые имеют точные смысловые значения, которые даже я могу понять.
Ссылочно прозрачен?
Вот ссылочно-прозрачный генератор случайных чисел:
...так что если
Date.now
был определен аналогичным образом, например:
int Date.now()
{
return 314159265358979; // think of it as
// a prototype...
}
тогда это также было бы ссылочно прозрачным (но не очень полезным :-).