Вам известны примеры элегантных решений в динамически типизированных языках?
Представьте себе два языка, которые (помимо информации о типе) имеют абсолютно одинаковый синтаксис, но один статически типизирован, а другой использует динамическую типизацию. Затем для каждой программы, написанной на языке со статической типизацией, можно получить эквивалентную программу с динамической типизацией, удалив всю информацию о типах. Поскольку это не всегда возможно, наоборот, класс программ с динамической типизацией, таким образом, строго больше, чем класс программ с статической типизацией. Давайте назовем это динамически типизированными программами, для которых нет преобразования переменных в типы, что делает их статически типизированными " реальными динамически типизированными программами".
Поскольку оба языковых семейства являются определенно тьюринг-полными, мы можем быть уверены, что для каждой такой реальной динамически типизированной программы существует статически типизированная программа, выполняющая одно и то же, но я часто читаю, что "опытные программисты могут писать очень элегантный код в динамически типизированные языки ". Поэтому я спрашиваю себя: есть ли хорошие примеры реальных программ с динамической типизацией, для которых любая эквивалентная программа с статической типизацией явно намного сложнее / гораздо менее "элегантна" (что бы это ни значило)?
Знаете ли вы о таких примерах?
3 ответа
Я уверен, что во многих проблемах "элегантности" статических языков не виновата сама статическая проверка типов, но существует недостаток выразительности системы статических типов, реализованной в языке, и ограниченные возможности компилятора. Если это сделано "правильно" (как, например, в Haskell), то программы внезапно оказываются краткими, элегантными… и более безопасными, чем их динамический аналог.
Вот иллюстрация (специфическая для C++, извините): C++ настолько мощен, что в нем реализован метаязык с системой шаблонных классов. Но все же, очень простую функцию трудно объявить:
template<class X,class Y>
? max(X x, Y y)
Существует огромное количество возможных решений, как?=boost::variant<X,Y>
или вычисления?=is_convertible(X,Y)?(X:is_convertible(Y,X):Y:error)
, ни один из них действительно не удовлетворяет.
Но теперь представьте себе препроцессор, который может преобразовать входную программу в ее эквивалентную форму передачи стиля продолжения, где каждое продолжение является вызываемым объектом, который принимает все возможные типы аргументов. CPS-версия max будет выглядеть так:
template<class X, class Y, class C>
void cps_max(X x, Y y, C cont) // cont is a object which can be called with X or Y
{
if (x>y) cont(x); else cont(y);
}
Проблема исчезла, max вызывает продолжение, которое принимает X или Y. Итак, есть решение для max со статической проверкой типа, но мы не можем выразить max в форме, отличной от CPS, untransform(cps_max)
не определено, так сказать. Итак, у нас есть некоторые аргументы max
может быть сделано правильно, но у нас нет средств для этого. Это недостаток выразительности.
Обновление для 2501: предположим, что есть несколько не связанных между собой типов X и Y, и есть bool operator<(X,Y)
, Что должноmax(X,Y)
вернуть? Давайте далее предположим, что X и Y оба имеют функцию-член foo();
, Как мы могли бы сделать возможным написать:
void f(X x, Y y) {
max(X,Y).foo();
}
возврат X или Y и вызов foo() для результата не являются проблемой для динамического языка, но почти невозможны для большинства статических языков. Однако мы можем получить намеченную функциональность, переписав f() для использования cps_max:
struct call_foo { template<class T> void operator(const T &t) const { t.foo(); } };
void f(X x, Y y) {
cps_max(x,y,call_foo());
}
Так что это не может быть проблемой для статической проверки типов, но это выглядит очень некрасиво и не выходит за рамки простых примеров. Итак, чего не хватает в этом статическом языке, что мы не можем предоставить статичное и удобочитаемое решение.
Да, ознакомьтесь с историей успеха Эрика Рэймонда Питона. По сути, речь идет о том, насколько проще задачи типа отражения с динамически типизированными языками программирования.