Это перевод ответа Алана Кея на вопрос "Why is functional programming seen as the opposite of OOP rather than an addition to it?" на Quora.
В конце 50х Джон МакКарти стал всё сильнее интересоваться штукой, которую называл «Искуственный Интеллект». Он также занимался консалтингом, и благодаря этому он познакомился с SAGE air defense system: большой системой огромных компьютеров, подключенных к радарным станциям и соединенных между собой. У них был графический дисплей с указательным устройством.
Реакция Джона была «Такая штука будет в каждом американском доме». Он понял, что сеть компьютеров — это по сути «информационная коммунальная услуга» (как вода, газ и т.д.)., и что домашние терминалы могут предоставлять разные виды «информационных услуг». Эти идеи, наряду с другими, помогли ему убедить MIT делать “time-sharing” их больших машин.
Он также понял, что компьютерный мир 50х годов — машинный код и новый Фортран — не особо вязался с «обычными людьми в американских домах». Это заставило его написать научную работу в 1958 — “Programs With Common Sense” («Программы со здравым смыслом»), и предложить, что для пользовательского интерфейса необходим активный полу-интеллектуальный агент — “Advice Taker” — который бы взаимодействовал с пользователями на понятном им языке, мог учиться, получая советы, мог решать проблемы от лица пользователей и от своего лица, и так далее (MIT AI Memo 17).
Он задумался, как реализовать такого агента, главными механизмами которого были бы различные логические обобщения, включая те, что требуют действий. В то время потенциальных действий было немного. Среди них, например, «обработка списков» (“list processing”). Так что он решил изобрести язык, который бы использовался для создания агента Advice Taker (и других видов роботов). В более общем смысле, язык позволил бы выполнять символические вычисления наряду с уже существующими тогда численными операциями.
Джон был отличным математиком и логиком, и он хотел придумать «математическую теорию вычислимости» (“A Mathematical Theory of Computation”) чтобы хорошо скрепить старые и новые идеи.
Результатом стал LISP (“LISt Processing”). Я писал о его важности в других местах.
В то же время он думал о том, какие виды логики, математики и программирования (он считал их сильно связанными) могут быть использованы для робота в реальном мире.
Опуская детали: проблема была в at (robot, philadelphia) и at (robot, new york) — это не могло работать одновременно, но могло случиться «со временем». Это похоже на проблему современных языков программирования, где переменные могут быть перезаписаны (а иногда даже файлы). Грубо говоря, внося в контекст процессора понятие «время».
Деструктивные вычисления допускают состояние гонки (race conditions) и делают сложными рассуждения о коде и логике. Джон начал думать о модальной логике, но потом понял, что простое сохранение истории изменений и индексации их с помощью «псевдо-времени» (где «факты» сохраняют значения) может позволить функциональному и логическому вычислению работать. Все факты, являющиеся истинными в определенное время он назвал «ситуациями» — некое подобие «слоя», разрезающего мировые линии и истории. (McCarthy “Situations, Actions, and Causal Laws” Stanford, 1963 prompted by Marvin Minsky for “Symbolic Information Processing”)
Один из способов совладать с этой схемой: «логическое время» просто включается в ситуации, а «время процессора» (cpu time) не будет учитываться в вычислениях.
Опуская детали: эта идея не умерла, но и не попала в стандарты вычислительных систем того времени, и даже сегодняшнего дня. Актуальная на тот момент идея была такой: процессор работает как хочет и старается защититься семафорами и т.д. (У этого подхода есть проблемы с блокировкой системы и др., но этот слабый стиль все еще является основным сегодня).
Системы, которые частично или полностью использовали идеи Джона это Strachey’s CPL, Lucid, Simula и другие. Также взгляните на Dave Jefferson’s TimeWarp schemes, Reed’s NetOS, Lamport’s Paxos, the Croquet system и др.
Например, возьмем Strachey. В начале 60х они поняли, что хвостовая рекурсия в Lisp равносильна «циклу с одним одновременным функциональным присвоением». И такая реализация будет намного чище: вычисление следующих значений можно делать за раз.
Состояние гонки невозможно, так как правые части присвоений вычисляются используя старые значения переменных, и само присвоение делается чтобы предоставить новые значения для переменных за раз. (Циклические повторения и присвоения могут быть чистыми если поддерживать отдельные «временные зоны», и т.д.).
Большие системы использовали версии вместо перезаписи и атомарные транзакции чтобы избежать состояния гонки.
Вернёмся к МакКарти и — теперь — к объектам. Мы в Parc поняли, что реализовать максимум идей Джона вроде “situations” и “fluents” — это хорошая идея. Даже если истории не будут храниться очень долго.
К примеру, это позволит «реальным объектам» быть мировыми линиями их стабильных состояний, и они смогут дойти до своего следующего состояния в полностью функциональном стиле. Терминами Strachey, они будут «видеть себя» без состояния гонки на пути к следующей своей версии.
Это также было бы полезным для множественных представлений, которые мы начали использовать. Представления можно разрешать только для стабильных объектов (/взаимоотношений), и этого можно добиться, ограничивая представления только уже высчитанными «ситуационными слоями».
В Parc экспериментировали с “UNDO”, и сообщество специалистов стало задумываться о “parallel possible worlds reasoning”.
Само программирование желало быть выраженным в терминах «историй и версий», и системы должны были иметь возможность откатываться к предыдущих версиям (включая значения, не только код).
Это была еще одна из причин работать над "deep John" в будущих системах. То есть делать все через мировые линии и «симулированное время». Недавняя публикация Алекса Уарта демонстрирует насколько детальными могут бытб «миры» http://www.vpri.org/pdf/tr2011001_final_worlds.pdf.
Последняя мысль: “Histories R US”. То есть нам нужно и движение во времени для большинства наших идей, и одновременно с этим мы хотим видеть как каждая деталь оказалась в том состоянии, в котором оказалась (и как двигаться дальше).
Джон МакКарти показал нам как сделать это 60 лет назад и записал это чтобы мы все могли прочитать и понять.
Итак: и ООП и функциональное программирование могут быть полностью совместимыми (и должны быть!). Нет никаких причин закапывать состояние в объектах, и нет причин изобретать «монады» в ФП. Нам лишь нужно понять, что «компьютеры — это симуляторы» и разобраться, что же симулировать.
Я буду выступать по этой теме в Июле в Амстердаме на конференции “CurryOn”.
— Алан Кей