Я завжди розглядав це скоріше як зручність, ніж про те, чи можна алгоритм виражати чи взагалі не можна. Якби я дуже хотів запускати такі програми, як надумана Мітчелла, я просто напишу відповідний симулятор машини Тьюрінга на моїй статично набраній мові.
Трюк із системою статичного типу полягає в тому, щоб запропонувати правильні види гнучкості лише для тих випадків, коли гнучкість дозволяє вам писати код, який легше піддається догляду.
Ось кілька прикладів методів структурування програм, якими іноді вважається, що їх легше керувати динамічно, ніж мови, які мають статичний тип.
Дженерики та контейнери
Статично типізованими мовами до ML (c. 1973) та CLU (c. 1974) було важко створити червоно-чорне дерево струн, червоно-чорне дерево цілих чисел, червоно-чорне дерево плавців або червоно-чорне дерево елементів конкретного типу Foo
. Однак було важко (можливо, неможливо) створити єдину реалізацію червоно-чорного дерева, яке було статистично перевірено і яке могло б обробляти будь-який із цих типів даних. Шляхи вирішення проблеми полягали в тому, щоб (1) повністю вийти з системи типу (наприклад: за допомогоюvoid *
в C), (2) написати собі якийсь макропрепроцесор, а потім записати макроси, які створюють код для кожного конкретного типу, який ви хочете, або (3) використовувати підхід Lisp / Smalltalk (і Java) для перевірки типу видобутого об'єкт динамічно.
ML та CLU запровадили поняття відповідно виведених та явно оголошених (статичних) параметрів, що параметризуються, що дозволяють писати загальні, статично типові типи контейнерів.
Підтип поліморфізму
У статично типових мовах до Simula67 (c. 1967) та Hope (c. 1977) не вдалося як зробити динамічну розсилку, так і статично перевірити, чи охоплювали ви справу для кожного підтипу. Багато мови мали деяку форму мічених спілок , але це було обов'язком програміста , щоб переконатися , що їх case
або switch
заяви, або їх таблиці стрибати, усі позакривали можливий тег.
Мови, що слідують за моделлю Simula (C ++, Java, C #, Eiffel), надають абстрактні класи з підкласом, де компілятор може перевірити, чи кожен підклас реалізував усі методи, оголошені батьківським класом. Мови, що слідують за моделлю Hope (всі варіанти ML, від SML / NJ до Haskell), мають алгебраїчні підтипи, де компілятор може перевірити, що кожне typecase
твердження охоплює всі підтипи.
Виправлення мавп та орієнтоване на аспекти програмування
Системи динамічного типу значно спрощують різні методи прототипування. У мовах, де типи представлені хеш-картами від рядків до функцій (наприклад, Python, Javascript, Ruby), досить просто глобально змінити поведінку кожного модуля, який спирається на певний тип, просто динамічно змінюючи хеш-карту, що представляє це тип.
Хоча існують очевидні способи, за допомогою яких виправлення мавп можна використовувати, щоб зробити програми важче підтримувати, але існують також способи, якими він може бути використаний для "добра", а не для "зла". Зокрема, в аспектно-орієнтованому програмуванні можна використовувати подібні методи виправлення мавп, щоб зробити такі речі, як змінити тип файлу, щоб вказати на віртуалізовану файлову систему, дозволяючи будувати інфраструктури для тестування одиниць для "вільних" або змінювати прості типи виключень, щоб вони друкувати повідомлення журналу щоразу, коли вони потрапляють для кращої налагодження.
На відміну від генерики та підтипу поліморфізму, де ключові ідеї статичної перевірки були доступні у 1970-х, статична перевірка аспектно-орієнтованого програмування є (я думаю) активною дослідницькою сферою. Я мало що про це знаю, за винятком того, що з 2001 року існує мова під назвою AspectJ .