Lisp-family: как избежать объектно-ориентированного java-мышления? [закрытый]
Предыстория: я сделал много больших и относительно сложных проектов на Java, имею большой опыт в программировании на встроенном языке C. Я познакомился со схемой и синтаксисом CL и написал несколько простых программ с racket.
вопрос: я запланировал довольно большой проект и хочу сделать это в рэкете. Я слышал много "если вы" получите "lisp, вы станете лучшим программистом"и т. д. Но каждый раз, когда я пытаюсь спланировать или написать программу, я все еще "разлагаю" задачу со знакомым объекты состояния с интерфейсами.
Существуют ли "шаблоны дизайна" для lisp? Как "получить" lisp-family "mojo"? Как избежать объектно-ориентированного ограничения на мышление? Как применить идеи функционального программирования, вызванный мощным макро-facitilties? Я попытался изучить исходный код больших проектов на github (например, Light Table) и запутался, а не просветился.
EDIT1 (менее неоднозначные вопросы): есть ли хорошая литература по этой теме, которую вы можете рекомендовать или есть хорошие проекты с открытым исходным кодом, написанные в cl/scheme / clojure, которые имеют высокое качество и могут служить хорошим примером?
3 ответов
несколько "парадигм" приходили в моду над летами: структурированное Программирование, объектно-ориентированное, функциональное и др. Придут другие.
даже после того, как парадигма выходит из моды, она все еще может быть хороша в решении конкретных проблем, которые впервые сделали ее популярной.
Так, например, использование ООП для GUI по-прежнему естественно. (Большинство фреймворков GUI имеют кучу состояний, измененных сообщениями / событиями.)
ракетка мульти-парадигма. Он имеет
способ сравнить программирование в OO vs Lisp (и" функциональное "программирование в целом) - посмотреть, что каждая" парадигма " позволяет программисту.
одна точка зрения в этой линии рассуждений, которая рассматривает представления данных, заключается в том, что стиль OO облегчает расширение представлений данных, но затрудняет добавление операций над данными. Напротив, функциональный стиль упрощает добавление операций, но затрудняет добавление новых данных представления.
конкретно, если есть интерфейс принтера, с OO, очень легко добавить новый класс HPPrinter, который реализует интерфейс, но если вы хотите добавить новый метод к существующему интерфейсу, вы должны отредактировать каждый существующий класс, который реализует интерфейс, что сложнее и может быть невозможно, если определения классов скрыты в библиотеке.
в отличие от функционального стиля, функции (вместо классов) являются единицей кода, таким образом, можно легко добавить новую операцию (просто напишите функцию). Однако каждая функция отвечает за диспетчеризацию в соответствии с типом входных данных, поэтому добавление нового представления данных требует редактирования всех существующих функций, которые работают с такого рода данными.
определение того, какой стиль больше подходит для вашего домена, зависит от того, добавите ли вы представления или операции.
это обобщение высокого уровня, конечно, и каждый стиль имеет разработаны решения для решения упомянутых компромиссов (например, mixins для OO), но я думаю, что это все еще в значительной степени.
вот известная академическая статья это захватило идею 25 лет назад.
вот некоторые заметки из недавнего курса (я учил) описывая ту же философию.
(обратите внимание, что курс отвечает как проектировать программы учебный план, который первоначально подчеркивает функциональный подход, но более поздние переходы к стилю OO.)
edit: конечно, это отвечает только на часть вашего вопроса и не касается (более или менее ортогональной) темы макросов. Для этого я ссылаюсь на отличный учебник Грега Хендершотта.
личное мнение:
Если вы параметризации конструкции объекта в названиях классов и их методов, как это можно делать с шаблонами C++ - тогда вы в конечном итоге с чем-то, что выглядит, как функциональный дизайн. Другими словами, функциональное программирование не делает бесполезных различий между похожими структурами, потому что их части имеют разные имена.
мое воздействие было Clojure, который пытается украсть хороший бит из объекта Программирование
- работа с интерфейсами
отбрасывая хитрые и бесполезные биты
- конкретные наследство
- традиционные данные скрывает.
мнения о том, насколько успешной была эта программа, различаются.
поскольку Clojure выражается в Java (или некотором эквиваленте), не только объекты могут делать то, что могут делать функции, существует регулярное сопоставление от одного к другому.
Так в чем может заключаться функциональное преимущество? Я бы сказал, выразительность. Есть много повторяющихся вещей, которые вы делаете в программах, которые не стоит захватывать в Java - кто использовал lambdas до Javaкомпактный синтаксис для них?