LINUX.ORG.RU

История изменений

Исправление monk, (текущая версия) :

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

Вот этим Racket существенно отличается от Haskell/Rust/Common Lisp. Я когда только перешёл на Racket, воспринимал его как Common Lisp с нормальными модулями и call/cc (любую программу на Common Lisp можно почти 1-в-1 перенести в Racket). Пытался сделать то, чего мне, казалось, не хватало (было привычным из Common Lisp’а): отладчик с произвольными командами, разработку в образе, CLOS на все функции.

Потом понял. Хорошего отладчика нет намеренно. Потому что хороший отладчик поощряет писать программы, работу которых не понимает сам автор. CLOS нет намеренно, потому что произвольное расширение метода легко ломает инварианты, на которые опирается автор метода.

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

Тоже ограничения, хоть и в другой плоскости.

В Common Lisp не так:

(setf (symbol-function +) 
      (let ((old (symbol-function +)))
      (lamda (&rest args) 
        (if (my-cond args) 
            (my-+ args)
            (apply old args))))

именно добавит новую ветку выполнения к системному CL:+.

Ну и в целом, наверное, будет странно, если библиотека будет экспортировать переопределённую «стандартную» функцию?

Для Racket в этом ничего странного. Пакет racket экспортирует функции из racket/base (да, неизменённые). typed/racket экспортирует переопределённые функции и синтаксисы из racket (функции с типами, синтаксис define слегка отличается, …).

Но ни один из этих языков не предоставляет из коробки функции сложения, которые работают именно так.

На C++ это однострочник:

template<typename... Args> auto sum(Args... args) { return (args + ...); }

sum(1, 2, 5);

На python: sum([1, 2, 5]) // ладно, не чистый пример

В остальных, согласен, «не принято». Но никто не мешает написать библиотеку и будет «из коробки». Также как есть CLOS в Racket.

Исходная версия monk, :

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

Вот этим Racket существенно отличается от Haskell/Rust/Common Lisp. Я когда только перешёл на Racket, воспринимал его как Common Lisp с нормальными модулями и call/cc (любую программу на Common Lisp можно почти 1-в-1 перенести в Racket). Пытался сделать то, чего мне, казалось, не хватало (было привычным ид Common Lisp’а): отладчик с произвольными командами, разработку в образе, CLOS на все функции.

Потом понял. Хорошего отладчика нет намеренно. Потому что хороший отладчик поощряет писать программы, работу которых не понимает сам автор. CLOS нет намеренно, потому что произвольное расширение метода легко ломает инварианты, на которые опирается автор метода.

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

Тоже ограничения, хоть и в другой плоскости.

В Common Lisp не так:

(setf (symbol-function +) 
      (let ((old (symbol-function +)))
      (lamda (&rest args) 
        (if (my-cond args) 
            (my-+ args)
            (apply old args))))

именно добавит новую ветку выполнения к системному CL:+.

Ну и в целом, наверное, будет странно, если библиотека будет экспортировать переопределённую «стандартную» функцию?

Для Racket в этом ничего странного. Пакет racket экспортирует функции из racket/base (да, неизменённые). typed/racket экспортирует переопределённые функции и синтаксисы из racket (функции с типами, синтаксис define слегка отличается, …).

Но ни один из этих языков не предоставляет из коробки функции сложения, которые работают именно так.

На C++ это однострочник:

template<typename... Args> auto sum(Args... args) { return (args + ...); }

sum(1, 2, 5);

На python: sum([1, 2, 5]) // ладно, не чистый пример

В остальных, согласен, «не принято». Но никто не мешает написать библиотеку и будет «из коробки». Также как есть CLOS в Racket.