Чому деякі мови програмування повні, але їм не вистачає здібностей інших мов?


42

Я натрапив на дивну проблему, коли писав інтерпретатор, який (повинен) підключати до зовнішніх програм / функцій: Функції в "C" і "C ++" не можуть підключити різні функції , наприклад, я не можу зробити функцію, яка викликає "printf" з точно такими ж аргументами, які він отримав, і замість цього повинен викликати альтернативну версію, яка приймає варіативний об'єкт. Це дуже проблематично, оскільки я хочу вміти зробити об’єкт, який містить анонімний гачок.

Отже, я подумав, що це дивно, оскільки Forth , JavaScript і, можливо, безліч інших мов можуть зробити це дуже легко, не вдаючись до мови асемблери / машинного коду. Оскільки інші мови можуть зробити це настільки легко, чи це означає, що клас проблем, який може вирішити кожна мова програмування, насправді змінюється залежно від мови, хоча ці мови є Тюрінгом завершеними ?


33
Ви повинні роздивитись тарінгів . Вони є захоплюючим типом мови програмування, який навмисно має якнайменше операцій, наскільки це можливо, поки все ще завершується. У більшості з них відсутні базові типи даних, функції, навіть прості речі, такі як оголошення змінних. Особисто я вважаю, що кодування в них - це дуже приємно, оскільки воно вимушує вас зі своєї зони комфорту спробувати щось непотрібне.
DJMcMayhem

8
Подивіться, що робить машина Тьюрінга, і ви побачите, що "Turing-complete" - це дуже низьке перешкода для очищення. По суті, все, що може "читати", "писати" та "стрибати", підтримуючи основні арифметики, є повним Тьюрінгом. Це значно нижче рівня мовних особливостей, які ви дивитесь.
aroth

2
Щоб бути ще смішнішим: інструкція MOV на процесорі x86 є завершеною Тьюрінгом. Для детальної інформації див. Cl.cam.ac.uk/~sd601/papers/mov.pdf .
Гарет Маккоган

3
Навіть картка гри Magic: The Gathering - цілковита. Тюрінг-повнота майже не має нічого спільного з особливостями мови.
Щогла

2
До речі, існують також дуже складні мови програмування, які не закінчуються, як, наприклад, ті перевірки.
盛安安

Відповіді:


68

Тюрінг повних мов може обчислити той самий набір функцій , який є набором загальних рекурсивних часткових функцій. Це воно.NkN

Це нічого не говорить про мовні особливості. Машина Тьюрінга має дуже обмежені композиційні особливості. Нетипізовані -ісчісленія набагато більш композиційно, але не вистачає багатьох функцій зазвичай зустрічаються в сучасних мовах.λ

Повнота Тюрінга нічого не говорить про наявність типів, вбудованих у масиви / цілі числа / словники, можливості введення / виводу, доступ до мережі, багатопотоковість, динамічне розподілення, ...

Тільки тому, що у Java немає функції X (скажімо, макроси, типи вищого рангу чи залежні типи), вона не раптом перестає бути завершеною Turing.

Тюрінг повноти та мовної виразності - це два різних поняття.


42
Едвін Брейді, дизайнер Ідріса, (лише половина) жартома використовує (не знаю, чи він його винайшов) терміном "Тетріс-повний", щоб виразити цю різницю між "може обчислити будь-яку обчислювальну функцію на натуральних числах" і "може використовувати для написання нетривіальних програм, які взаємодіють із середовищем ".
Йорг W Міттаг

12
Ви також можете згадати, що ви могли мати ці речі в C / C ++. Вам просто доведеться написати якийсь код, який виступає компілятором у C / C ++ для іншої мови, яка містить їх, коли ваш код збирає рядок у код C / C ++. Тоді ви можете просто програмувати щось на зразок Java у вашому файлі C. Це все було б багато роботи, але це можливо (можливо, тому що C / C ++ є Turing завершеним).
Shufflepants

4
@Shufflepants Мені цікаво, чи дійсно корисно сказати "Я можу це зробити на C ++, оскільки можу інтерпретувати іншу мову". За цим ознакою Java, ML, C ++ еквівалентні. TM з оракул для системних дзвінків (I / O) також еквівалентні. Я побоююся, що, виходячи з цього міркування, практично всі мови однаково виразні. Якщо так, то порівняння мов не є корисним поняттям.
чі

9
@chi Ви праві, вони рівноцінні. Ось що означає бути Тьюрінгом завершеним. Все, що можна зробити з однією системою Turing Complete, можна зробити в іншій системі Turing Complete. Це може бути не зручно робити в певній системі. А зручність робити різні речі - це основний спосіб порівняння різних мов програмування. Але це не те питання.
Shufflepants

5
@Rhymoid Якщо з причини доступу до пам'яті C не закінчується Turing, або через те, що можливість надсилати довільні сигнали на підключений пристрій, який має довільно великий обсяг пам’яті, не можна вважати, що жодна реальна світова мова чи пристрій не закінчується. . Але я не відчуваю, що це дуже продуктивна лінія міркувань.
Shufflepants

47

Тюрінг повноти - це абстрактне поняття обчислюваності. Якщо мова Тюрінга є повною, вона може робити будь-які обчислення, які може зробити будь-яка інша мова Тюрінга.

Однак це не говорить про те, наскільки зручно це робити. Деякі функції, які є легкими для деяких мов, можуть бути дуже складними в інших, через вибір дизайну. Тюрінг повноти просто говорить про те, що ви можете робити обчислення. Як крайній приклад, може бути важко підключити варадієві функції в C ++, але можливо написати інтерпретатор JavaScript в C ++, який може підключити різні варіанти.

Мовний дизайн - це досить цікаве мистецтво. Один з головних кроків, який потрібно зробити, - це визначити, які форми поведінки ви хочете сформувати основу вашої мови. Це поведінка, яку легко зробити вашою мовою, оскільки вони вбудовані в перший поверх. Ми приймаємо дизайнерські рішення щодо того, які функції потрібно включити до кожної мови.

Що стосується вашого конкретного прикладу, коли C розроблявся, він був розроблений так, щоб він працював дуже близько до того, як діяли мови монтажу дня. Різноманітні функції просто висували аргументи на стек з дуже малою безпекою. Реалізація цих різноманітних функцій була залишена компілятору, щоб забезпечити максимальну мобільність. Відповідно, мало можливо припущень щодо можливостей обладнання. До часу появи JavaScript JavaScript сцена змінилася. Він вже працює у віртуальній машині як інтерпретована мова, тому баланс зміщується до зручності. Дозвільне підключення різноманітних функцій стає розумним. Навіть у випадку JavaScript, який складається як раз в часі, наші компілятори готові зберігати набагато більше додаткової інформації про аргументи, ніж компілятори C, які були готові зберігати.


1
@Wildcard Я вважав би (практично) всі компілятори як невідомі Wrt. Більшість мов є повними Тьюрінгом, але з часом їх потрібно інтерпретувати / складати до складання, що ні. Але це необхідне фізичне обмеження - апаратне забезпечення ніколи не є Тьюрінгом потужним. Тим не менш, обчислюваність пропонує безліч корисних концепцій, які "застосовуються" в практичному розумінні для комп'ютерів реального світу.
чі

3
@Wildcard У тому тривіальному сенсі. Асамблея (і С) має покажчики фіксованого розміру, які можуть адресувати лише обмежений об'єм пам'яті. Теоретично ми могли б визначити збірку, де покажчики не є необмеженими природними елементами, але я б більше не називав це "збіркою" - я б назвав цю URM чи щось подібне. На практиці ми просто робимо вигляд, що фізичні межі є досить великими, щоб наші програми могли працювати, тому навіть якщо комп'ютер є лише машиною з кінцевим станом (маючи на увазі, що він не може, наприклад, виконувати додавання), ми більше думаємо про це як про машину Тьюрінга ( тому доповнення можливо).
чі

4
@chi Це не зовсім точно. По-перше, практично кожен вважає, що С є Тюрінгом завершеним, оскільки ми зазвичай присвоюємо це словосполучення навколо припущення, що "у вас достатньо пам'яті". Для дуже малої кількості людей, яким доводиться турбуватися про більш суворі формулювання, коли такі припущення є недійсними, C не визначає розмір вказівника та не визначає обмеження на те, скільки пам’яті може бути адресовано. Тож навіть в абсолютно суворому сенсі "Тьюрінг завершений" С справді є Тьюрінгом завершеним.
Корт Аммон

3
@CortAmmon Я не погоджуюся. Якби ми формалізували семантику C, намагаючись вбудувати припущення про "достатню пам'ять", ми б провалились, оскільки sizeof(void *)маємо право оцінювати щось за стандартом ISO C. Це змушує нас обмежувати об'єм пам'яті для будь-якої програми, чимось великим - але все-таки обмеженим. Наприклад, я не можу написати програму, семантика якої - додавання двох довільних натуралів. C може все-таки зробити Turing потужним через введення-виведення, використовуючи файли, такі як стрічки TM (як @Hurkyl вказано вище). Я згоден з тим, що це на практиці не питання.
чі

7
Я пропоную нову мову C-inf, яка точно схожа на C, за винятком випадків, коли занадто багато пам'яті виділяється за допомогою рекурсії або розподілу купи, програма переривається, перекомпілюється з більшим значенням для sizeof (void *) і sizeof (size_t), і починає працювати знову з самого початку.
gnasher729

26

Подумайте про мови програмування як про різні наземні транспортні засоби: велосипеди, автомобілі, ховеркари, поїзди.

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

Але ця заява нічого не говорить про те, як ти туди потрапиш. Це може бути на рейках, може бути на дорогах, може бути в повітрі. Таким же чином Turing завершеність нічого не говорить про те, як ви обчислюєте функцію. Ви можете використовувати рекурсію, ітерацію або якісь дивні стільникові автомати. Ви можете використовувати типи чи ні, ви можете використовувати динамічні чи статичні методи. Але якщо все, що ви вважаєте, це функції (або набори / формальні мови), ви можете обчислити, поки ви Turing Complete, ці функції дають вам однакову потужність.


4
Це чудова аналогія. Це також добре поширюється на питання, яке я бачив в іншому місці на цьому сайті, про те, чи можуть існувати інші моделі обчислень, які перевершують машину Тьюрінга: У цій аналогії літаки та космічні кораблі більше, ніж Тьюрінг завершений, а катери - це інша тип машини цілком. :)
Wildcard

2
Швидше, ніж легке подорож, мабуть, краща аналогія для обчислень супер-Тьюрінга. Це може бути можливо, але більшість людей думають , що це не так .
jmite

@jmite Звичайно, до сих пір немає хороших доказів, які б припускали, що наші мізки є супер-твердими комп'ютерами. Наша (явна) нездатність розглянути нестабільні машини може випливати з цього, хоча це не обов'язково є непереборним бар'єром. Літаки насправді є досить хорошою аналогією - вони просто ходять "прямо" між двома точками, ігноруючи місцевість. Якби ми могли ігнорувати саму топологію простору часу, ми також могли б літати швидше, ніж світло. Не те, що я кажу, що можна ігнорувати топологію космічного часу, пам'ятайте :)
Луань

1
@Luaan Правильно, але нашому мозку не обов'язково потрібно бути супер-Тюрінгом, щоб зрозуміти супер-Тьюрінг-комп’ютер. Я можу описати семантику машини Тюрінга за допомогою більш слабкої мови, що закінчується, наприклад, просто набраний обчислення лямбда, написавши функцію, яка приймає ТМ та його стан, і переходити до наступного стану. Я фактично не можу запустити машину цією мовою (бо це може зайняти нескінченні кроки), але я можу написати, як виглядає кожен крок.
jmite

Чи не @Luaan, «є ще не гарне доказ того, щоб запропонувати наш мозок супер-Тьюринга комп'ютери» -Можливо, але немає також ніяких підстав вважати , що людський розум тільки машина Тьюринга. Оскільки немає машини Тюрінга, яку можна було б вказувати на будь-яке місце, яке не можна простежити за ідеями, зародженими людським розумом, - все ж існує відмінність того, що життя може зароджувати ідеї, а механічне сприяння не може. Що ж стосується моделей обчислень, я думаю, що машини Тьюрінга успішно охоплюють все, що можна було б обґрунтовано назвати "обчислення", ідеї та мрії та таке, незважаючи на це.
Wildcard

17

Те, що ви, по суті, запитуєте, - це різниця між обчислювальною потужністю і тим, що зазвичай називають виражаючою силою (або просто виразністю ) мови (або системою обчислення).

Обчислювальна потужність

Обчислювальна потужність ставиться до того , які проблеми мови можна обчислити. Найвідоміший клас обчислювальної потужності - це той, що еквівалентний Універсальній машині Тьюрінга . Є багато інших систем обчислень, таких як Random Access машини , l-числення , SK комбінатора обчислення , М-рекурсивної функції , WHILEпрограми та багато іншого. І як виявляється, всі вони можуть імітувати один одного, а це означає, що всі вони мають однакову обчислювальну силу.

Це породжує тезу Церкви Тюрінга (названа на честь Церкви Алонцо, яка створила λ-числення, та Алана Тьюрінга, який створив Універсальну машину Тюрінга). Теза Церкви-Тьюрінга - це гіпотеза про обчислюваність з двох аспектів:

  1. всі обчислювальні системи, здатні до загальних обчислень, однаково потужні;
  2. людина, що дотримується алгоритму, може обчислити саме ті функції, які може обчислити машина Тьюрінга (і, отже, будь-яка з інших систем).

Однак друге важливіше в галузі філософії розуму, ніж інформатика.

Тим НЕ менше, є дві речі , Черча-Тьюринга-Thesis НЕ кажуть, що мають безпосередній стосунок до вашого запитання:

  1. наскільки ефективними є різні симуляції та
  2. наскільки зручним є кодування проблеми.

Простий приклад для (1): на машині з випадковим доступом копіювання масиву вимагає часу, пропорційного довжині масиву. На машині Тьюрінга, однак, потрібен час, пропорційний квадрату довжини масиву, оскільки машина Тьюрінга не має доступу до оперативної пам'яті, вона може переміщатися по стрічці по одній осередку за часом. Тому для їх копіювання потрібно перемістити по n елементів масиву n разів. Отже, різні моделі обчислень можуть мати різні характеристики продуктивності, навіть в асимптотичному випадку, де ми намагаємось абстрагуватися від деталей реалізації.

Прикладів для (2) є багато: і λ-обчислення, і Python є повним Тьюрінгом. Але чи бажаєте ви написати програму на Python чи на λ-обчисленні?

Є ще третя зморшка, яку я до цього часу обійшов: усі ці оригінальні системи були розроблені логіками, філософами або математиками, а не комп'ютерними науковцями ... просто тому, що комп'ютерів і, таким чином, інформатики не існувало. Всі вони йдуть назад до початку 1930 - х років, ще до Конрада Цузе «S дуже перші експерименти (що не були програмованими і / або Тьюрингу в будь-якому випадку). Вони говорять лише про "обчислювані функції на натуральних числах".

Зараз, як виявляється, є багато чого можна виразити як функції на натуральних числах - адже наші сучасні комп’ютери навіть обходять набагато менше, ніж це (в основному 3-4 функції на числах 0 і 1, і це все ), але, наприклад, яку функцію обчислює операційна система?

Це поняття вводу / виводу, побічних ефектів, взаємодіючих з навколишнім середовищем, не охоплює ідея "функції над натуральними числами". І все-таки, це наче важливо, оскільки, як одного разу сказав Саймон Пейтон Джонс "Вся чиста функція без побічних ефектів, це зробити ваш процесор гарячим" , на що учасник аудиторії відповів "насправді, це сторона -ефект теж! "

Едвін Брейді , дизайнер Ідріса , (лише половина) жартома використовує (не знаю, чи він його винайшов) терміном "Тетріс-повний", щоб виразити цю різницю між "може обчислити будь-яку обчислювальну функцію на натуральних числах" і "може використовувати для написання нетривіальних програм, які взаємодіють із середовищем ". Ще іронічніше він демонструє це, здійснюючи клон космічних загарбників в Ідрісі , але він говорить, що впевнений, що Тетріс зводиться до космічних загарбників.

Ще одна річ , щоб вказати на те , що не тільки є Тьюринг-еквівалентність не обов'язково достатньо , щоб говорити про фактично писати «корисні» програми, вона може OTOH також навіть не бути necesssary . Наприклад, SQL став еквівалентом Тьюрінга лише ANSI SQL: 1999 , але до цього він був корисний. Насправді, деякі можуть стверджувати, що створення Тьюрінга-еквівалента зовсім не додало його корисності. Існує багато мов, орієнтованих на домен, які не є еквівалентними Тьюрінгу. Мова опису даних зазвичай не є (і не повинна бути). Загальні мови, очевидно, не можуть бути еквівалентними Тьюрінгу, але ви все одно можете писати в них петлі подій, веб-сервери чи операційні системи. Є також мови, які є еквівалентом Тьюрінга, але там, де це насправді вважається помилкою.

Отже, загалом, еквівалентність Тьюрінга не є надзвичайно цікавою, якщо ви не хочете статично аналізувати програми.

Виразність

Якщо припустити, що наша обчислювальна система є достатньо потужною для обчислень, щоб навіть взагалі вирішити нашу проблему, що ми маємо зробити далі, - це висловити наш алгоритм вирішення цієї проблеми в якомусь формальному позначенні для цієї системи. Іншими словами: нам потрібно написати програму якоюсь комп'ютерною мовою. Ось тут і входить поняття виразності .

Це, по суті, стосується того, як "легко" або "приємно" писати нашу програму на нашій конкретній мові програмування. Як бачите, поняття досить розпливчасте, суб'єктивне та більше психологічне, ніж технічне.

Однак є спроби більш точних визначень. Найвідоміший (і найсуворіший із мене, про який я знаю) - Маттіас Феллейзен у своїй роботі « Про виразну силу мов програмування (перші дві сторінки містять ніжне вступ, решта статті - м'ясніша»).

Основна інтуїція така: під час перекладу програми з мови на іншу мову деякі зміни, які потрібно внести, містяться локально (наприклад, перетворення FORциклів у WHILEцикли або цикли в умовні GOTOs), а деякі вимагають зміни на глобальну структура програми.

Коли ви можете замінити одну особливість однієї мови на іншу особливість іншої мови лише локальними перетвореннями, тоді, як кажуть, ці особливості не впливають на виражальну силу. Це називається синтаксичним цукром .

З іншого боку, якщо це вимагає зміни глобальної структури програми, тоді, як вважається, мова, яку ви перекладаєте, не може виразити функцію. А мова, з якої ви перекладаєте, вважається більш виразною (стосовно цієї особливості).

Зауважимо, що це дає об'єктивно вимірне визначення виразності. Зауважимо також, що поняття залежить від контексту та є порівняльним. Отже, якщо кожну програму мовою A можна перекласти на мову B лише з локальними змінами, і є принаймні одна програма мовою B, яку не можна перекласти на A лише з локальними змінами, то мова B є строго виразнішою, ніж мова А. Однак більш вірогідний сценарій полягає в тому, що багато програм на обох мовах можна перекладати туди і назад, але є деякі програми на обох мовах, які не можуть бути переведені на іншу. Це означає, що жодна мова не є строго виразнішою за інші, вони просто мають різні особливості, які дозволяють різним чином виражати різні програми.

Це дає формальне визначення того, що означає бути "більш виразним", але воно все ще не фіксує психологічні уявлення, що стоять за явищем. Наприклад, синтаксичний цукор, згідно з цією моделлю, не збільшує виразну силу мови, оскільки його можна перекладати, використовуючи лише локальні зміни. Тим НЕ менше, ми знаємо з досвіду , що наявність FOR, WHILEі IFє, навіть якщо вони просто синтаксичний цукор для умовних GOTOмоделей висловлення нашої наміри легше .

Справа в тому, що різні мови мають різні особливості, які полегшують чи важче виражати різні способи мислення про проблему. І деякі люди можуть знайти один спосіб виразити свої наміри простіше, а інші - іншим способом.

Приклад, який я знайшов у тезі Ruby на StackOverflow: багато користувачів, які слідкують за тегом Ruby, стверджують, що цикли легше зрозуміти, ніж рекурсія, а рекурсія - лише для просунутих функціональних програмістів, а петлі - інтуїтивніші для новачків, але я бачив кілька випадків повний новачок, який інтуїтивно пише такий код:

def rock_paper_scissors
  get_user_input
  determine_outcome
  print_winner
  rock_paper_scissors # start from the top
end

Що зазвичай призводить до того, що кілька людей коментують, що "це не працює" і "вони роблять неправильно", а "правильний шлях" - це:

def rock_paper_scissors
  loop do
    get_user_input
    determine_outcome
    print_winner
  end
end

Отож, очевидно, є люди, для яких рекурсія хвоста є більш природним способом виразити поняття "петління", ніж петлеві конструкції.

Підсумок

Той факт, що дві мови є еквівалентом Тьюрінга, говорить одне і саме одне: те, що вони можуть обчислити той самий набір функцій на натуральних числах, як і машина Тьюрінга. Це воно.

Це нічого не говорить про те, як швидко вони обчислюють ці функції. Це нічого не говорить про простоту вираження цих функцій. І це нічого не говорить про те, що вони ще можуть зробити, окрім обчислювальних функцій на натуральних числах (наприклад, посилання на бібліотеки С, читання вводу від користувача, записування виводу на екран).

чи це означає, що клас проблем, які кожна мова програмування може вирішити фактично, змінюється залежно від мови, навіть якщо ці мови завершені?

Так.

  1. Є проблеми, які не охоплені терміном "Тюрінг-завершений" (який стосується лише обчислювальних функцій на натуральних числах), наприклад, друк на екран. Дві мови можуть бути завершеними Тьюрінгом, але одна може дозволити друк на екрані, а інша - ні.
  2. Навіть якщо обидві мови можуть вирішити однакові проблеми, це нічого не говорить про те, наскільки складне кодування, і як легко виразити це кодування. Наприклад, C може вирішити кожну проблему. Haskell може, просто написавши інтерпретатора Haskell в C ... але для початку вирішити проблему потрібно спочатку написати інтерпретатора Haskell.

7

Усі цільні програми програмування Turing можуть реалізувати один і той же набір алгоритмів. Отже, якщо ви бачите, що якийсь алгоритм дуже важко реалізувати певною мовою, це не означає, що це неможливо.

Пам'ятайте, що мова складається з синтаксису та семантики. Іноді набір слів, що належать до якоїсь мови, не є мінімальним, щоб вважати Тюрінга завершеним, є функції, які полегшують речі (тому їх називають особливостями ). Якщо ви скористаєтеся цими функціями, мова все ще завершиться Тюрінгом.

Деякі з них можуть представляти інтерес:


5

Усі мови, що завершують Тьюрінг, можуть обчислювати однакові речі.

Якщо ви спробуєте реалізувати сучасну мову, ви помітите, що більшість її функцій не додають жодних обчислювальних можливостей. Багато з цих функцій можна звести до більш простих, які вже існують на одній мові.

Ось кілька прикладів:

  • Якщо у вас немає перерахунків, ви можете використовувати цілі числа.
  • Якщо у вас немає буферів, які знають їх розмір, ви можете створити тип, який містить розмір і буфер, який не знає його розміру.
  • Якщо у вас немає перевірки меж буферів, ви можете просто перевіряти індекс кожного разу, коли ви їх використовуєте.
  • Якщо у вас немає варіативних функцій, ви можете створити функцію, яка приймає буфер, який знає його розмір, і читати з цього буфера ту саму інформацію, яку ви отримали з формальних аргументів.
  • Якщо у вас немає операторів, ви можете використовувати функції.
  • Якщо у вас немає типів, які можуть успадковувати один одного, ви можете створювати типи, які містять один одного, і отримувати доступ до них через додатковий рівень непрямості, при цьому підтипізація - це просто перетворення типу рукоятки на весь тип в а ручка до утримуваного типу.
  • Якщо у вас немає делегатів, але у вас є покажчики функцій, ви можете створити тип, що містить референтний об’єкт та покажчик функції.
  • Якщо у вас немає делегатів, але у вас є інтерфейси, ви можете оголосити інтерфейс, який містить єдиний метод з потрібною підписом.
  • Якщо у вас немає загальних типів, ви можете використовувати неполітичні типи, які передбачають лише верхню або нижню межу, яка вас цікавить (і, можливо, виконувати відповідні ролики на місцях використання, щоб підтримувати компілятор).
  • Якщо у вас немає системи лінійного / афінного типу, ви можете просто уникати використання будь-якої змінної більше одного разу.
  • ...і так далі.

Основний мовний дизайн зосереджується на особливостях, які полегшують та зручніше обчислювати речі швидше, розпізнавати наші помилки раніше, програмувати проти невідомих компонентів, робити паралелізм безпечнішим тощо.

Чисто обчислювальні речі були прибиті давно.


4

Існуючі відповіді справедливо вказують на те, що повнота Тюрінга не є хорошим способом порівняння мов. Дійсно, майже всі мови є Тюрінгом завершеними. ("Якщо всі особливі, то ніхто не особливий", як говорили Неймовірні.)

Тим НЕ менше, це можна порівняти виразність мови з математичною точністю. Погляньте на тему « Експресивна сила мов програмування» Felleisen . Приблизно ідея полягає в тому, щоб задати наступне питання: Чи можу я перетворити будь-яку програму мовою A в програму мовою B, внісши лише локальні зміни? Іншими словами, Felleisen надає математично точну форму вашій інтуїції.


2

На додаток до відповідей усіх інших, ось ще одна аналогія.

Для прання одягу потрібні три речі: резервуар, який містить воду, якийсь миючий засіб та механізм перемішування. Це можна було б реалізувати багатьма способами. Водосховище - це все, що містить достатню кількість води (наприклад, ванна, озеро, річка). Механізмом ажітації може бути механічний пристрій, пральна дошка або навіть скеля, об яку б'ють одяг. І миючі засоби також бувають різних форм.

То яка різниця між сучасною комп'ютерною пральною машиною та скелею біля річки?

Він зводиться до трьох речей: ефективність, безпека та зручність. Деякі способи миття використовують менше енергії, менше забруднюють навколишнє середовище, використовують менше води тощо. Деякі способи миття вимагають менш повторюваних ручних заходів (які призводять до травм) або перебування на вулиці в несприятливу погоду. А деякі способи миття не вимагають від людини няні процесу.

Мови програмування Тьюрінга мають загальне призначення, тому вони ставляться перед більш ніж одним завданням. Тим не менш, для даного завдання деякі мови програмування є більш ефективними, зручнішими та безпечнішими (в тому сенсі, що менше може піти не так, коли програма фактично використовується), ніж інші.


2

Інші дали багато хороших відповідей, але вони прямо не згадують жодного застереження, яке колись мене дуже бентежило: цілісність повноти не означає, що мова може виражати довільні обчислювальні функції від її входів до її результатів. Він слабший: повинен існувати певний спосіб представлення домену та діапазону набору обчислюваних функцій як входів та виходів, щоб кожна з цих функцій відображалась у програмі, яка представляє свої входи на відповідні виходи.

Візьмемо, наприклад, мову, що виражає машини Тюрінга. Кожна програма мовою - це машина Тьюрінга.

Тепер розглянемо підмову всіх машин Тьюрінга, які читають і записують лише символи a, b і blank. Це Тьюрінг завершено, але він не може виражати жодної програми, яка, наприклад, виробляє c на всіх входах, тому що він не може записати жодних cs. Він може виражати всі обчислювані функції на входах і виходах, закодованих у вигляді рядків як і bs.

Отже, неправда, що всі мови Тюрінга можуть обчислювати одні й ті ж речі, навіть коли ми обмежуємо їх обчислювальними функціями від їх потенційних входів до їх потенційних результатів. Мова може зажадати певних способів кодувати входи та виходи.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.