Программирование на языке Ада



    Довелось намедни на одном белорусском ресурсе прочесть статью «10 языков программирования, которые больше никому не нужны». Среди «заживо погребенных» оказались Fortran, Basic, J#, Turbo Pascal, Ada и другие. Так вот, наибольшую полемику, как ни странно, вызвало обсуждение Aдa (надеюсь в этом месте я не оскорбляю чьи-либо чувства). Что, собственно говоря и сподвигло покопаться в этой увлекательной теме.

    Ада получил свое название в честь той самой Ады Лавлейс, великого математика и первого в мире программиста (кстати, она единственный законнорожденный ребёнок знаменитого английского поэта Джорджа Гордона Байрона и его жены Анны Изабеллы Байрон). Этот язык был создан в конце семидесятых годов для бортовых систем военных объектов Пентагона.

    Тем удивительней, что в 1989 году в СССР материализовался ГОСТ (он же государственный стандарт) по работе с данным языком программирования. Если покопаться в документе, то там можно найти массу интересных вещей. Вообще хочется снять шляпу перед предшественниками, сделавшими эту по-настоящему впечатляющую работу. Честно говоря, в 80-е в СССР, как ни странно, вообще с книгами по программированию судя по всему было неплохо. Вот тут краткая Ада-библиография.

    Эксперты сходятся во мнении, что настоящих служителей Ада на постсоветском пространстве не так уж и много. Это и понятно. Все-таки, в основном данный язык применяется для программной разработки в авионике, атомной энергетике и в других промышленных отраслях, к которым на Java, ну никак, не подъедешь.

    Стоит отметить, что язык изначально разрабатывался для встраиваемых систем. Отсюда — неразвитость Ады по части GUI и СУБД. А раз с этим у неё туго, то и шансов развиться не было. Зачем она массовому разработчику, ведь ~99% пользовательских приложений нуждаются в GUI и СУБД.

    Синтаксис


    У Ada – простой, понятный, легко читаемый синтаксис, который существенно снижает риск ситуаций, когда случайная опечатка приводит к тому, что код не становится формально неправильным, но существенно меняется его семантика.

    Изначально, Ада — модульный язык программирования со строгой типизацией, унаследовавший синтаксис от Паскаль и Алгол. Если вы учили первый в школе или институте, то глядя на «Hello, World!» должны испытать ностальгию:

    with Ada.Text_IO;
    

procedure Hello is
 
    use Ada.Text_IO;

    begin
 
    Put_Line("Hello, world!");
    
end Hello;

    Одним из главных требований к языку была надёжность его использования. Соответственно, это повлекло за собой строгие ограничения по структуре, типам, написанию и многому другому. Кроме того, почти все ошибки здесь улавливаются на этапе компиляции. Другим требованием была максимальная читаемость кода в распечатанном виде, что повлекло за собой тяжеловесность полученного языка и невысокую гибкость.

    Более поздние стандарты частично решали эти проблемы, но по понятным причинам, они не сделали из Ада второй Python. (с)

    Где больше Ада?


    Покопавшись в «этих-ваших» интернетах оказалось, что Boeing, Airbus и даже российские Ил-96 и Бе-200 летают благодаря программным разработкам из Ада. Вся авиация плотно сидит там же. ПО для атомных станций и даже банковская система, включая сети банкоматов от Ада тоже не далеко ушли. Аналогичное можно сказать про автопром.

    Тем не менее, если сравнить количество запросов из HR на специалистов по С#, Python, Java, С++, то очевидно, что адептов Ада требуется в разы меньше. Но это не означает, что они вовсе не нужны. Не случайно в 2012 году были разработаны новые стандарты языка. Есть мнение, что совсем скоро он получит второе дыхание. Однако, справедливости ради, стоит отметить, что за его почти сорокалетнюю историю, подобных прогнозов было не мало.

    Если вас заинтересовал данный язык и вы вдруг решили узнать, где сегодня в мире грызут гранит Ада, заходите по ссылке. Но, если вы спец по С++, то в Parallels для вас есть местечко. Велкам!

    Parallels
    109,00
    Мировой лидер на рынке межплатформенных решений
    Поделиться публикацией

    Комментарии 100

      +4
      Кстати, я считаю что сейчас наступает время языка Ада для встроенных решений — это просто идеальный язык! К сожалению, пока не удается продолжить серию статей на эту тему, но все впереди.
        0
        Сейчас Rust уже «идеальнее». И на подходе ATS.
        +6
        Вся авиация плотно сидит там же

        JSF (это который F-35) уже на C++ программировали, в сети даже стандарт кода под него есть.
        SpaceX на своих ракетах тоже C++ используют. А заграничные вакансии разработчиков на Ada обычно требуют возможности оформления допуска к секретам.

          +2
          Плюс, формальная верификация в тех же боингах делается на Coq, насколько я знаю.
            0
            Обычно Coq — финальная стадия верификации. На чем написан верифицируемый проект не понятно.
          +3
          На самом деле, к такому заголовку картинку совсем другую хочется подобрать!
            +3
            Признаюсь, было искушение. Но побоялся оскорбить чьи-либо чувства. Нынче с этим нужно аккуратнее. Ну а в целом, изначально зацепился за книгу. А за ней оказалась целая история, причем, живых и активных в отрасли людей. Все не зря.
            +11
            Особенно порадовал в списке умерших Fortran. Похоже, Интел ничего не понимает и выпускает свежую версию ifort чуть ли не каждый год совершенно зря.
              +4
              О да, пару лет назад я обратился к дедушке фортрану от родного православного сионизма, ибо запарился изобретать математические велосипеды, рискуя обосраться в мелких, но жизненно важных для меня деталях. Фортран мало того что богат на библиотеки писанные математиками для математиков, но это всё прекрасно компилируется оптимизируясь по ходу, и на выходе мы получаем код-огонь, обгоняющий даже мои велоСИпеды, сказать что я был удивлён, ничего не сказать…
              … а дата сатанисты пусть и дальше молятся на питон, где тоже много чего есть, только вот какчество этого дела как у ардуино, пользователям которых топорность тоже не очевидна :-)
                +1
                  +10

                  Довольно большая часть библиотек научного стека Питона — это Фортран в обертке. Питон больше нужен для некритичных операций, как "клей".

                    0
                    Да я ж против питона ничего не имею.
                    Вполне себе такой современный бейсик, только мощнее.

                    Но если уж про обёртки вспомнили: сдаётся мне, компилятор гораздо эффективнее сможет оптимизировать монолитную программу, нежели сборище модулей.
                      0

                      Это так, и на Питоне зачастую куски, критичные по скорости, компилируют через Cython.


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

                        +3

                        Но и про Tcl забывать не стоит.

                          +4

                          Писал я на не, м, почти 10 лет… Немного перефразируя Луркоморье, это язык, на котором можно писать только в стельку пьяным.

                            +2

                            Но если даже он может, значит стоящий язык.
                            Сравнение python и tcl.

                              0

                              После примерно 5-7 тысяч строк и достаточно сложной логики на Tcl становится уж слишком сложно писать, и дико не хватает нормального объектно-ориенторованного подхода.

                                0

                                5-7 тысяч строк это все же немного, вот, например, Удостоверяющий Центр Tcl/Tk. Согласен с объектно-ориенторованным подходом было еще красивее. Но у Python-а свои заморочки, хотя все лучшее от Tcl он хорошо в себя вбирает.

                      0
                      Знаю, согласен, однако смотрите habr.com/post/261201/#comment_8480183 упомянутый выше, но это ещё не всё…
                      … бывают такие ситуации, когда этот клей, старый-добрый клей момент, надышавшись которым можно увидать разноцветных, резиновых зверушек и это прямо сказывается на получаемых результатах, но без широкого математического кругозора, это не разу не очевидно…
                      Вот и получается, что вроде
                      Одни и те-же вещи считаем,
                      На босу ногу топор одеваем,
                      Сапогом небо косим,
                      В решете воду носим.

                      А результат достигается и так и эдак, немного хуже, много дольше, и это много оно не только из-за оптимизации, оно и по другим причинам, из-за которых дольше может статься никогда…
                      Извините что не пишу конкретики, поверьте её полно но, она мой хлеб в буквальном смысле слова.
                      +2

                      LOL: дата сатанисты. Это даже круче, чем сайентологи.

                      +4
                      Да, Фортран уже давно «хоронят», но на нём до сих пор львиная доля научных вычислительных проектов делается. В том числе и те, которые с нуля пишутся. Стандарт обновляется каждые 3 года, сейчас готовится стандарт 202х. Причём, начиная с текущего основного стандарта, 2008, там появляются фичи, которым трудно найти замену в других языках.
                        0
                        там появляются фичи, которым трудно найти замену в других языках.

                        Какие это фичи?
                          +3
                          Стоит начать с того, что и некоторые стандартные вещи, как например, динамические многомерные массивы, мало в каких других языках поддерживаются. Помимо этого, начиная с 2015-го стандарта, в Фортане появляется поддержка многопоточности (атомные операции, критические секции и т.п.) на уровне языка. В частности, это позволяют компилятору производить эффективный потокобезопасный код.

                          Но многопоточностью сейчас, наврное, мало кого удивишь. Однако «killer-feature» на данный момент — это комассивы (по сути распределённые массивы), которые позволяют реализовывать параллелизацию по модели PAGS. Появилось это ещё в стандарте 2008, но полноценную поддержку компиляторами получило только пару лет назад. Позволяет писать эффективный код для суперкомпьютера, не вызывая напрямую MPI. Что-то подобное есть, по-моему, только в новом языке Julia, но он ещё из беты не вылез.
                            +1
                            Звучит довольно любопытно. Не сориентируете, куда копать, чтобы познакомиться с современным Фортраном?
                              +2
                              Можете здесь глянуть. Там в README ещё ссылки есть.

                              Правда, там только фичи, которые касаются производительности. Если хочется подробней, то прямо на сайте комиссии по стандартизации есть такие обзоры: New Features in Fortran 2003, то же для Fortran 2008, то же для Fortran 2018.
                                +1
                                Кстати, если вообще с нуля, то есть такие книжки: Modern Fortran Explained: Incorporating Fortran 2018.
                                +2

                                Только не PAGS а PGAS. все это взялось из coarray Fortran которому уже более 30 лет. И пробдемы там теже что и в нем(и что и во всех PGAS). Remote getы медленные на всех существующих имплементациях, т.е. об появлении высокоэффективногот кода для кластера заменой массиввов на co-масчивы рассчитывать не приходится => нужно переписывать код

                                  +2
                                  Опечатался, пардон.

                                  CAF был расширением, теперь (уже лет 10) стал стандартом. Насчёт медленности get: можете дать ссылки на бенчмарки? Не флейма ради, действительно любопытно.

                                  Мне кажется, что при оптимизрованной архитектуре, проблемы возникать не должно. А на данный момент производители кластеров оптимизируют их для PGAS.
                                  Вот, например, сравнение производительности CAF и Non-blocking MPI. При это CAF (например в библиотеке Open Coarrays) реализуется, в том числе, и как тонкая прослойка над MPI-RMA (тот же get/put).
                                    +1
                                    бенчмарков как таковых у меня лично нет, из того где это упоминается часть есть тут dl.acm.org/citation.cfm?id=2859624

                                    Всё что реализуют современный HPC сети тот же IB(а также даже и отечественные) это грубо говоря низкоуровневые примитивы (как в shmem, запись, чтение, блокировка). Проблема с get в том что его нельзя делать асинхронно put это положил кому-то и забыл, а у getа то результат есть, получается что на putах всё быстрее от этого мир розовых поней в лице coarrays/UPC рушится, т.к. они предоставляют такой же api как и в обычном C/fortran позволяя ему и читать и писать в память на уровне кода так же легко как и в локальнуюю память что побуждает программиста обращаться к этим шаренным массивам как к обычным и так же часто читать память нежели писать => см. про getы
                                      +1
                                      Я понял, о чём Вы. Да, разница между put и get, конечно, есть. Для этого программисту надо примерно представлять, что происходит под капотом, когда он пишет arr[i] = x или y = arr[i], и принимать это во внимание.

                                      В любом случае, понятно, что для того, чтобы выжать максимум масштабируемости, все коммуникации надо реализовывать руками на MPI. Но есть масса задача, где-то пересылки идут не часто и большими блоками. Тогда можно пожертвовать парой процентов в виде накладных расходов для того, чтобы сделать код читабельным и понятным.
                            +1
                            Здесь на языки программирования переносятся законы рыночной экономики. «Если вы не едете на велосипеде, то вы падаете» — т.е. то, что не развивается, то умирает. Между тем существуют нишевые продукты, которые и не показывают развития, и не умирают.
                            +3
                            Читал эту книжку, когда она ещё продавалась в магазинах (не в «Старой книге» :)
                            Больше всего запомнилось, что после end надо указывать, чего именно это end («end Hello» в приведённом примере).
                            С тех пор часто пишу "}//Hello"
                            Ещё стоит отметить, что ОС для Intel 432 была написана на Ada:
                            https://en.wikipedia.org/wiki/IMAX_432
                              0
                              С тех пор часто пишу "}//Hello"

                              Вот она, профдеформация, во всей красе. А как после вас код дописывать/переписывать/рефакторить?
                                +3
                                Да как любой код с комментариями. Это же комментарий.
                                  –1
                                  Комментарий, который стоит не в тему и в нестандартном месте. Опустим то, что непонятно, что с ним произойдёт при автоматическом рефакторинге в современных IDE — это надо проверять в каждой отдельно. Но сам факт, что приходится писать комментарий, — мне непоняет. Если вы теряетесь в скобках — используйте отступы. Если вы теряетесь в отступах — наведите на закрывающую скобку и IDE подсветит соответствующую открывающуюю. Если всё ещё теряетесь — значит вы через чур много кода написали в одном месте — воспользуйтесь декомпозицией рекурсивно до тех пор, пока блоки кода не станут быть видимы целиком невооружённым глазом.
                                    0
                                    Но ведь у вас — тоже «профдеформация, во всей красе».
                                    Если вы что-то не пользуете, то другим это надо запретить?
                                    «end Hello» было нужно во времена многострочных вложенных циклов и низких разрешений экранов, т.ч. не влезало в экран. А среды программирования бывали однооконными (или их вообще не было, т.ч. — текстовый файл и вызов компилятора из командной строки). Разработчики сделали простое и полезное решение. А потом было лень переучиваться, да и незачем.
                                      –1
                                      Нет, у меня профдеформации нет. Профдеформация, простыми словами, — это когда ты делаешь какую-нибудь фигню или судишь как-то по-своему о вещах, не потому что это логично, целесообразно, нужно… а потому что по причине долгой работы по определённой профессии, у тебя так нейроны в голове законнектились. Это что-то вроде привычки, ритуала… отчасти на бессознательном уровне, и нужно приложить усилия, чтобы убедить себя в том, что такое поведение — некорректно, и нужно отучать себя от него.

                                      А мне почти 33 года, программированием я занимаюсь с 16 лет, застал и бейсик на Spectrum-like компьютерах, и турбо паскаль, и прочие «прелести» тех времён. Но те времена давным-давно прошли. И писать сейчас в стиле пятнадцати-двадцати -летней давности — это надо быть тем ещё динозавром с зашореным мысшлением, совсем не способным к адаптации.
                                  0
                                  Тяжело представить, что кому-то могут сильно помешать метки-комментарии окончания блока. IMHO это довольно удобно, когда по какой-либо причине приходится писать код с большим количеством вложенных блоков.
                                    0
                                    Не знаю ни одной причины, по которой следовало бы писать код с большим количеством вложенных блоков. Приведёте пример?
                                      0
                                      Увы, пример привести уже не могу, т.к. такой код я видел только однажды (причем закрытие блока было откомментировано точно так же) и в том конкретном случае, это помогло разобраться в жуткой мешанине блоков в 2-3 экрана.
                                        0
                                        То есть вы однажды в каком-то говнокоде видели пример использования комментария на закрывающей скобке и из этого единичного случая теперь готовы пропагандировать использования этой дикой методики в современных реалиях?
                                          0
                                          использования этой дикой методики в современных реалиях

                                          Если я правильно понял посыл — то только в говнокоде.
                                            0
                                            Да, вы все правильно поняли, такая предусмотрительность «кодера» упрощает переписывание кода в нормальный вид.
                                              0
                                              А если «кодер» не предусмотрительный — то такой приём годится как промежуточный этап при рефакторинге.
                                0
                                Будет ли програмирование на языке Рая?
                                  +4
                                  Вы не поверите, но РАЯ даже заставляли учить в школах:
                                  dic.academic.ru/dic.nsf/ruwiki/1130547
                                    +8
                                    Как же никто не написал книжку от РАЯ до АДА?
                                      0
                                      от РАЯ до АДА


                                      Туда и обратно.
                                  +3
                                  Ада — модульный язык программирования со строгой типизацией, унаследовавший синтаксис от Паскаль и Алгол.

                                  Что у вас со склонениями?

                                    +5
                                    У нас тут в курчатовском институте одна их расчетных программ для системы СВРК ВВЭР-1000 изначально была на с++. Потом ее переписали на Аду.

                                    Еще у Ады есть очень интересное, так сказать, расширение — SPARK. Этот инструмент позволяет «доказывать» корректность выполнения программы на этапе компиляции.

                                      +1
                                      Если судить по известному индексу, у Ады не плохая 35 позиция. Нпр., у PostScript гораздо хуже, а Assembly language сильно утрачивает популярность и съехал на 15-ю позицию. Это отмечено в Вики:
                                      There have always been debates over the usefulness and performance of assembly language relative to high-level languages. Assembly language has specific niche uses where it is important; see below. As of July 2017, the TIOBE index of programming language popularity ranks assembly language at 11, ahead of Visual Basic, for example.
                                      Но, ИМХО вряд ли кто скажет, что Ассемблер — ЯП, который совершенно никому не нужен. ИМХО очень неоднозначно с рейтингами ЯП: м.б. ЯП с небольшим рейтингом, но хоронить его никак нельзя.
                                        +3
                                        О!

                                        Я лет шесть назад пробовал устроиться на работу в контору, в которой частью процесса было «решить задачу на языке, который не использовался в работе до тех пор». Я как раз попробовал на Ada.
                                          0

                                          Зачётное название статьи.

                                            +1
                                            Про J# ни разу еще не слышал из списка «мертвых». Пошел гуглить. Странно, кстати, что таким порядком в «мертвые» не записали Perl!
                                              +1
                                              Потому что J# это по сути не самостоятельный язык, а побочный продукт попытки отжима Java у Sun и истории становления C#, который уже, в свою очередь, стал полноценным языком, который пошёл в массы.
                                                +1
                                                Я уж про это нагуглил. :) А вообще, интересно сколько таких попыток было за всю историю?!
                                                  0
                                                  Попыток отжать Java? Или создание языков ради посторонних целей (отжать что-то, надавить на кого-то, вытеснить с рынка конкурента)? Я думаю, тут цифра будет, во-первых, большая, во-вторых, дробная, — потому что зачастую сложно отнести что-то к однозначно мудацкой затее. Например, язык C++/CLI, выпущенный той же корпорацией Microsoft, с одной стороны, может показаться, что был попыткой сделать свой C++ с преферансом и профурсетками (а может и нет, кто знает, что у них на уме было), но с другой, — на практике использовался как клей между привычным нам платформозависимым кодом и managed-кодом, работающим под .NET… А перед ним был Managed C++. А ещё была такая весёлая штука, как J++ (раз уже J# вспомнили). Или вот C++/CX — ещё одна помесь бульдога с носорогом, но на этот раз — чтобы писать под WinRT. Это я не касаюсь чисто исследовательских проектов, как Cω. Или domain-specific языков, как X++. Что-то я отошёл от темы вопроса… но это не спроста, если начать основательно копать историю только языков только от Microsoft, можно пошатнуть свою психику.
                                              +1
                                              язык изначально разрабатывался для встраиваемых систем. Отсюда — неразвитость Ады по части GUI и СУБД
                                              Язык 1980 года, о каких GUI и встраиваемых системах идёт речь?))
                                                +1
                                                  +1
                                                  Как минимум банкоматы, станки с ЧПУ, микрокалькуляторы и бортовые вычислители на ракетах тогда уже вовсю существовали. Самые что ни на есть классические встраиваемые системы.
                                                    0
                                                    Дык и C++ примерно тех же лет. А Си уж и того древнее. Однако там всё есть. :-)

                                                    Текущий стандарт Ады — это Ada 2012. И этот язык сильно отличается по своим возможностям от того, что было стандартизировано в 1983 году.

                                                    А вот ориентированность на embedded mission critical systems осталась. Это одно из основных применений Ады сейчас. Хотя есть либы и фреймворки и для всего остального. Написать http-сервер там не сложнее чем на С++.
                                                      0
                                                      А то GUI, которое не на Аде, оно на языках какого года?

                                                      Мне, кстати, больше всего GUI Cocoa нравится, а оно не просто так получилось таким. Оно восходит к Objective C (тогда ещё без дефиса) и его библиотек из тех самых страшных 80х. Но в тех самых страшных 80х оно, наверное, по сравнению с другими, было не очень, а за прошедшее время устаканилось, и поэтому такое хорошее. Иметь время устаканиться и быть на свежем языке — вещи не очень совместимые.
                                                      0
                                                      Кто-нибудь видел на GitHub и SourceForge реальные проекты на Аде? Дайте ссылки.
                                                        +3
                                                        Реальные проекты на Аде распространяются на восьмидюймовых дискетах.
                                                          +16
                                                          Реальные проекты на Аде распространяются по баллистическим траекториям.
                                                          +2
                                                          Например, альтернативный (заменяющий собой классические portmaster, portupgrade и poudriere) менеджер репозиториев и пакетов для FreeBSD и DragonFly. Необычные языки программирования в *BSD использовались и раньше: так, CVSup, инструмент для быстрого чекаута-апдейта (network distribution) из некогда популярной системы контроля версий CVS, был написан на Модуле (Ezm3); впрочем, впоследствии его заменила аналогичная утилита, написанная на C (csup).
                                                            0
                                                            github.com/ghdl/ghdl
                                                            Даже использовал — фронтенд VHDL к gcc.
                                                              +1
                                                              blog.vacs.fr — ORM, блог и вики, и сам сайт на этом же движке работает

                                                              gnoga.com/#tools — движок для облачных приложений

                                                              github.com/mosteo/adagio — p2p (Gnutella2) сервачок

                                                              ironsides.martincarlisle.com — верифицированный DNS сервер на SPARK

                                                              parasail-lang.org — виртуальная машина (чем-то напоминает Erlang) и 4 языка программирования

                                                              www.pegasoft.ca/tia.html — консольный редактор

                                                              gprbuild (в составе дистрибутивов GNAT, хотя можно и отдельно установить) эволюцонировал из чисто адских gnatmake, а потом gprmake, чтобы лучше поддерживать смешанные C/C++ проекты. И настолько в этом преуспел, что и для проектов без языка Ада хорошо подходит. После gprbuild я не переварил CMake. Не знаю, чего с него так тащатся. Может, gprbuild никогда не видели.

                                                              muen.sk — верифицированный гипервизор
                                                              +2
                                                              Игра STARTREK (текстовая) на ADA :-)
                                                              STARTREK.ADA
                                                              procedure STAR_TREK is

                                                              energy : integer := 4000;
                                                              torpedoes : integer := 10;
                                                              star_date : integer := 3421;
                                                              klingons : integer;
                                                              total_klingons : integer; -- # klingons in galaxy
                                                              star_bases : integer; -- # starbases in galaxy
                                                              x_sector,y_sector : integer; -- position of Enterprise
                                                              x_quadrant,y_quadrant : integer; -- position of Enterprise
                                                              condition : string(1..6) := "Green ";
                                                              damage : array(1..6) of integer;
                                                              x,y : integer;
                                                              max_klingons : constant integer := 4;
                                                              x_klingon, y_klingon, power_klingon : array(1..max_klingons) of integer;
                                                              sectors : array(0..7,0..7) of character;
                                                              quadrants : array(0..7,0..7) of integer;
                                                              command : integer;
                                                              moved, docked : boolean := false;

                                                              function rand(A : integer) return integer is
                                                              function truncate(A : float) return integer is
                                                              b : integer := integer(A);
                                                              begin
                                                              if float(b) < a then return b; else return b-1; end if;
                                                              end truncate;
                                                              begin
                                                              return truncate(rnd(0.0) * float(a));
                                                              end rand;

                                                              function distance(i,j,x,y : integer) return integer is
                                                              a,b : integer;

                                                              function sqrt(a : integer) return integer is
                                                              begin
                                                              if a=0 then return 0;
                                                              elsif a=1 then return 1;
                                                              else
                                                              for guess in 2..256 loop
                                                              if guess**2 = a or (guess+1)**2 > a then
                                                              return guess;
                                                              end if;
                                                              end loop;
                                                              end if;
                                                              end sqrt;

                                                              begin -- distance
                                                              a := i - x;
                                                              b := j - y;
                                                              return sqrt(a ** 2 + b ** 2) + 1;
                                                              end distance;

                                                              procedure get_blank_sector is
                                                              begin
                                                              x := rand(7);
                                                              y := rand(7);
                                                              if sectors(x,y) /= '.' then
                                                              get_blank_sector;
                                                              end if;
                                                              end get_blank_sector;

                                                              procedure reset is -- reset all enterprise variables
                                                              begin
                                                              new_line;
                                                              energy := 4000;
                                                              torpedoes := 10;
                                                              for i in 1..6 loop
                                                              damage(i) := 0;
                                                              end loop;
                                                              condition := "Green ";
                                                              end reset;

                                                              procedure dock is -- dock the enterprise at a starbase
                                                              begin
                                                              reset;
                                                              docked := true;
                                                              condition := "Docked";
                                                              end dock;

                                                              function unexplored(A,B : integer) return boolean is
                                                              begin
                                                              if quadrants(a,b) < 0 then
                                                              return true;
                                                              else
                                                              return false;
                                                              end if;
                                                              end unexplored;

                                                              procedure initialize is
                                                              begin
                                                              put("Please wait while I create the universe");new_line;
                                                              put("(Even God took seven days...)");new_line;
                                                              reset;
                                                              x_quadrant := rand(7);
                                                              y_quadrant := rand(7);
                                                              star_date := 3421;
                                                              total_klingons := 0;
                                                              star_bases := 0;
                                                              for i in 0..7 loop
                                                              for j in 0..7 loop
                                                              declare
                                                              n : integer := 1;
                                                              o : integer;
                                                              begin
                                                              o := rand(max_klingons+1); -- get rand # klingons
                                                              total_klingons := total_klingons + o;
                                                              n := n + o * 100;
                                                              n := n + rand(8);-- get rand # stars
                                                              if rand(8)=1 then
                                                              n := n + 10;
                                                              star_bases := star_bases + 1;
                                                              end if;
                                                              quadrants(i,j) := -n;
                                                              end;
                                                              end loop;
                                                              end loop;
                                                              put("Initialization complete."); new_line;
                                                              end initialize;

                                                              procedure set_up_quadrant is
                                                              begin
                                                              for i in 0..7 loop
                                                              for j in 0..7 loop
                                                              sectors(i,j) := '.';
                                                              end loop;
                                                              end loop;

                                                              x_sector := rand(7);
                                                              y_sector := rand(7);
                                                              sectors(x_sector,y_sector) := 'E';

                                                              if abs(quadrants(x_quadrant,y_quadrant)) mod 100 > 9 then
                                                              get_blank_sector;
                                                              sectors(x,y) := 'B';
                                                              end if;

                                                              if abs(quadrants(x_quadrant,y_quadrant)) >= 100 then
                                                              declare
                                                              i : integer :=
                                                              abs(quadrants(x_quadrant,y_quadrant))/100;
                                                              begin
                                                              for j in 1..i loop
                                                              get_blank_sector;
                                                              sectors(x,y) := 'K';
                                                              x_klingon(j) := x;
                                                              y_klingon(j) := y;
                                                              power_klingon(j) := rand(20) * 10 + rand(20) + 5;
                                                              end loop;
                                                              klingons := i;
                                                              end;
                                                              else
                                                              klingons := 0;
                                                              end if;

                                                              if abs(quadrants(x_quadrant,y_quadrant)) mod 10 > 0 then
                                                              declare
                                                              i : integer :=
                                                              abs(quadrants(x_quadrant,y_quadrant)) mod 10;
                                                              begin
                                                              for j in 1..i loop
                                                              get_blank_sector;
                                                              sectors(x,y) := '*';
                                                              end loop;
                                                              end;
                                                              end if;
                                                              end set_up_quadrant;

                                                              procedure attacked is
                                                              begin
                                                              if klingons /= 0 then
                                                              for i in 1..klingons loop
                                                              declare
                                                              j : integer;
                                                              begin
                                                              j := power_klingon(i) /
                                                              distance(x_klingon(i),y_klingon(i),x_sector,y_sector);
                                                              put(j);
                                                              put(character'val(9));
                                                              put("unit hit from Klingon at ");
                                                              put(x_klingon(i)+1);
                                                              put(',');
                                                              put(y_klingon(i)+1);
                                                              put(" (");
                                                              put(power_klingon(i));
                                                              put(')');
                                                              new_line;
                                                              energy := energy - j;
                                                              end;
                                                              end loop;
                                                              end if;
                                                              end attacked;

                                                              procedure commands is

                                                              procedure short_range_scan is
                                                              begin

                                                              -- set starship condition

                                                              if klingons > 0 then
                                                              condition := "Red ";
                                                              elsif docked then
                                                              dock;
                                                              elsif energy < 300 then
                                                              condition := "Yellow";
                                                              else
                                                              condition := "Green ";
                                                              end if;

                                                              -- print quadrant map

                                                              for i in 0..7 loop
                                                              for j in 0..7 loop -- print a row of quadrant
                                                              put(sectors(i,j)); put(' ');
                                                              end loop;
                                                              put(" ");

                                                              -- print a line of starship information

                                                              case i is
                                                              when 1 =>
                                                              put("Stardate=");put(star_date);new_line;
                                                              when 2 =>
                                                              put("Condition: ");
                                                              put(condition);
                                                              new_line;
                                                              when 3 =>
                                                              put("Quadrant=");
                                                              put(x_quadrant+1);put(",");
                                                              put(y_quadrant+1);new_line;
                                                              when 4 =>
                                                              put("Sector=");
                                                              put(x_sector+1);put(",");
                                                              put(y_sector+1);new_line;
                                                              when 5 =>
                                                              put("Energy=");put(energy);new_line;
                                                              when 7 =>
                                                              put("Klingons left=");put(total_klingons);new_line;
                                                              when others =>
                                                              new_line;
                                                              end case;
                                                              end loop;
                                                              end short_range_scan;

                                                              procedure long_range_scan is

                                                              procedure display(number : integer) is

                                                              procedure dispnum(number : integer) is
                                                              begin
                                                              if number = 0 then
                                                              put('-');
                                                              else
                                                              put(number);
                                                              end if;
                                                              end dispnum;

                                                              begin
                                                              dispnum(number/100);
                                                              dispnum((number/10) rem 10);
                                                              dispnum(number rem 10);
                                                              end display;

                                                              begin
                                                              put(" Long range scan");
                                                              new_line;
                                                              for i in 0..7 loop
                                                              for j in 0..7 loop
                                                              if abs(i-x_quadrant) <= 1 and abs(j-y_quadrant) <= 1 then
                                                              quadrants(i,j) := abs(quadrants(i,j));
                                                              end if;
                                                              if unexplored(i,j) then
                                                              put("***");
                                                              elsif i = x_quadrant and j = y_quadrant then
                                                              put(" E ");
                                                              else
                                                              display(quadrants(i,j));
                                                              end if;
                                                              put(' ');
                                                              end loop;
                                                              new_line;
                                                              end loop;
                                                              end long_range_scan;

                                                              procedure phasors is
                                                              units : integer;
                                                              aux : integer;
                                                              length : integer;
                                                              begin
                                                              put("Number of units to fire? ");
                                                              get(units);
                                                              energy := energy - units;
                                                              while units > 0 and klingons /= 0 loop
                                                              aux := power_klingon(klingons);
                                                              length := distance(x_klingon(klingons),y_klingon(klingons),
                                                              x_sector,y_sector);
                                                              if length /= 0 then
                                                              aux := aux * length;
                                                              end if;

                                                              -- aux has relative power needed to destroy klingon

                                                              if units >= aux then -- more than enough to kill
                                                              units := units - aux;
                                                              put("Klingon at ");
                                                              put(x_klingon(klingons)+1);
                                                              put(',');
                                                              put(y_klingon(klingons)+1);
                                                              put(" destroyed!!!");
                                                              sectors(x_klingon(klingons),y_klingon(klingons)) := '.'; klingons := klingons - 1;
                                                              quadrants(x_quadrant,y_quadrant) :=
                                                              quadrants(x_quadrant,y_quadrant) - 100;
                                                              total_klingons := total_klingons - 1;
                                                              new_line;
                                                              else -- subtract what we threw at it...
                                                              power_klingon(klingons) :=power_klingon(klingons) -
                                                              units / length;
                                                              put(units / length);
                                                              put(" unit hit on Klingon at ");
                                                              put(x_klingon(klingons)+1);
                                                              put(',');
                                                              put(y_klingon(klingons)+1);
                                                              new_line;
                                                              units := 0;
                                                              end if;
                                                              end loop;
                                                              end phasors;

                                                              procedure navigate is
                                                              type_of_propulsion : character;
                                                              x, y : integer;

                                                              procedure get_x_y is
                                                              begin
                                                              put("New x co-ordinate: ");
                                                              get(x);
                                                              put("New y co-ordinate: ");
                                                              get(y);
                                                              if x<1 or x>8 or y<1 or y>8 then
                                                              put("Invalid co-ordinates, try again!");new_line;
                                                              get_x_y;
                                                              end if;
                                                              x := x - 1; y := y -1;
                                                              end get_x_y;

                                                              procedure new_sector is
                                                              begin
                                                              get_x_y;
                                                              if sectors(x,y) = '.' then
                                                              sectors(x,y) := 'E';
                                                              sectors(x_sector,y_sector) := '.';
                                                              energy := energy - distance(x,y,x_sector,y_sector);
                                                              x_sector := x;
                                                              y_sector := y;
                                                              else
                                                              put("That sector is not empty, try again!");new_line;
                                                              new_sector;
                                                              end if;
                                                              end new_sector;

                                                              procedure check_docked is
                                                              begin
                                                              docked := false;
                                                              for i in x_sector-1..x_sector+1 loop
                                                              for j in y_sector-1..y_sector+1 loop
                                                              if sectors(i,j) = 'B' then
                                                              docked := true;
                                                              end if;
                                                              end loop;
                                                              end loop;
                                                              if docked then dock; end if;
                                                              end check_docked;

                                                              begin
                                                              put("Impulse (I) or Warp (W) power? ");
                                                              get(type_of_propulsion);new_line;
                                                              docked := false;

                                                              if type_of_propulsion = 'W' or type_of_propulsion = 'w' then
                                                              get_x_y;
                                                              moved := true;
                                                              energy := energy - distance(x_quadrant,y_quadrant,x,y) * 100;
                                                              x_quadrant := x;
                                                              y_quadrant := y;
                                                              else
                                                              new_sector;
                                                              short_range_scan;
                                                              end if;
                                                              check_docked;
                                                              end navigate;

                                                              begin -- commands
                                                              command := 0;
                                                              attacked; -- Enterprise is attacked immediately
                                                              short_range_scan; -- show the captain what he is up against

                                                              while not moved and energy > 0 and total_klingons /= 0 loop
                                                              put("Command? ");
                                                              get(command);
                                                              case command is
                                                              when 0 =>
                                                              long_range_scan;
                                                              when 1 =>
                                                              short_range_scan;
                                                              when 2 =>
                                                              phasors;
                                                              attacked;
                                                              short_range_scan;
                                                              when 3 =>
                                                              navigate;
                                                              when others => -- menu if bad command
                                                              put("0 - long range scan");new_line;
                                                              put("1 - short range scan");new_line;
                                                              put("2 - phasors");new_line;
                                                              put("3 - navigate");new_line;
                                                              end case;
                                                              end loop;
                                                              end commands;

                                                              begin -- main startrek program
                                                              initialize;
                                                              while energy > 0 loop
                                                              moved := false; -- say we haven't moved out yet
                                                              set_up_quadrant; -- initialize the quadrant
                                                              commands;
                                                              end loop;

                                                              if total_klingons = 0 then
                                                              if energy > 0 then
                                                              put("Congratulations, you have saved the Federation");
                                                              new_line;
                                                              put("and have been promoted to Admiral.");new_line;
                                                              else
                                                              put("You have destroyed the klingon manace and have");
                                                              new_line;
                                                              put("killed yourself in the process. A statue will");
                                                              new_line;
                                                              put("erected in your honor. Rest in peace and try");
                                                              new_line;
                                                              put("not to think of the pidgeons.");
                                                              new_line;
                                                              end if;
                                                              elsif energy <= 0 then
                                                              put("You have been destroyed and the empire has been");
                                                              new_line;
                                                              put("taken over by Klingons. Better luck next time.");
                                                              new_line;
                                                              else
                                                              put("Time has run out. The Klingons have invaded");
                                                              new_line;
                                                              put("en masse and wiped out the Federation.");
                                                              end if;

                                                              end STAR_TREK;


                                                              Компилируется, запускается и работает (IMHO без глюков) под CP/M.
                                                                +2
                                                                Учил в конце 90-х в институте Ada 95. Помнится, понравилась легкость реализации параллельных вычислений и довольно низкий порог входа.
                                                                  +1
                                                                  Ада не является сокращением, это имя вполне себе конкретного человека в честь которого она названа, поэтому не надо писать это слово целиком заглавными буквами.
                                                                  А язык хорош по своему. Но к сожалению тяжелый, сложный и дорогой компилятор в 80х не оставил ему особых шансов на PC в сравнении с дешевыми и быстрыми Паскаля и С/С++ отсюда и не великая популярность, к тому же писать на нем тяжелее, а вот читать наоборот легче потом.
                                                                    +2

                                                                    Я программировал на Ada немного, это было на VAX/VMS

                                                                      +2
                                                                      Принципиально важные моменты:
                                                                      Ада (Ada) — язык программирования, созданный в 1979—1980 годах в ходе проекта Министерством обороны США с целью разработать единый язык программирования для встроенных систем (то есть систем управления автоматизированными комплексами, функционирующими в реальном времени).[...] Перед разработчиками не стояло задачи создать универсальный язык, поэтому решения, принятые авторами Ады, нужно воспринимать в контексте особенностей выбранной предметной области.

                                                                      разработавшая его [ЯП] группа под руководством француза Жана Ишбиа
                                                                      Давно на одной конференции познакомился с профессором CS не помню какого французского университета. Он рассказывал, что Ада во Франции — национальная гордость и многие курсы у них на этом языке. Поэтому если кто хочет найти больше литературы и кода на Аде, то имеет смысл искать во французских источниках.
                                                                      В 1983 году язык был официально стандартизован ANSI. [...] Министерство обороны США [...], запретив выпускать трансляторы языка, не прошедшие официальную процедуру тестирования на соответствие стандартам. [...] Тестирование проводилось по принципу «всё или ничего» — при ошибке в обработке хотя бы одного тестового примера компилятор считался не прошедшим тест, причём тестирование было действительно только на той аппаратной и программной платформе, на которой оно проводилось. Таким образом была в зародыше подавлена возможность образования «версий» или «диалектов» языка Ада.
                                                                      Есть интересный сборник статей по сравнению ЯП: Языки программирования Ада, Си, Паскаль. Сравнение и оценка/ Под. ред.А.Р.Фьюэра, Н. Джехани, М.: Радио и связь, 1989.
                                                                        +7
                                                                        Ада во Франции — национальная гордость, и многие курсы у них на этом языке.
                                                                        Французы вообще, похоже, мастаки по части годных языков программирования: еще можно вспомнить INRIA и их [O]Caml.
                                                                        +2
                                                                        В Oracle DB используется язык PL/SQL, созданный на основе идей Ada.

                                                                        Думаю, что из-за схожести синтаксиса ее надо позиционировать в том числе и разработчикам Oracle, примерно так как java и с# позиционировали разработчикам на C/C++.

                                                                        Для разработчиков Oracle, наверное, было бы интересно разрабатывать нативные, быстрые, занимающие небольшое количество памяти, работающие вне базы Oracle DB web — приложения на Ada (и не только для Oracle DB).

                                                                        А там и до embedded решений недалеко и расширения областей своего применения как разработчика (не всем нравится enterprise, где в основном и применяется Orcle)
                                                                          +1
                                                                          За что наминусовали Милсу?
                                                                          Ада и PL/SQL соотносятся как C и С++, и именно благодаря PL/SQL, Ада является живым популярным языком.
                                                                            +1
                                                                            Как Ораклист, заинтересован. Где-нибудь можно почитать про Аду (не Лавлейс :)) подробнее?

                                                                            habr.com/company/parallels/blog/430924/#comment_19411252
                                                                            Отметил, что в PL/SQL тоже есть подобное.
                                                                              0
                                                                              Я исследовал вопрос применимости Ады. Применять — можно, но желающих — мало.
                                                                              Чтение википедии по теме даст больше знаний по этому вопросу, чем обсуждаемая статья или чей-то обзор («10 языков программирования, которые больше никому не нужны»).
                                                                              Местами Ada — нужна, в основном — в Европе.
                                                                              Стоит упомянуть о GNAT.
                                                                              GNAT — часть большинства дистрибутивов Linux и BSD.
                                                                              FSF GNAT is part of most major GNU/Linux or BSD distributions and is included in the main GCC Sources.

                                                                              Ada и Fortran есть в GNU Compiler Collection, а всяких новомодных языков там нет. Т.ч. якобы «неиспользуемые» очень даже рабочие и поддерживающиеся.

                                                                              Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.

                                                                              Самое читаемое