Які імперативні мови програмування не підтримують рекурсію?


21

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

Які мови не підтримували рекурсію з самого початку і коли ця підтримка була додана?

Відповіді:


21

Я не впевнений, що це COBOL (це, звичайно, не було свого часу), але я не можу навіть уявити, щоб хтось так сильно піклувався.

Fortran починає працювати з Fortran 90, але вимагає використовувати recursiveключове слово, щоб сказати, що підпрограма є рекурсивною.

PL / Я був майже однаковий - рекурсію підтримували, але вам довелося чітко сказати, які процедури були рекурсивними.

Я сумніваюся, що є набагато більше, ніж це. Коли ви переходите до цього, заборона рекурсії була в основному тим, що IBM зробив у своїх мовних конструкціях з тієї простої причини, що мейнфрейми IBM (360/370 / 3090 / ...) не підтримують стек в апаратному забезпеченні. Коли більшість мов походить від IBM, вони здебільшого забороняють рекурсію. Тепер, коли всі вони приходять з інших місць, завжди дозволена рекурсія (хоча я мушу додати, що ще кілька інших машин, зокрема оригінальний Cray 1, не мали апаратної підтримки для стека).


Комп'ютери з контрольними даними періоду також не підтримували рекурсію (виклики підпрограми виконувались з інструкцією, яка модифікувала код, щоб вставити перехід до інструкції виклику + 1). Коли Вірт розробив Паскаля на 6600, він, ймовірно, повинен був придумати новий спосіб викликати підпрограми.
Девід Торнлі

@David: так - і не випадково, їх також розробив Сеймур Крей. Одного разу мені довелося подивитися компілятор Pascal 6000, але не пригадую, щоб переглянув, що він зробив для створення (імітації?) Стекових кадрів.
Джеррі Труну

notably the original cray 1Отже, вам не потрібна рекурсія для клонування динозаврів? Я здогадуюсь насправді від нас, мавп, гойдатися по деревах.
нормантхеквід

2
навіть CAML (і OCAML, F #) потребують рекурсивних функцій, явно позначених.
jk.

1
@Panzercrisis: Я не впевнений, чи IBM брав участь у x86, але їхні поточні мейнфрейми простежуються безпосередньо до IBM 360, який з'явився на ринку в 1964 році, тому базовий дизайн передував x86 ще пару десятиліть.
Джеррі Труну

16

У Вікіпедії сказано:

Ранні мови, такі як Fortran, спочатку не підтримували рекурсію, оскільки змінні були розподілені статично, а також місце для повернення адреси.

http://en.wikipedia.org/wiki/Subroutine#Local_variables.2C_recursion_and_re-entrancy

FORTRAN 77 не дозволяє рекурсію, Fortran 90 робить (рекурсивні процедури повинні бути чітко оголошені так).

Більшість компіляторів FORTRAN 77 допускають рекурсію, деякі (наприклад, DEC) вимагають використання параметра компілятора (див. Розділ параметрів компілятора). GNU g77, який суворо відповідає стандарту Fortran 77, взагалі не дозволяє рекурсії.

http://www.ibiblio.org/pub/languages/fortran/ch1-12.html


У iirc був принаймні один компілятор FORTRAN 77, який, хоча технічно підтримував рекурсію, загальна кількість фреймів стека, які ви могли мати, були настільки невеликими рекурсіями, мало ефективно використовувати для багатьох проблем
jk.

6

Мова програмування OpenCL не підтримує рекурсії. (див. розділ 6.8 специфікації OpenCL )

Поточною мотивацією для цього є: відсутність місця для глибоких стеків; b) бажання статично знати загальні необхідні асигнування для оптимізації для продуктивності за наявності великих наборів реєстрів та великої вставки.

Це цілком може стосуватися інших мов програмування GPU, наприклад, мов шейдерів.


2

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


Деякі з цих мікроконтролерів (наприклад, сімейство PIC16) мають лише апаратний стек виклику (не доступний інструкціями) і не мають будь-якої іншої форми стеку, тому функції не можуть мати локальні змінні при використанні рекурсії (оскільки чітко потрібен стек даних для цього ...) Довідка: en.wikipedia.org/wiki/PIC_microcontroller#Stacks
Але

1

BASIC в дні рядкових номерів, як правило, мав погану підтримку рекурсії. Багато (всі?) ОСНОВИ того часу підтримували вкладені дзвінки gosub, але не підтримували простий спосіб передачі параметрів або повернення значень таким чином, щоб було корисно самостійно телефонувати.

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


1

Це залежить від того, що ви маєте на увазі під « підтримкою ». Для підтримки рекурсії вам потрібен стек, де слід інстанціювати локальні змінні при кожному повторному вході.

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

Я не знаю, чи можна це назвати "підтримкою". Факти полягають у тому, що я писав рекурсивну функцію за допомогою ZX-Spectrum BASIC, як це робив у Fortran77, як у COBOL ... завжди з цим фокусом.


1

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


2
Він підтримує рекурсію, наскільки підтримує виклики методів. Зазвичай є CALLінструкція, яка автоматично підштовхує IP до стеку перед переходом до підпрограми, та RETінструкція, яка відображає зворотну адресу в IP. Немає ніяких причин не CALLмати власного входу.
Blorgbeard

@Blorgbeard - абсолютно вірно, хоча я б стверджував, що це недостатньо, щоб вважати, що "підтримує рекурсію" в загальновизнаному розумінні, оскільки він не обробляє параметри, необхідні для рекурсивного виклику.
mikera

1
Ну, рекурсивні дзвінки технічно не потребують параметрів, правда? void f() { f(); }є рекурсивним.
Блоргберд

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

Я гадаю, ви могли це сказати. Але в цьому випадку збірка також не підтримує циклів (вам доведеться вручну CMP та JNZ). Я думаю, це питання того, що ви називаєте "підтримуючим".
Blorgbeard
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.