99

У американцев есть глуповатая считалочка — «песня о пиве», наверняка её многие слышали в американских фильмах. Когда-то у меня было хобби — делать вывод этой считалочки на разных языках программирования. Со временем набралась приличная коллекция.

58. R — математический язык программирования, на сайте о нём есть ряд заметок, так аннотацию пропущу, сразу программа:
# Written by Evgeny Stepanischev, 2017

bottles <- function(beer) {
    ifelse(beer == 0, "no bottles",
        ifelse(beer > 1, paste(beer, "bottles"),  "1 bottle")
    )
}

for (i in 99:1) {
    paste(bottles(i), "of beer") -> b

    cat(b, " on the wall, ", b, ".\n", sep = "")
    cat("Take one down and pass it around,", bottles(i - 1), "of beer on the wall.\n\n")
}

cat("No more bottles of beer on the wall, no more bottles of beer.\n")
cat("Go to the store and buy some more, 99 bottles of beer on the wall.\n")
57. Язык калькулятора Электроника МК-61. Если вы знаете, о каком калькуляторе идёт речь, то понимаете, что полноценную «песню» на нём не написать, всё, что мне удалось — вывести на индикатор строку вида «99 BEEr», где цифру придётся ввести самостоятельно. О сложностях, с которыми пришлось столкнуться я писал достаточно подробно, так что повторяться не буду.
8112000 Х→П c 8 + ИНВ Х→П b Вх 10 ÷ [X] Х→П d 8 + ИНВ Х→П e В/О ПРГ
П→Х 0 1 0 ÷ [x] Х→П 1 Вх {x} 1 0 × Х→П 2
1 1 Х→П 8 1 2 Х→П 7 П→Х 2 ПП 34 Х→П a
1 4 Х→П 8 1 3 Х→П 7 П→Х 1 ПП 34 П→Х a
^ С/П
6 - /-/ x<0 45 9 + К П→Х 7 + ИНВ В/О
1 + К П→Х 7 + ИНВ К П→Х 8 ^ В/О
56. CMake — автоматизированная система сборки пакетов, имеющая развитый, хотя и несколько уродливый макроязык. Инструкции, большей частью, знакомые, разве что способ возврата значений несколько из макросов и функций несколько странный — через параметры и глобальные переменные.

Никакого ООП, само собой, и всё весьма примитивно по меркам развитых языков
# 99.cmake
# to run: cmake -P 99.cmake
# Written by Evgeny Stepanischev, 2015

cmake_minimum_required(VERSION 3.0)

macro(bottles beer ret)
    if(${beer} EQUAL 0)
        set(${ret} "No bottles")
    elseif(${beer} EQUAL 1)
        set(${ret} "1 bottle")
    else()
        set(${ret} "${${beer}} bottles")
    endif()
endmacro()

foreach(beer RANGE 99 1 -1)
    bottles(beer bottles)
    math(EXPR beer "${beer}-1")
    bottles(beer bottless)

    message("${bottles} of beer on the wall, ${bottles}.")
    message("Take one down and pass it around, ")
    message("${bottless} of beer on the wall.")
    message("")
endforeach()

message("No more bottles of beer on the wall, no more bottles of beer.")
message("Go to the store and buy some more, 99 bottles of beer on the wall.")
56. БЭЙСИК «Электроники МК85». Этот язык отличается странностями. Например, там фиксированное количество переменных с определёнными (только однобуквенными именами), причём только одна строковая переменная может содержать не более 30 символов (её имя — символ доллара), остальные могут содержать не более семи символов.

Или запись массивов — все числовые переменные, по сути, являют собой один массив. Индекс «один» массива с именем «А» совпадает с переменной «B», а индекс «два» переменной «B» — это переменная «D» и так далее. Так что вы можете использовать что-то одно — либо массив полностью, либо переменные.

Другая неприятная особенность — небольшой максимальный размер строки и программы и весьма ограниченный её размер. Из-за этого принято лепить программу как можно более компактно (что я и сделал).

В общем, представляю вашему вниманию программу «99 бутылок пива на стене», написанную на БЭЙСИКе микрокомпьютера «Электроника МК-85», я запускал, работает:
10FOR B=99 TO 1 STEP -1
20A=B:GOSUB90:PRINT" of beer on the wall, ";:GOSUB90:PRINT"."
30PRINT"Take one down and pass it around, ";:A=B-1:GOSUB90
40PRINT" of beer on the wall."
50NEXT B
60PRINT"No more bottles of beer on the wall, no more bottles of beer."
70PRINT"Go to the store and buy some more, 99 bottles of beer on the wall."
80END
90GOTO100*(SGN(A-1)+2)
100PRINT"no bottles";:RETURN
200PRINT"1 bottle";:RETURN
300PRINT A;" bottles";:RETURN
55. 𝄢 Cello — это набор макросов к Си, вводящих в язык кучу комплексных типов, простую работу с выделением и освобождением памяти под них, лямбда-функции, классы и так далее.

В документации выглядело неплохо, но по факту оказалось, что библиотека недописана, а документация неполная и содержит ошибки. Шаг в сторону и программа вылетает. Например, она падает, если попытаться использовать возвращаемое лямбдой значение.

Пример ошибки в документации — функции в «стиле Си» не могут быть заданы внутри функции main, хотя на сайте указан пример, в котором утверждается обратное (и он не компилируется).

По идее, библиотека должна упрощать программирование, но в моём случае (я понимаю, «песня про пиво» не совсем та программа, в которой раскрывается эта библиотека) всё было ровно наоборот — на чистом Си я справился бы значительно быстрее.

Если бы её дописать и достойно задокументировать, вышло бы что-то интересное, пока же я пас — надо знать в деталях каждый макрос (а их там очень много) чтобы понять из-за чего скомпилированное в очередной раз упало.
#include "Cello.h"

int main() {
    lambda(bottles, args) {
        var beer = cast(at(args, 0), Int);

        if_eq(beer, $(Int, 0)) {
            print("no bottles");
        } else {
            if_gt(beer, $(Int, 1)) {
                print("%d bottles", beer);
            } else {
                print("1 bottle");
            };          
        }

        return None;
    };

    for (var beer = $(Int, 99); gt(beer, $(Int, 0));) {
        call(bottles, beer);
        print(" on the wall, ");
        call(bottles, beer);
        println(".");

        print("Take one down and pass it around, ");
        sub(beer, $(Int, 1));
        call(bottles, beer);
        println(" of beer on the wall.n");
    }

    println("No more bottles of beer on the wall, no more bottles of beer.");
    println("Go to the store and buy some more, 99 bottles of beer on the wall.");
}
54. HQ9+ — язык, у которого только четыре оператора. «H» выводит «Hello world», «Q» печатает исходный код программы, 9 выводит «песню о пиве», а «плюс» «увеличивает аккумулятор». Язык, понятное дело, придуман в шутку и у неё есть продолжения — «объектный» «HQ9++», Тюринг-полный «HQ9+B» и так далее.

Так что данная программа на этом языке выглядит вот так:
9
53. Scratch — визуальный язык программирования для детей. Программа строится из цветных блоков, цвета кодируют тип блока — «движение», «внешность», «звук», «данные», «управление», «операторы» и так далее. Основные конструкции обычных языков в наличии. Процедур, как таковых, нет, но можно отсылать события другим подпрограммам и через глобальные переменные получать результат. Есть даже что-то похожее на потоки — передавая события, можно запускать подпрограммы асинхронно.

Из структур данных есть целые числа и числа с плавающей точкой, строки и даже массивы. Для последних доступны все операторы для работы с ними — добавление, удаление, замена, получение значения по индексу, замена и так далее. Scratch (84.30КиБ) 52. AppleScript — встроенные в операционную систему «МакОС» язык программирования, используемый для мелкой автоматизации. По программе этой не очень очевидно, но язык максимально приближен к английскому, причём многие вещи можно формировать разнообразными способами — так же, как бы это сделал носитель английского языка.

В остальном, это обычный динамический интерпретируемый язык со слабой типизацией. Как видно в одном месте мне пришлось сделать преобразование типа. Вообще-то ЭплСкрипт делает это и сам, но в случае присоединения к строке, он число присоединит через запятую.
(* Песня про пиво. Автор — Евгений Степанищев *)
repeat with beer from 99 to 1 by -1
     set b to bottles(beer)
     log b & " on the wall, " & b & "."
     log "Take one down and pass it around, " & bottles(beer - 1) & " of beer on the wall."
     log
end repeat

log "No more bottles of beer on the wall, no more bottles of beer."
log "Go to the store and buy some more, 99 bottles of beer on the wall."

on bottles(beer)
     if beer = 0 then
 	        return "no bottles"
     else if beer > 1 then
 	        return (beer as string) & " bottles"
     else
 	        return "1 bottle"
     end if
end bottle
51. Applesoft BASIC — Бейсик разработанный компанией Майкрософт, использовавшийся в компьютерах фирмы Эпл, начиная с 1977 года. Ничего особо примечательного, вполне полнофункциональный язык, хоть и не без недостатков тех ранних «бейсиков» — вызов функций по номеру строки, параметров нет, локальных переменных нет, в общем, все прелести.

Я специально использовал конструкцию «ON…GOTO», хоть в ней и не было необходимости — хотел показать аналог конструкции switch. SGN тут — встроенная функция нахождения знака выражения.
000 REM Песня про пиво, автор — Евгений Степанищев
001 HOME: TEXT
010 FOR beer = 99 TO 1 STEP -1
020 b = beer: GOSUB 100
030 ? bottles$; " on the wall, "; bottles$; "."
035 b = beer - 1: GOSUB 100
040 ? "Take one down and pass it around, "; bottles$; " of beer on the wall."
050 ?
060 NEXT
070 ? "No more bottles of beer on the wall, no more bottles of beer."
080 ? "Go to the store and buy some more, 99 bottles of beer on the wall."
090 END
099 REM
100 ON SGN(b-1)+2 GOTO 120, 130, 110
110 LET bottles$ = STR$(b) + " bottles": RETURN
120 LET bottles$ = "no bottles": RETURN
130 LET bottles$ = "1 bottle": RETURN
50. Batsh — чрезвычайно лёгкий в освоении язык с Си-подобным синтаксисом, который умеет транслироваться в баш- и бат-скрипты, т.е. скрипты, которые будут без проблем работать и в мире Линукса, и в мире Виндоуз. Язык без особых затей, работает, похоже, железобетонно, но бедноват — даже обычного цикла for в нём нет. В общем набор минимальный (хотя рекурсия есть), но программировать можно.
// Песня о пиве на языке Batsh Степанищева Евгения

function bottles(bottle){
    if (bottle == 0) {
        return "no bottles";
    }
    
    if (bottle == 1) {
        return "1 bottle";
    }
    
    return bottle ++ " bottles";
}

i = 99;
while (i > 0) {
    b = bottles(i) ++ " of beer";

    println(b, "on the wall,", b ++ ".");
    i = i - 1;
    println("Take one down and pass it around,", bottles(i), "of beer on the wall.\n");
};

println("No more bottles of beer on the wall, no more bottles of beer.");
println("Go to the store and buy some more, 99 bottles of beer on the wall.");
49. VIM Script — встроенный скриптовый язык программирования консольного редактора VIM. Синтаксис довольно обычен, учится легко. Мощный для своего класса — обилие встроенных функций, довольно согласованный синтаксис, различные типы массивов. Есть интересные особенности, например, возможность явного переопределения функций, префиксы переменных для явного определения зоны видимости (например, префикс «a:» у меня в функции — это аргументы) или функции, которые могут принимать что-то вроде примитивного итератора.
" написал Евгений Степанищев bolknote.ru"

:function Bottles(bottle)
:    return get(["no bottles", "1 bottle"], a:bottle, a:bottle . " bottles")
:endfunction

:for beer in range(99, 1, -1)
:   let b =  Bottles(beer) . " of beer"
:   echo b "on the wall," b . "."
:   echo "Take one down and pass it around, " . Bottles(beer-1) . " of beer on the wall.\n"
:endfor

:echo "No more bottles of beer on the wall, no more bottles of beer."
:echo "Go to the store and buy some more, 99 bottles of beer on the wall."
48. Гоу (Go) — язык программирования, придуманный в «Гугле». Я на нём программирую, время от времени, и довольно неплохо его уже знаю. Замечательный, на мой взгляд, язык. Этакий «Си с человеческим лицом». Особенно интересно добавлено туда ООП, да и параллельные вычисления сделаны хорошо. Единственно — не нравится реализация обработки ошибок через panic/defer.

Язык статический, строгой типизации, компилируемый. Кстати, одна из особенностей языка — исключительно быстрая компиляция.

Некоторые ребята считают, что он похож на «Паскаль». Думаю это из-за конструкции „:=“, которая означает в Гоу «создать локальную переменную с типом присваемого результата», а эти ребята ничего кроме этой конструкции из «Паскаля» не помнят.
package main
import "strconv"

func main() {
    for i := 99; i>0; i-- {
        b := bottles(i) + " of beer"

        println(b + " on the wall, " + b + ".")
        println("Take one down and pass it around, " + bottles(i-1) + " of beer on the wall.\n")
    }

    println("No more bottles of beer on the wall, no more bottles of beer.")
    println("Go to the store and buy some more, 99 bottles of beer on the wall.")
}

func bottles(beer int) string {
    switch (beer) {
        case 0:
            return "no bottles"
        case 1:
            return "1 bottle"
    }

    return strconv.Itoa(beer) + " bottles"
}
47. КуМир — очередной неинтересный язык программирования «Комплект учебных Миров или Миры Кушниренко».

В 1995 году «КуМир» (о ужас!) был рекомендован Министерством образования РФ в качестве основного учебного материала по курсу «Основы информатики и вычислительной техники» на основе учебника А. Г. Кушниренко, Г. В. Лебедева и Р. А. Свореня.

Совершенно неинтересно про него рассказывать, если честно, хотя среда разработки очень неплоха в плане диагностики ошибок.
| написал Евгений Степанищев bolknote.ru

алг песня про пиво
нач
    цел пиво
    нц для пиво от 99 до 1 шаг -1
        вывод сколько пива(пиво), ' on the wall, ', нс
        вывод 'Take one and pass around,', нс
        вывод сколько пива(пиво-1), ' on the wall.', нс, нс
    кц
    вывод "No more bottles of beer...", нс
    вывод "Go to the store and buy some more...", нс
    вывод "99 bottles of beer."
кон

алг лит сколько пива(цел пиво)
нач
    если пиво = 0 то
        знач:="No"
    иначе
        знач:=цел_в_лит(пиво)
    все

    знач:=знач + ' bottle'

    если пиво <> 1 то
        знач:=знач+'s'
    все
кон
46. gnuplot — программа для построение графиков, имеющая довольно развитый язык программирования. Основная особенность — отсутствие циклов, хотя доступна их эмуляция — через команду перезагрузки файла (reread).

Программа, выводящая песню о пиве (beer.gp)
# Написал Евгений Степанищев

bottles(beer) = beer == 1 ? '1 bottle' : beer ? sprintf('%d bottles', beer) : 'no bottles'

if (!exists("beer")) beer=99
print bottles(beer), " of beer on the wall, ", bottles(beer)," of beer\n",\
      "Take one and pass it around,"

beer=beer-1

print bottles(beer)," of beer on the wall.\n"

if (beer>0) reread

print "No more bottles of beer on the wall, no more bottles of beer.\n", \
"Go to the store and buy some more, 99 bottles of beer on the wall."
45. Windows Powershell. Наконец-то в Windows появился мощный, красивый язык командной строки. Язык построен на конвеерах, где по конвееру передаётся не просто текст, а объекты. Особый интерес представляет интеграция с .NET Framework и WMI.

Язык просто изучается, имеет понятную структуру и широкие возможности. Я посмотрел первую версию языка, но уже доступна вторая версия оболочки.

Программа, выводящая песню о пиве (beer.ps1)
# Написал Евгений Степанищев aka BOLK

function bottles([int]$beer) {
    switch ($beer) {
        0       { "no bottles" }
        1       { "1 bottle" }
        default { "$beer bottles" }
    }
}

99..1 | ForEach-Object {
    $bottles = (bottles $_) + ' of beer'

    $bottles + ' on the wall, ' + $bottles + '.'
    'Take one down and pass it around, ' + (bottles($_-1)) + " of beer on the wall.`n"
}

'No more bottles of beer on the wall, no more bottles of beer. 
Go to the store and buy some more, 99 bottles of beer on the wall.'
44. РАЯ (русский алгоримический язык). Язык, придуманный академиком Ершовым для обучения детей программированию. Все названия на русском языке, что, впрочем, совершенно не отвлекает. Для написания программы я использовал падучую реализацию языка с сайта «Инфомир».

Особо о языке сказать нечего, разве что понравились многословные имена переменных, процедур и функций (можно записывать через пробелы), показалось интересным наличие исполнителей (вроде известной «черепашки») и не понравилось отсутствие конкатенации строк и операции «неравно» (в документации я этого не нашёл).
| Написал Евгений Степанищев aka BOLK
алг
нач
    цел сколько пива

    нц для сколько пива от 99 до 1 шаг -1
        выводим пиво(сколько пива, " on the wall, ") 
        выводим пиво(сколько пива, ".")

        вывод нс, "Take one and pass it around,", нс
        выводим пиво(сколько пива, " on the wall.")
        вывод нс, нс
    кц

    вывод "No more bottles of beer:", нс
    вывод "Go to the store and buy some more:", нс
    вывод "99 bottles of beer." 
кон

алг выводим пиво(цел пива, лит окончание)
нач
    вывод число пива(пива), " bottle"
    если пива > 1 или пива=0
        то вывод "s"
    все
    вывод окончание
кон

алг лит число пива(цел пива)
нач
    если пива=0
        то знач:="No"
        иначе знач:=цел_в_лит(пива)
    все
кон      
43. MS HTML. Конечно, HTML не является языком программирования. Но и на этом языке разметки, применяя особенности Internet Explorer, можно написать песню про пиво. Лишнюю строку пришлось «спрятать» за экран. Работает, естественно, только в Internet Explorer.
<!-- Written by Evgeny "BOLK" Stepanischev -->
<style type="text/css">
    .outer { position: absolute; top: -20px }
    body { background: white; margin: 0; padding: 10px }
    body, table { font-size: 11px; font-family: Tahoma }
    table, td, tr { margin: 0; padding: 0; border-collapse: collapse }
</style>

<body>
<xml id="dataOuter">
<row>
    <d><o>9</o></d>
    <d><o>8</o></d>
    <d><o>7</o></d>
    <d><o>6</o></d>
    <d><o>5</o></d>
    <d><o>4</o></d>
    <d><o>3</o></d>
    <d><o>2</o></d>
    <d><o>1</o></d>
</row>
</xml>

<xml id="dataInner">
<row>
    <d><i>9</i></d>
    <d><i>8</i></d>
    <d><i>7</i></d>
    <d><i>6</i></d>
    <d><i>5</i></d>
    <d><i>4</i></d>
    <d><i>3</i></d>
    <d><i>2</i></d>
    <d><i>1</i></d>
    <d><i>0</i></d>
</row>
</xml>

<xml id="dataInnerSingle">
<row>
    <d><i>9</i><s>s</s></d>
    <d><i>8</i><s>s</s></d>
    <d><i>7</i><s>s</s></d>
    <d><i>6</i><s>s</s></d>
    <d><i>5</i><s>s</s></d>
    <d><i>4</i><s>s</s></d>
    <d><i>3</i><s>s</s></d>
    <d><i>2</i><s>s</s></d>
    <d><i>1</i></d>
</row>
</xml>

<div class="outer">
<table datasrc="#dataOuter">
<tr>
<td>

<table datasrc="#dataInner">
<tr>
<td>
<span datafld="o"></span><span datafld="i"></span>&nbsp;beer bottles
of beer on the wall.<br /><br />
<span datafld="o"></span><span datafld="i"></span>&nbsp;beer bottles
of beer on the wall,
<span datafld="o"></span><span datafld="i"></span>&nbsp;bottles of beer.<br />
Take one and pass it around,<br />
</td>
</tr>
</table>

</td>
</tr>
</table>

<table datasrc="#dataInnerSingle">
<tr>
<td>
<span datafld="i"></span>&nbsp;beer
bottle<span datafld="s"></span> of beer on the wall.<br /><br />
<span datafld="i"></span>&nbsp;beer
bottle<span datafld="s"></span> of beer on the wall,
<span datafld="i"></span>&nbsp;bottle<span datafld="s"></span>
of beer.<br />
Take one and pass it around,<br />
</td>
</tr>
</table>

No beer bottle of beer on the wall.<br />
<br />
No more bottles of beer...<br />
Go to the store and buy some more...<br />
99 bottles of beer.
</div>
</body>
42. TheBAT! На языке макросов почтового клиента TheBAT! 1.63b8. Ужасный язык. Плохо выглядит, трудно читается. Есть регулярные выражения, ветвление и вызов быстрых шаблонов (некий эквивалент процедур). Только в последней версии появились определяемые пользователем переменные (конструкция %_nnn или %SETnnn). Если будете испытывать, пустые строки в конце шаблонов нужно удалить.
* основной шаблон *
%REM="Beer song. Written by Evgeny Stepanischev"
%_BE1=9%_BE2=9%QINCLUDE="beer_loop"%-
No more bottles of beer:
Go to the store and buy some more:
99 bottles of beer.

* быстрый шаблон beer_loop *
%QINCLUDE="print_beer" on the wall, %QINCLUDE="print_beer".
Take one and pass around,
%IF:"%_BE2"="0":'%_BER=%_BE1%QINCLUDE="dec"%_BE1=%_BER%_BE2=9':'%_BER=%_BE2%QINCLUDE="dec"%_BE2=%_BER'%-
%QINCLUDE="print_beer" on the wall.

%IF:"%_BE1%_BE2"="00":"":'%QINCLUDE="beer_loop"'%-

* быстрый шаблон print_beer *
%IF:"%_BE1%_BE2"="00":'No':'%IF:"%_BE1">"0":"%_BE1%_BE2":"%_BE2"'%-
bottle%QINCLUDE="beers" of beer%-

* быстрый шаблон beers *
%IF:"%_BER"="1":"":"s"%-

* быстрый шаблон dec *
%IF:"%_BER"="1":"%_BER=0":""%-
%IF:"%_BER"="2":"%_BER=1":""%-
%IF:"%_BER"="3":"%_BER=2":""%-
%IF:"%_BER"="4":"%_BER=3":""%-
%IF:"%_BER"="5":"%_BER=4":""%-
%IF:"%_BER"="6":"%_BER=5":""%-
%IF:"%_BER"="7":"%_BER=6":""%-
%IF:"%_BER"="8":"%_BER=7":""%-
%IF:"%_BER"="9":"%_BER=8":""%- 
41. FOCAL. Название языка произошло от сокращения Formula CALculator. В настоящее время язык, можно сказать, умер - в интернете мне с большим трудом удалось найти его описание. Ни одной действующей версии компилятора или интерпретатора языка мне найти не удалось.

Что интересно в языке - нумерация строк. Она двойная. Строки огранизуют группы с внутренней нумерацией, к которым (группам) можно обращаться при помощи различных конструкций. Другая интересная особенность - все операторы можно сокращать. Например, вполне можно писать "COMMENT" как "C", а "FOR" - как "F".

Как я сказал, компилятора или интерпретатора мне найти не удалось, так что пришлось писать программу по теории. В частности, по скудной литературе мне не удалось понять как должна работать функция FSBR (вызов группы строк как функции), поэтому пришлось определять функции другим путём.

Уже после выхода этой песни, со мной связался Алексей Томин и привёл описание функции FSBR. Вот, что он пишет: FSBR позволяет определить функцию с одним аргументом (с использованием & как параметра). Самое смешное- возможна рекурсия.

Пример - вычисление факториала.
11.1 I (&-1) 11.3,11.3,11.2
11.2 S &=&*FSBR(11,&-1)
11.3 R

Программа, выводящая песню о пиве (beer)
1.10 COMMENT Beer song. Written by Evgeny Stepanischev
1.20 FOR I=99, -1, 1; DO 2
1.30 TYPE "No more bottles of beer...", !
1.40 TYPE "Go to the store and buy some more...", !
1.50 TYPE "99 bottles of beer.", !
1.60 QUIT

2.10 SET B=1; DO 3; TYPE " on the wall, "; DO 3
2.20 TYPE !, "Take one and pass around,", !
2.30 SET B=2; DO 3; TYPE " on the wall.", !

3.10 DO 4.10; TYPE " of beer"; RETURN

4.10 IF (I-B) 4.20, 4.30, 4.40
4.20 TYPE "No bottles"; RETURN
4.30 TYPE "1 bottle"; RETURN
4.40 TYPE %4.00, I, "bottles"; RETURN
40. Refal. Литературы по этому языку достаточно, так что, если возникнет заинтересованность - поищите в интернете. Пожалуй, описывать я его не буду, лишь приведу небольшую выдержку из учебника.

Рефал - язык манипулирования символьными объектам: текстами, формулами, программами и т.п. Программа на Рефале состоит из функций, которые могут определяться друг через друга, т.е. рекурсивно. Отсюда и название: Алгоритмический язык Рекурсивных Функций. Язык Рефал был создан В. Турчиным в качестве метаязыка для описания семантики других языков. Язык определения функций Рефала, основанный на понятиях образца и результатного выражения, чрезвычайно прост и компактен. Образцы - [..] в сжатой и наглядной форме обеспечивают как запись условий на вид аргумента, так и разбиение аргумента на составные части.

Программа, выводящая песню о пиве (beer.ref):
** Beer song. Written by Evgeny Stepanischev

Pr   {
     e1 = <PRINTLN! *STDOUT e1>;
     };

S    {
     1  = ;
     e1 = 's';
     };

Beer {
     0 = 'No bottles of beer';
     e1, <S e1>: e2 = e1 ' bottle' e2 ' of beer';
     };

Beers
    {
    e1 (e2), <Beer e1>: e.beer =
        <Pr e.beer ' on the wall, ' e.beer '.'>
        <Pr 'Take one and pass around,'>
        <Pr <Beer e2> ' on the wall.'>
        <Pr>;
    };

Start
    {
    0  = <Pr 'No more bottles of beer...'>
         <Pr 'Go to the store and buy some more...'>
         <Pr '99 bottles of beer.'>;

    e1, <- e1 1>: e2  = <Beers e1 (e2)> <Start e2>;
    };

$EXEC Start 99;
39. TBC (Tokiwa BASIC Compiler). Эта бесплатная версия компилятора является урезанной версией коммерческого компилятора TWK-86BC и написал её японец Tokiwa.

Компилятор умеет компилировать код в COM и DOS EXE-файлы и интересен тем, что имеет интеграцию со встроенным ассемблером и довольно развитый интересный синтаксис, основанный на языке BASIC. Например, присутствует оператор DefInt, который сообщает компилятору, что переменные, начинающиеся с заданных оператором букв, имеют целочисленный тип.

Есть блочные конструкции, операторы обработки ошибок, выбора альтернативы (on ... goto ...), поддержка строк и меток, в связи с чем поддерживаются как обычные процедуры и функции, так и переходы по номерам строк. Предусмотрены операторы ввода-вывода для работы с устройствами DOS и файлами и многое другое.

Кстати, что неприятно удивило - возвращаемым значением для процедур и функций (кстати, можно сказать, что процедуры и функции тут различаются только ключевыми словами) может быть только числовое значение.

Программа, выводящая песню о пиве (beer.tkw)
* Beer song. Written by Evgeny Stepanischev

Integer I
Character S

For I=99 To 1 Step -1
    Call Beer(I)

    Print S; " on the wall, ";S;"."
    Print "Take one and pass around,"

    Call Beer(I-1)
    Print S; " on the wall." : Print
Next I

Print "No more bottles of beer..."
Print "Go to the store and buy some more..."
Print "99 bottles of beer."

SubRoutine Beer(I)
    Integer I

    If I=0 Then S="No" Else S=Str$(%1I I)
    S=S+" bottle"

    If I<>1 Then S=S+"s"

    S=S+" of beer"

    Return
SubEnd


End
38. XSLT. Язык преобразований одного XML-документа в другой, основанный на XML же. Написано о нём достаточно много, так что останавливаться на нём не буду. Это, в отличие от большинства языков, на которых я программировал - декларативный язык. Строго говоря, XSLT мёртв без другого языка - XPath, языка выборки. С его помощью, например, выполняются все вычисления. В парсерах первых версий нет циклов, что кажется несколько странным, так что мне пришлось использовать рекурсию. Кстати, наиболее странное в XSLT другое - однажды объявленная переменная больше не может менять своего значения. Это ограничение обходят при помощи рекурсии и использования локальных переменных.

Запустить скрипт на выполнение можно, сохранив листинг в файл beer.xml и открыв его браузером Internet Explorer.

Программа, выводящая песню о пиве (beer.xml)
<?xml version="1.0"?>
<?xml-stylesheet type="text/xsl" href="#beer"?>

<!-- Beer song. Written by Evgeny Stepanischev -->

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
id="beer">
<xsl:output method="html"/>
<xsl:strip-space elements="*"/>

<xsl:template name="beer">
  <xsl:param name="n"/>
  <xsl:choose>
    <xsl:when test="boolean($n)">
      <xsl:value-of select="$n"/>
    </xsl:when>
    <xsl:otherwise>
      No
    </xsl:otherwise>
  </xsl:choose>
  <xsl:text> bottle</xsl:text>

  <xsl:if test="boolean($n - 1)">
    <xsl:text>s</xsl:text>
  </xsl:if>
</xsl:template>

<xsl:template name="while" match="/">
  <xsl:param name="i" select="99"/>
  <xsl:choose>
    <xsl:when test="$i != 0">
      <xsl:variable name="str">
        <xsl:call-template name="beer">
          <xsl:with-param name="n" select="$i"/>
        </xsl:call-template>
      </xsl:variable>

      <xsl:value-of select="$str"/>
      <xsl:text> on the wall, </xsl:text>
      <xsl:value-of select="$str"/>
      <xsl:text> of beer.</xsl:text><br />
      <xsl:text>Take one and pass around,</xsl:text><br />
      <xsl:call-template name="beer">
          <xsl:with-param name="n" select="$i - 1"/>
      </xsl:call-template>
      <xsl:text> on the wall.</xsl:text><br /><br />

      <xsl:call-template name="while">
        <xsl:with-param name="i" select="$i - 1"/>
      </xsl:call-template>
    </xsl:when>
    <xsl:otherwise>
      No more bottles of beer...<br />
      Go to the store and buy some more...<br />
      99 bottles of beer.
    </xsl:otherwise>
  </xsl:choose>
</xsl:template>

</xsl:stylesheet>
37. JavaScript for Adobe Photoshop (Photoshop 7.0 Scripting plug-in v.1.0.2a). В Adobe Photoshop с версии 7.0 появились полноценные скриптовые языки. Если верить руководству можно использовать три языка - JavaScript, VBScript и AppleScript.

Описывать JavaScript мне не интересно - базовые конструкции стандартные (включая блок "try"), добавлены лишь специфические объекты для управления всем тем, что есть в Photoshop, соответственно и объектная модель отличается от той, что принята, например, в браузерах.

Одним словом - полное управление всем, до чего можно дотянуться в бесконечных меню и опциях Adobe Photoshop (включая фильтры), из скриптового языка. Грандиозные возможности для дизайнеров, пробующих себя в программировании, или программистов, пытающихся заняться дизайном. :)

Программа, выводящая песню о пиве (beer.js)
preferences.rulerUnits = Units.POINTS
preferences.typeUnits  = TypeUnits.POINTS

var docRef = documents.add(640, 480)
displayDialogs = DialogModes.NO

var textColor = new SolidColor
textColor.rgb.red = textColor.rgb.green = textColor.rgb.blue  = 0

var TextLayer = docRef.artLayers.add()
TextLayer.kind = LayerKind.TEXT;

TextLayer.textItem.font     = "Tahoma"
TextLayer.textItem.position = Array(10, 10)
TextLayer.textItem.size     = 12
TextLayer.textItem.color    = textColor

var content = ''

function WriteLn(str)
{
    content += '\r'+str
}

function PrintBeer(n)
{
    return (n ? n : 'No') + ' bottle' + (n-1 ? 's' : '') + ' of beer'
}

for (i = 99; i>0;)
{
    WriteLn (PrintBeer(i) + ' on the wall, '+PrintBeer(i)+'.')
    WriteLn ('Take one and pass around,')
    WriteLn (PrintBeer(--i) + ' on the wall.')
    WriteLn ('')
}

WriteLn ('No more bottles of beer...')
WriteLn ('Go to the store and buy some more...')
WriteLn ('99 bottles of beer.')

TextLayer.textItem.contents = content
docRef = textColor = TextLayer = null
36. Nullsoft (SuperPiMP|Scriptable) Install System. NSIS - настраиваемый инсталлятор от компании Nullsoft, позволяющий создать пакет для инсталляции и деинсталляции вашего собственного продукта. Выходной файл представляет собой обычную программу. Для сжатия данных NSIS может использовать алгоритмы Zip и Bzip2, так что весь код получается довольно компактным.

Весь процесс установки и удаления продукта описывается на собственном языке программирования, где есть опции управления внешним видом инсталлятора, команды использования внешних плагинов, поддержки нескольких языков, команды предпроцессора и собственно язык с поддержкой функций, секций, ветвления, файлового ввода-вывода. Язык поддерживает так же несложную обработку событий в виде callback-функций с зарезервированными именами.

Я использовал версию 2.0b2. Язык инсталлятора крайне простой, поэтому не поддерживает локальных переменных и параметров у пользовательских функций - вместо них приходится использовать глобальные пользовательские переменные (их 20 штук) или стек. Кстати, и параметры плагинам передаются именно через стек.

Все имена переменных начинаются с доллара, программист для своих собственных целей может использовать лишь двадцать переменных - $0..$9, $R0..$R9, переменные не типизированы, в строках выполняется интерполяция, в качестве ограничителей строк подходят любые кавычки. Ветвление выполняется командами сравнения, которые в качестве аргумента принимают три ссылки, по одной из которых происходит переход в зависимости от результата сравнения.

Операции с числами так же выглядят несколько неожиданно. Вообще, даже прочитав полностью документацию, без примеров достаточно просто оставить без внимания некоторые возможности, которые становятся очевидными при просмотре примеров. Так что будете писать инсталлятор для своего продукта - загляните ещё и в примеры.

В любом случае, NSIS - достаточно надежный продукт, появился он не один год назад и используется, например, для инсталляции достаточно известного проигрывателя WinAMP.

Программа, выводящая песню о пиве (beer.nsi)
; Beer song.  Written by Evgeny Stepanischev
Name "Beer song"
Caption "Beer song"
OutFile "beer99.exe"
BrandingText "Beer song (Evgeny Stepanischev)"
ShowInstDetails show

!macro c
    StrCpy $2 ""
    Call PrintBeer
!macroend

Function PrintBeer
    IntCmp $1 0 no "" ""
    StrCpy $2 "$2$1"
    Goto +2
no:
    StrCpy $2 "$2No"
    StrCpy $2 "$2 bottle"
    IntCmp $1 1 nos "" ""
    StrCpy $2 "$2s"
nos:
    StrCpy $2 "$2 of beer"
FunctionEnd

Section ""
    StrCpy $1 99

loop:
    !insertmacro c
    StrCpy $2 "$2 on the wall, "
    Call PrintBeer
    DetailPrint "$2."
    DetailPrint "Take one and pass around,"
    IntOp $1 $1 - 1

    !insertmacro c
    DetailPrint "$2 on the wall."
    DetailPrint ""
    IntCmp $1 0 "" loop loop

    DetailPrint "No more bottles of beer..."
    DetailPrint "Go to the store and buy some more..."
    DetailPrint "99 bottles of beer."

SectionEnd
35. Pocket Basic 1.00 для Casio PV. Несмотря на то, что его автор, Petr Vlcek называет этот язык Бейсиком, Бейсиком он не является. Достаточно хотя бы взглянуть на синтаксис, если это для кого-то не аргумент, то скажу, что каждый элемент строки является число от -128 до 127, над которыми можно производить обычные арифметические действия, например вот так: ASSIGN text<a+1>=text<a+1>+2. Для того, чтобы работать со элементами строки, как с символьными значениями, применяется модификатор точка (".").

Язык довольно минималистский (например, из операторов ввода присутствует только TOUCH, позволяющий узнать в каком месте экрана было произведено касание, в функцию нельзя передать параметр и так далее), а потому малораспространенный. Несмотря на это язык мне понравился, своей простотой и, если так можно выразиться, средой разработки.

В отличие от OWBasic, где для редактирования программ используется встроенное в ОС приложение Memo, Pocket Basic предоставляет собственную среду для создания программ. Реализация имеет массу недостатков, в частности, встроенная клавиатура не содержит национальных символов, нет возможности переименования файлов и так далее, но есть и достоинства. Большим достоинством среды Pocket Basic является возможность набора операторов за один клик.

Каждый оператор языка начинаются с уникальной буквы, так что если редактор ждет ввода оператора, при нажатии на нужную букву оператор вводится целиком. Такой подход потребовал от создателя языка некоторых жертв, например блочный оператор IF выглядит довольно неожиданно, его полная конструкция выглядит, как IF - ELSE - CONTINUE. Другим достоинством среды является возможность использования колеса PV для передвижения по тексту.

Теперь, что касается программы, которая получилась в конечном счете. Поскольку документация весьма скудная, да еще и на немецком я не смог узнать если ли в языке условие «неравно». Испробовав все возможные варианты, я пришел к выводу, что нету. В конце цикла я использую очистку экрана перед выводом следующей фразы, у Pocket Basic'a есть серьезные проблемы со скроллингом, так что, чтобы избежать мусора на экране мне пришлось просто очищать экран. Как видно у программы отсутствует форматирование отступом, причина - среда разработки не позволяет производить такое форматирование.

Программа, выводящая песню о пиве (Beer)
! Beer song. Written by Evgeny Stepanischev
PROC beer
IF b=0
WRITE "No"
ELSE
WRITE b
CONTINUE
!
WRITE " bottle"
IF b=1
ELSE
WRITE "s"
CONTINUE
!
WRITE " of beer"
RETURN
!
!
VAR INT b
ASSIGN b=99
!
FOR b>0
USE beer
WRITE " on the wall, "
USE beer
WRITE "."l
WRITE "Take one down and pass around."l
ASSIGN b=b-1
USE beer
WRITE "."
SLEEP 4
BOX
ASSIGN posy=0
ASSIGN posx=0
NEXT
!
WRITE "No more bottles of beer..."l
WRITE "Go to the store and buy some more..."l
WRITE "99 bottles of beer."
SLEEP 20
34. Паркетчик. Весьма забавный язык, предназначенный для обучения детей программированию. Очень напоминает переведенный Паскаль, если не считать сишных блочных конструкций. Если бы у меня были дети я бы для их обучения, на первых порах, возможно, выбрал бы этот язык.

Кроме основых конструкций ветвления, циклов и поддержки подпрограмм, язык предоставляет средства управления «Паркетчиком» - неким средством рисования цветных квадратов на ограниченом поле. В программе я специально разбил содержимое цикла на две фазы, чтобы показать, как «Паркетчика» можно использовать, например, для контроля за четностью.

Из недостатков.

Язык, конечно, не предназначен для серьезного программирования, но это не оправдание для того, чтобы не делать поддержку строк и чисел с плавающей точкой.

Насколько я понял из файлов примеров, в программе нет циклов с произвольным шагом, приходится для этого использовать циклы «пока».

Кроме того, в бесконечном цикле «Паркетчик» умудрился намертво завесить мою Windows XP. Никакой возможности прервать программу я не нашел, компьютер ни на что не реагировал.

Скрипт, выводящий песню о пиве (beer.prg)
цел пиво;

Программа {
  пиво:=198;
  Делать пока (пиво>0) { 
    если (слева стена) то {
        если (пиво=2) то {
          Сообщить "1 bottle of beer on the wall, 1 bottle of beer."
        } иначе
        {
          Сообщить пиво/2, " bottles of beer on the wall, ",
          пиво/2, " bottles of beer."
        };
        
        Сообщить "Take one down, pass it around."
        Шаг вправо;
    } иначе
    {
      если (пиво=2) то {
        Сообщить "1 bottle of beer on the wall."
      } иначе {
        если (пиво>1) то {
          Сообщить пиво/2, " bottles of beer on the wall."
        } иначе {
          Сообщить "No bottles of beer on the wall.";
        };
      };
    
      Шаг влево;
    };
    
    пиво:=пиво-1;
  };
  
  Сообщить "No more bottles of beer...";
  Сообщить "Go to the store and buy some more...";
  Сообщить "99 bottles of beer.";
}
33. OW-BASIC - наиболее популярный, среди пользователей PV-S450, диалектов языка BASIC. Ему присущи все основные черты небольших современных интерпретаторов этого языка - наличие процедур с локальными параметрами и параметрами по указателю, блочные конструкции, функции работы со строками и отсутствие необходимости нумеровать строки.

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

Программа, выводящая песню о пиве (! beer)
! beer
! Beer song. Written by Evgeny Stepanischev

PROC beer i, VAR s$
  IF i>0 THEN
    s = STRING(i)
  ELSE
    s = "No"
  ENDIF

  s = s+" bottle"

  IF i<>1 THEN
    s = s+"s"
  ENDIF
  s = s+" of beer"
ENDP

FOR i=0 TO 98
  beer 99-i, s$
  ? s;" on the wall, ";s;"."
  ? "Take one and pass around,"
  beer 98-i, s
  ? s;" on the wall.":? ""
NEXT

? "": ? "No more bottles of beer..."
? "Go to the store and buy some more..."
? "99 bottles of beer."
32. Parrot. Очень молодой, его первый компилятор в байт-коды появился 10 сентября (дело происходило в 2001 году - более позднее примечание), язык виртуальной машины для интерпретируемых языков. Насколько я понимаю, разрабатывался специально для Perl6.

Язык по базовым конструкциям беднее ассемблера - нет ни одной конструкции цикла, все они заменяются условными переходами, ограниченное количество переменных (по 32 на каждый тип переменной), зато есть поддержка функций (параметры передаются через стек), операций с файлами, операторов ввода-вывода и так далее. Поскольку интерпретатору около месяца, диагностика ошибок еще весьма бедная, иногда единственное сообщение, которое получаешь на экран - «Segmentation fault». :)

Скрипт, выводящий песню о пиве (beer.pasm)
# Beer song. Written by Evgeny Stepanischev

        set      I1, 99
        branch   MAIN

beer:   if       I1, _NZERO
        print    "No"
        branch   _I1_EL

_NZERO: print    I1
_I1_EL: print    " bottle"
        eq       I1, 1, _NO_S

        print    "s"
_NO_S:  ret



MAIN:   bsr      beer
        print    " of beer on the wall, "
        bsr      beer
        print    " of beer."
        print    "\nTake one and pass around,\n"

        dec      I1

        bsr      beer
        print    " on the wall.\n\n"

        if       I1, MAIN

        print    "No more bottles of beer...\n"
        print    "Go to the store and buy some more...\n"
        print    "99 bottles of beer.\n"

        end
31. Bascom-8051 (версия два). Язык для программирования микроконтролеров, как следствие специализации имеет операторы для работы с битовыми типами, LCD, внешней памятью, таймерами и сигналами и так далее.

Расшифровывается BASCOM, как "BASic COMpilator". По моему мнению, он если и похож на Бейсик, то весьма отдаленно. Язык имеет ряд тонких особенностей, с которыми мне пришлось столкнуться при написании даже такой простой программы: оператор for с ключевым словом downto не требует указания отрицательного step, переменная "B" зарезервирована, процедуры надо сначала объявлять, потом только использовать, процедуры являются входимыми (возврат осуществляется по стеку) и программу перед их телом надо останавливать, аргументы функций ассоциируются с переданной переменной по имени, т.е. передав значение процедуре printbeer я присвою значение переменной beer. И т.д. и тому подобное.

Не говоря уж о том, что строку перед конкатенацией с самой собой надо сохранять, а передача параметров каким-то образом контролируется по имени. Что было последней каплей - отсутствие методов описания функций, приходится обходиться процедурами с глобальными переменными. :) Как-то я отвык от подобного. Пойти написать что-нибудь на ассемблере что ли? Кстати, в этом языке, как и предыдущем есть возможность использования ассемблерных комманд.

Под Windows существует эмулирующий компилятор со средой разработки, поддерживающий пошаговое исполнение, точки останова и вывод отладочной информации. Я пользовался демо-версией, которую нашел на одном польском сайте.

Программа, выводящая песню о пиве (beer.bas)
' Written by Evgeny Stepanischev

Dim Beer As Byte , Res As String * 10
Declare Sub Printbeer(beer As Byte)

Beer = 2

While Beer > 0
   Call Printbeer(beer)

   Print Res ; " on the wall, " ; Res ; "."
   Print "Take one down, pass it around."

   Decr Beer
   Call Printbeer(beer)

   Print Res ; " on the wall."
   Print
Wend

Print "No more bottles of beer..."
Print "Go to the store and buy some more..."
Print "99 bottles of beer."

End

Sub Printbeer(beer As Byte)
   Dim Tmp As String * 10

   If Beer = 0 Then Res = "No" Else Res = Str(beer)

   Tmp = Res + " bottle" : Res = Tmp
   If Beer <> 1 Then Res = Tmp + "s"

   Tmp = Res : Res = Tmp + " of beer"
End Sub
30. Базовый SIMPLE. Необычный язык с интересными синтаксическими конструкциями, поддержкой списков (как в LISP), кортежей, функций с произвольным количеством параметров, псевдоассемблера, предпроцессора и фреймовых структур. Это язык со строгой типитизацией и чувствительный к регистру.

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

Скрипт, выводящий песню о пиве (beer.smp)
// Written by Evgeny Stepanischev

define beer(n) {
    cond {
         n>0 do princ(n);
         n<1 do princ("No");
    };

    princ(" bottle");
    if (n<>1) {princ("s");};
    princ(" of beer");
};

define main() {
    declare b=99;

    lcond {
        b=0 do {
            print("No more bottles of beer...");
            print("Go to the store and buy some more...");
            print("99 bottles of beer.");
        };

        do {
            beer(b); princ(" on the wall, ");
            beer(b); print(".");
            print("Take one down, pass it around.");

            b:=b-1;
            beer(b); print(" on the wall.");
            print("");
        };
    };
};
29. Euphoria. Очень интересный язык с возможностью оперирования списками, как базовыми типами. Например, их можно складывать, сравнивать и вообще производить любые операции, как над атомарными типами. Единственное, что для меня оказалось странным, это тот факт, что атомарные типы не являются частным случаем списков (последовательностей).

В общем не знаю чем, но язык мне понравился. :) Кстати, в языке, насколько я понимаю, есть разница между операция "запятая" (разделение элементов в списке) и "запятая с пробелом" (разделение аргументов функции). Свое предположение я не проверял (а описание читал очень бегло), но, если будете писать программы на этом языке, будьте осторожны с запятой.

Для этого языка существуют интерпретаторы под DOS, Windows и Linux, а так же транслятор в язык C. Описание языка распространяется вместе с интерпретатором.

Программа, выводящая песню о пиве (beer.ex)
-- Written by Evgeny Stepanischev
integer beer
beer = 99

procedure PrintBeer (integer b)
    if b then
        printf (1, "%d", b)
    else
        puts (1, "No")
    end if

    puts (1, " bottle")

    if b!=1 then puts (1, 's') end if
end procedure

while beer>0 do
    PrintBeer(beer) puts (1, " of beer on the wall, ")
    PrintBeer(beer) puts (1, " of beer.\n")
    puts (1, "Take one down, pass it around.\n")

    beer = beer - 1
    PrintBeer(beer) puts (1, " of beer on the wall.\n\n")
end while

puts (1, "No more bottles of beer...\n")
puts (1, "Go to the store and buy some more...\n")
puts (1, "99 bottles of beer.")
28. RW1. Язык используется в основном для программирования виртуальных роботов, между которыми проводятся такие же виртуальные бои.

В языке есть возможность описания пользовательских функций, но я не смог ими воспользоваться из-за... отсутствия в языке символьных типов. Хорошо хоть оператор SAY понимает строки, причем с возможностью вывода значений переменных.

О самом интерпретаторе. Программы прекомпилируются в собственную систему байт-кодов, после чего исполняются интерпретатором. У прекомпилятора, который и выполняет проверку синтаксиса очень бедные возможности диагностики, так что мне приходилось подолгу ломать голову на тем, почему программа не работает. В частности из-за конструкции «var--», которая в языке существует, но не может быть применена, как самостоятельная конструкция.

И, наконец, что касается вечного цикла в конце. Программы на языке RW1 (по крайней мере, что касается описания роботов, представляет собой зацикленную программу и вечный цикл нужен для того, что бы программа не начала выполняться заново.

Скрипт, выводящий песню о пиве (beer.rw1)
% Written by Evgeny Stepanischev

ROBOT "Beer"
AUTHOR "Evgeny Stepanischev"

main()
{
  beer=99
  while(beer>0)
  {
     IF(beer>1) SAY "&BEER bottles of beer on the wall, &BEER bottles of beer."
     ELSE SAY "&BEER bottle of beer on the wall, &BEER bottle of beer."

     SAY "Take one down, pass it around."

     beer = beer-1

     IF(beer>1) SAY "&BEER bottles of beer on the wall."
     ELSE
     {
        IF(beer) SAY "&BEER bottle of beer on the wall."
        ELSE SAY "No bottles of beer on the wall."
     }

     SAY ""
     
  }

  SAY "No more bottles of beer..."
  SAY "Go to the store and buy some more..."
  SAY "99 bottles of beer."

  WHILE(1)
  {
  }
}
27. MACS (MACrotestSoftware). Язык управления стендом и описания технологического процесса ремонта электронных плат. Для этой цели в языке есть весьма специфические конструкции. Из недостатков языка — отсутсвие возможности описания пользовательских процедур и функций и наличие всего двух типов данных - целых чисел и строк. Из глюков интерпретатора — необходимый последний перевод строки.

Программа, выводящая песню о пиве (beer.mcs)
// Written by Evgeny Stepanischev

cls
 string beer
 string w = " on the wall"
 def b

 for def i=198 to i > 0, i=i-1
 do
    b = i/2

    if b beer = b else beer = "No" endif
    beer = beer+" bottle"
    ifs b!=1 beer = beer+"s"

    if i&1
       beer w ".\r\n\r\n"
    else
       beer w ", " beer "."
       "\r\nTake one down and pass it around,\r\n"
    endif

 done


 "No more bottles of beer...\r\n"
 "Go to the store and buy some more...\r\n"
 "99 bottles of beer."

 pause
26. RBASIC. Язык RBASIC предназначен для того, что бы предоставить пользователю возможность быстро создавать свои программы для решения задач по ведению радиомониторинга с помощью широкодиапазонных компьютерных сканирующих приемников фирмы Winradio Communications.

Основа языка - BASIC к которому добавлены некоторые конструкции и специальные функции для управления приемниками, такие например, как управления шумоподавителем, громкостью, модуляцией и т.п.

Скрипт, выводящий песню о пиве (beer.rbp)
# Beer song. Written by Evgeny Stepanischev
LET b=99
LET s$=""
FOR i=99 TO 1 STEP -1
GOSUB @beer     
PRINT s$+" on the wall, "+s$+" of beer."
PRINT "Take one and pass around,"
b = b-1
GOSUB @beer
PRINT s$+" on the wall."
PRINT ""    
NEXT i
     
PRINT "No more bottles of beer..."
PRINT "Go to the store and buy some more..."
PRINT "99 bottles of beer."
     
END
       
@beer
LET s$=""
IF b>0 THEN s$ = s$ + str$ (i) ELSE s$ = s$ + "No"
s$ = s$ + " bottle":IF b<>1 THEN s$ = s$+"s"
RETURN
25. Omens (Object manageMENt System). Язык, сочетающий в себе черты C, C++ и Java. Например, конструции он унаследовал от C, принципы работы с указателями и ссылками - из C++, а описания классов - из Java.

В данный момент язык и система разработки (компилятор в платформо-независимый байт-код и интерпретатор) находятся в стадии бета-тестирования. Наверное, поэтому циклы for и while интерпретатор (даже в файлах примеров) выполнять отказался из-за чего мне пришлось использовать рекурсию.

Сам Omens разрабатывался, как платформонезависимая среда со встроенным облегченным механизмом описания и манипулирования сложными данными, в том числе и с базами данных (DB2, Oracle, MS SQL, dBASE, MS Access, ...). Из интересных особенностей - у программы может быть несколько точек входа.

Программа, выводящая песню о пиве (beer.oms)
//  Beer song. Written by Evgeny Stepanischev

class beer {
    private void PrintBeer(byte n) {
        if (n>0)
        system.out.print(lang.ltoa(n)); else
        system.out.print("No");
        system.out.print(" bottle");

        if (n!=1) system.out.print("s");
    }


    private void For(byte i) {
        PrintBeer(i);
        system.out.print(" on the wall, ");
        PrintBeer(i);
        system.out.print(" of beer.");

        system.out.println("Take one and pass around,\n");
        PrintBeer(i-1);
        system.out.print(" on the wall.\n\n");
        if (i>1) For(i-1);
    }


    public void main() {
        For(99);

        system.out.print("No more bottles of beer...");
        system.out.println("Go to the store and buy some more...");
        system.out.println("99 bottles of beer.");
    }
};
24. KiXtart. Язык пакетных файлов. Достаточно простой, наглядный и функциональный. Интересны конструкции вывода на экран и принципы построения функций. Функции (точнее подпрограммы) можно строить при помощи блока Function или, как в BASIC'е, через GOSUB и метки. Что мне понравилось - KiXtart предоставляет большую свободу в форме записи. Так, например, операторы можно разделять переводом строки, табуляциями, пробелами.

Скрипт, выводящий песню о пиве (beer.kix)
; Beer song. Written by Evgeny Stepanischev

Function Beer($n)
  If $n
    $n
  Else
    "No"
  Endif

  " bottle"
  If $n<>1 "s" Endif
EndFunction


FOR $beer = 99 TO 1 STEP -1
  Beer ($beer) " on the wall, "
  Beer ($beer) " of beer."

  ? "Take one and pass around,"

  ? Beer ($beer-1)
  
  " on the wall."??

NEXT

"No more bottles of beer..." ?
"Go to the store and buy some more..." ?
"99 bottles of beer."
23. Ruby. Скриптовый язык, который я посчитла очень похожим на Перл, поэтому писал на нём как на Perl. Отличия есть и существенные, но тем не менее. Как и предыдущем языке, есть префиксные различия между глобальными (начинаются на "$" или "@") и локальными переменными. Из странностей - конструкцию "1?2:3" не удалось заставить работать с локальными переменными. Возможно это особенность языка, но, мне кажется, чисто идеологически обосновать ее трудно.

Скрипт, выводящий песню о пиве.
# Beer song. Written by Evgeny Stepanischev

def Beer (n)
  if n!=0 then
    print n
  else
    print 'No'
  end

  print " bottle"
  print "s" unless n==1
end

$i = 99

while $i>0 do
  Beer ($i)
  print " on the wall, "
  Beer ($i)
  print "\nTake one and pass around,\n"
  $i-=1;
  Beer ($i)
  print " on the wall.\n\n"
end

print <<EOF
No more bottles of beer...
Go to the store and buy some more...
99 bottles of beer.
EOF
22. Miva. Доступ к этому языку я получил чисто случайно. Будем считать, что я нашел распечатки парочки программ на этом языке на улице. Это недалеко от истины, ибо документацию по Miva я в глаза не видел.

Итак Miva - это скриптовый полнофункциональный язык, применяемый исключительно в Веб-программировании. Синтаксис, на мой взгляд, несколько неуклюж, что, впрочем, легко объяснимо способом его внедрения, и неоправданно многословен. Из интересных особенностей - разделение локальных, глобальных и системных (?) переменных через объекты "l", "g" и "s".

Скрипт, выводящий песню о пиве (beer.mv)
<HTML><MIVA STANDARDOUTPUTLEVEL = "text, html, compresswhitespace">

<MvCOMMENT>
| Beer song. Written by Evgeny Stepanischev
</MvCOMMENT>

<MvFUNCTION NAME="Beer" PARAMETERS="n">
<MvIF EXPR = "{ l.n NE 0 }">&[ l.n ]<MvELSE>No</MvIF>
bottle<MvIF EXPR = "{ l.n NE 1 }">s</MvIF>
of beer</MvFUNCTION>

<MvASSIGN NAME = "g.i" VALUE = 99>

<MvWHILE EXPR = "{ g.i GE 1 }">
<MvEVAL EXPR="{ Beer(g.i) }"> on the wall, <MvEVAL EXPR="{ Beer(g.i) }">.<BR>
Take one and pass around,<BR>
<MvASSIGN NAME = "g.i" VALUE = "{ g.i - 1 }">
<MvEVAL EXPR="{ Beer(g.i) }">
on the wall.<BR><BR>

</MvWHILE>

No more bottles of beer...<BR>
Go to the store and buy some more...<BR>
99 bottles of beer.


</HTML>
21. ActionScript5. Внутренний язык Flash5. По виду очень похож на JavaScript (если не считать "add", обязательные точки с запятой и прочие мелочи), даже многие предопределенные объекты те же, но по идеологии - нет. Например, как в JavaScript осуществляется доступ к каким-либо внешним сущностям? Правильно, через коллекции. В ActionScript доступ происходит по имени.

Из интересных особенностей интерпретатора... ActionScript от версии к версии сильно изменяется. Вплоть до несовместимости. Так вот, если интепретатору подсунуть Flash предыдущей версии, он выполняет все необходимые преобразования в ActionScript за программиста, комментируя все свои дейстия.

Скрипт, выводящий песню о пиве.
// Beer song. Written by Evgeny Stepanischev

function PrintBeer (i)
{
    return (i?i:'No') add ' bottle' add (i-1?'s':'') add
    ' of beer';
}


for (i = 99; i>0; i--)
{
    trace ((b=PrintBeer (i)) add ' on the wall, ' add b add '.');
    trace ('Take one down and pass it around,');
    trace (PrintBeer (i-1) add ' on the wall.\n');
};

trace ('No more bottles of beer...\n' add
'Go to the store and buy some more...\n' add
'99 bottles of beer.');
20. PasScript. Можно сказать, что это VIRT со всеми присущими ему особенностями и конструкциями (например, "P << [[ 70, 5], <<P]"), только с синтаксисом Object Pascal. Из глюков интерпретатора я заметил нежелание конструкции "for" работать с переменными типов "byte" и "word", плюс конструкция "writeln" сначала печатает перевод строки и только потом - свой параметр.

Скрипт, выводящий песню о пиве (beer.pas)
// Beer song.  Written by Evgeny Stepanischev

program Beer;
procedure PrintBeer( n: byte );
begin
      if n<>0 then write (n)
      else write ('No');

      write (' bottle');
      if n<>1 then write ('s');

      write (' of beer');     
end;

var
  I: integer;

begin
      for I:=99 downto 1 do
      begin
           PrintBeer (I);
           write (' on the wall, ');
           PrintBeer (I);
           write ('.');
           writeln ('Take one and pass around,');
           writeln ();

           PrintBeer (I-1);
           write (' on the wall.');
           writeln ();
           writeln ();
      end;
      write ('No more bottles of beer...');
      writeln ('Go to the store and buy some more...');
      writeln ('99 bottles of beer.')
end.
19. VIRT. Объекно-ориентированный язык. По синтаксису напоминает Object Pascal, Modula 2, Modula 3 и Oberon. Особенности. Специальные конструкции языка позволяют легко задавать списки и деревья, есть возможность перегрузки операторов "+", "-", "[]" и тому подобных, конструкции обработки исключительных ситуаций, вычисления языковых конструкций и многое другое.

Пара слов о реализации. Отступы в программе осуществляются при помощи пробелов, табуляции интерпретатор не любит, кроме того не любит он пробелов между именем функции и скобками. Но это не самое странное. Реализованный язык, по всей видимости, не дает использовать многобуквенные переменные, по крайней мере внутри функций. Так что, если вдруг, будьте внимательны.

На сайте есть компонент (45$) для Delphi, позволяющий использовать интерпретатор в качестве внутреннего языка для какого-либо проекта.

Программа, выводящая песню о пиве (beer.w).
-- Песня о пиве. Написал Евгений Степанищев

function PrintBeer(n)
    s := ''
    if n<>0 then
        s := s+str(n)
    else
        s := s+'No'
    end
    s := s+' bottle'
    if n<>1 then
        s := s+'s'
    end
return s+' of beer'

-- Main program

    P := 99
    While P Do
        Writeln( PrintBeer( P )+' on the wall, '+PrintBeer( P )+'.' )
        Writeln( 'Take one and pass it around,' )
        P := P-1
        Writeln( PrintBeer( P )+' on the wall.'+EOL() )
    End

    Writeln( 'No more bottles of beer...' )
    Writeln( 'Go to the store and buy some more...' )
    Writeln( '99 bottles of beer.')
return
18. РАПИРА. Точнее некий диалект языка РАПИРА для Конструктора Исполнителей.
Среда разработки и диалект мне не понравились. Не запоминаются положения и размеры окон, расцветка хромает, после вывода ошибки происходит выход, не хватает множества функций, синтаксис, не смотря на заявление разработчика, все-таки частично регистро-зависим и т.д. и т.п.

Сам язык РАПИРА (расшифровывается, как "Расширенный Адаптированный Поплан-Интерпретатор, Редактор, Архив") был придуман, как видно из синтаксиса, в Советском Союзе для обучения программированию в школах. Похоже, что конструктивно представляет из себя простую кальку с Паскаля.

Программа, выводящая песню о пиве (Panupa для Конструктора Исполнителей).
// Песня о пиве. Написал Степанищев Евгений
фун встр (и)
    старш:= и/10
    младш:= и mod 10

    если старш>0
        возврат симв(48+старш)+симв(48+младш)
    иначе
        возврат симв(48+младш)
    всё
кон фун

фун пиво (и)
    если и=0
        стр:= 'No'
    иначе
        стр:= встр (и)
    всё

    стр:= стр+' bottle'
    если и<>1
        стр:= стр+'s'
    всё

    возврат стр
кон фун

проц старт()
    для и от 99 до 1 шаг -1
        печать пиво (и)+' on the wall, '+пиво (и)+'.'
        печать 'Take one and pass it around,'
        печать пиво (и-1)+' on the wall.'
        печать ''
    кц

    печать 'No more bottles of beer...'
    печать 'Go to the store and buy some more...'
    печать '99 bottles of beer.'

кон проц
17. Ox ("Окс") - объектно-ориентированный язык с обширными математическими и статистическими библиотеками. Например, в языке, напрямую, можно перемножать две матрицы или производить инверсию. К другим особенностям можно отнести способность языка импортировать некоторые распростаненные форматы данных. Например, такие типы, как in7, xls, wks, dht, fmt, можно сразу прочитать в матрицу. Синтаксис Ox, по утверждению авторов, похож на языки C, C++ и Java. Интерпретаторы и трансляторы в C этого языка существуют под Windows, MS DOS, Linux, SunOS, Dec-Unix, Irix, HP-UX и IBM AIX. Лично я пользовался бесплатным консольным интерпретатором версии 2.20 под Windows.

Программа на языке Ox.
// Beer song. Written by Evgeny Stepanischev
#include <oxstd.h>

printbeer (const beer)
{
    print (beer?beer:"No", " bottle", beer-1?"s":"");
}


main()
{
    decl beer;

    for (beer = 99; beer > 0;)
    {
         printbeer (beer);
         print(" on the wall, ");
         printbeer (beer);
         print (".\nTake one and pass it around,\n");
         beer--;
         printbeer (beer);
         print (" on the wall.\n\n");
    }

    print ("No more bottles of beer...\n",
    "Go to the store and buy some more...\n",
    "99 bottles of beer.");
}
16. Oberon-2. Язык Оберон был создан автором Паскаля и Модулы-2 Никлаусом Виртом в 1987 году. В 1992 году Вирт и Ханспетер Мёссенбёк добавили в язык ряд новых средств. Так родился Оберон-2.

Считается, что язык это крайне простой и аскетичный. Лично мне он не понравился. Уж не знаю чем. Впечатлил меня транслятор. Использовал я JOB v0.75 С.Свердлова, видимо, по недоразумению, названный компилятором. Интересен он тем, что переводит программу на Оберон-2 в байт-коды Java, т.е. файл с расширением .class, который, в свою очередь, можно запустить на любой Java-машине.

Отсюда и, встречающиеся в листинге, строчки «javalang» и «javalang.PString». Думаю, транслятор этот пригодится Pascal-ориентированным программистам, которым понадобилось написать пару апплетов или классов Java.

Программа, выводящая песню о пиве (Oberon-2).
(* Beer song. Written by Stepanischev E.V.*)

MODULE Beer;

IMPORT javalang, Out;

PROCEDURE PrintBeer( n : INTEGER );
BEGIN
   IF n#0 THEN Out.Int (n,1) ELSE Out.String ("No") END;
   Out.String (" bottle");
   IF n#1 THEN Out.Char ("s"); END;

   Out.String (" of beer");
END PrintBeer;


PROCEDURE main*( VAR args : ARRAY OF javalang.PString );
VAR beer: INTEGER;
BEGIN
   Out.Open;
   FOR beer:=99 TO 1 BY -1 DO
      PrintBeer (beer);
      Out.String(" on the wall,");
      PrintBeer (beer); Out.Char ("."); Out.Ln;
      Out.String ("Take one and pass it around,"); Out.Ln;
      PrintBeer (beer-1);
      Out.String (" on the wall."); Out.Ln; Out.Ln;
   END;
   Out.String ("No more bottles of beer..."); Out.Ln;
   Out.String ("Go to the store and buy some more..."); Out.Ln;
   Out.String ("99 bottles of beer.");

END main;

END Beer.
15. Язык dbPager. Предназначен для динамической генерации страничек под MS IIS. Инструкцию по настройке прекомпилятора под IIS5 я не нашел, так что тестировал под версией для коммандной строки. Язык несколько, на мой взгляд, необычен своей концепцией блочников и некоторыми конструкциями, но, в целом, очень хорошо читается и воспринимается.

Скрипт, выводящий песню о пиве (beer.dbp).
// Beer song. Written by Stepanischev E.V. (dbPager)
var "beer=99"
    var "LoopLimit=99" :: while 1
        var ""
            @beer:printbeer
        %Space%on the wall,
        var ""
            @beer:printbeer
        .%CrLf%
        Take one and pass it around,%CrLf%
        set "beer=[%beer%-1]"
        var ""
            @beer:printbeer
        %Space%on the wall.%CrLf%%CrLf%

No more bottles of beer...%CrLf%
Go to the store and buy some more...%CrLf%
99 bottles of beer.

:printbeer
    switch %beer%
        #0 :: No
        #else :: %beer%
    %Space%bottle
    switch %beer%
        #1 :: 
        #else :: s
    %Space%of beer
14. Small C. Написав в предыдущей серии программу, выводяшую песню о пиве, на C--, я заинтересовался классом малоизвестных си-подобных языков. Благо Интернет и поисковые машины под рукой.

Первое, что мне попалось - это Small C. Впервые сведения о этом языке появились в октябре 1999 года в Dr. Dobb's Journal. Язык простой и удобный, настолько отличен от C, что перечислять эти отличия тут я не буду. Подробности можно найти в документации, доступной там же, на сайте.

Интересно, что исполнение программ происходит, как и в Java, в два этапа. На первом программа прекомпилируется в байт-коды, на втором - байт-коды интерпретируются или, если используется JIT, компилируются в машинный код и исполняются.

Несколько матерных слов в адрес компилятора. Отвратительная диагностика, странная реакция на символы табуляции, лишние переводы строки и символы "^", неработоспособность конструкции "a?b:c" и так далее. Компиляция моего небольшого примера заняла на P-II 333 примерно 10 секунд. А теперь сам листинг.

Программа, выводящая песню о пиве (Small C).
/* 99 beer song. Written by Stepanischev E.V. Small C */
#include <console>

printbeer (b)
{
     if (b) printf ("%d",b); else printf ("No")
     printf (" bottle")
     if (b!=1) printf ("s")
     printf (" of beer")
}

main ()
{
     for (new i = 99; i > 0;)
     {
           printbeer (i)
           printf (" on the wall, ")
           printbeer (i)
           printf (".^nTake one and pass it around,^n")
           i--
           printbeer (i)
           printf (" on the wall.^n^n")
     }

     printf ("No more bottles of beer...^n");
     printf ("Go to the store and buy some more...^n");
     printf ("99 bottles of beer.");
}
13. Windows Script Host - технология, заботливо упрятанная в недра вашей Windows заботливой компанией Microsoft. Скрипт написан с применением 2-й версии технологии, которая распространяется вместе с Windows 2000. Впрочем, ничего не мешает поставить его на любую другую ОС этого семейства. Базируется она на JScript или VBScript и позиционируется как замена пакетному (batch) языку DOS.

Способ запуска: wscript.exe beer.js. Во время выполнения настоятельно не рекомендуется переключать окна.

Скрипт, выводящий песню о пиве (beer.js).
function PrintBeer(i)
{
    return (i?i:"No")+" bottle"+(i-1?'s':'')+" of beer"
}

WshShell = WScript.CreateObject("WScript.Shell")
with (WshShell)
{
    Run("notepad.exe")
    WScript.Sleep(100)
    AppActivate("Untitled - Notepad")

    for (i = 99; i>0;)
    {
        SendKeys (PrintBeer (i)+" of beer on the wall, ")
        SendKeys (PrintBeer (i)+".~")
        SendKeys ("Take one and pass it around,~")
        i--
        SendKeys (PrintBeer (i)+" on the wall.~~")
    }

    SendKeys ("No more bottles of beer...~")
    SendKeys ("Go to the store and buy some more...~")
    SendKeys ("99 bottles of beer.")
}
12. C--. Есть язык C, есть C++, а есть, оказывается, Си--. Язык, занимающий промежуточное положение между C и ассемблером. Его автором является Peter Cellik (Канада), в данный момент поддержкой и расширением синтаксиса языка занимается Михаил Шекер (Россия). Адрес его странички в Сети можно найти внизу заметки.

Язык мне показался обычным ассемблером, с вредренными элементами синтаксиса С. Этакий навороченный макроассемблер. Попался бы мне такой лет так пять назад - оторвал бы с руками, а сейчас... Но, хотя на ассемблере теперь я пишу только мелочь, а мелочь лучше писать без применения всяческих прилад, стирать все же не буду - вдруг пригодится.

P.S. Кстати, на страничке можно скачать архиватор HA, переписанный на Си--. Работать он после такой модификации стал в полтора раза быстрее. Заслуга языка и компилятора или автора модификации?

Программа, выводящая песню о пиве.
?use80486
?include "WRITE.h--"

void PRINTBEER ()
{
    $PUSH AX;
    IF (AX) WRITEWORD (AX); ELSE WRITESTR ("No");
    WRITESTR (" bottle");
    $POP AX;
    IF (AX<>1) WRITE ('s');
    WRITESTR (" of beer");
}

void main()
byte bott;
byte beer = 99;
{
    WHILE (beer)
    {
        PRINTBEER (beer);
        WRITESTR  (" on the wall, ");
        PRINTBEER (beer);
        WRITESTR  (".\nTake one and pass it around,\n");
        beer--;
        PRINTBEER (beer);
        WRITESTR  (" on the wall.\n\n");
    };

    WRITESTR ("No more bottles of beer...\n");
    WRITESTR ("Go to the store and buy some more...\n");
    WRITESTR ("99 bottles of beer.");

    AX = 0x4C;
    $INT 0x21;
}
11. Microsoft Dialer. Можно только удивляться, сколько языков программирования можно найти у себя на компьютере. Эта песнь о пиве написана на языке программирования SCP-файлов, файлов, руководящих соединением через модем. Насколько я понял в этом языке есть примитивная арифметика, вывод, циклы и ветвление (правда без else), но нет преобразования типов. Точнее можно узнать на MSDN, но мне было лень было искать информацию. Так что переменная цикла nB используется только для упрощения. Но как бы то ни было, написать программу у меня получилось. :)

Скрипт, выводящий песню о пиве.
; "99 beer" song by Evgeny V. Stepanischev
proc main
    string szA = "9"
    string szB = "9"
    string szS = " bottles"
    string szX = ""
    string szY = ""

    integer nB = 99

    set screen keyboard on
    delay 2

    ; Эту строчку ждет мой провайдер
    ; У вас она может быть другой
    transmit "@D^M^M"

    while Nb>0 do

    if szA!="0" then
    transmit szA
    endif

    transmit szB

    szS = " bottles"
    if nB==1 then
    szS = " bottle"
    endif

    transmit szS
    transmit " of beer on the wall, "

    if szA!="0" then
    transmit szA
    endif

    transmit szB
    transmit szS
    transmit " of beer.^M"
    transmit "Take one and pass it around,^M"

    szX = szA

    if szB=="0" then
        if szA=="1" then
        szX = "0"
        endif

        if szA=="2" then
        szX = "1"
        endif

        if szA=="3" then
        szX = "2"
        endif

        if szA=="4" then
        szX = "3"
        endif

        if szA=="5" then
        szX = "4"
        endif

        if szA=="6" then
        szX = "5"
        endif

        if szA=="7" then
        szX = "6"
        endif

        if szA=="8" then
        szX = "7"
        endif

        if szA=="9" then
        szX = "8"
        endif

    szY = "9"

    endif

    if szB=="1" then
    szY = "0"
    endif

    if szB=="2" then
    szY = "1"
    endif

    if szB=="3" then
    szY = "2"
    endif

    if szB=="4" then
    szY = "3"
    endif

    if szB=="5" then
    szY = "4"
    endif

    if szB=="6" then
    szY = "5"
    endif

    if szB=="7" then
    szY = "6"
    endif

    if szB=="8" then
    szY = "7"
    endif

    if szB=="9" then
    szY = "8"
    endif

    szA = szX
    szB = szY

    nB = nB - 1

    if nB==0 then
    transmit "No more bottles of beer on the wall.^M"
    endif

    if nB!=0 then
    if szA!="0" then
    transmit szA
    endif

    transmit szB

    szS = " bottles"
    if nB==1 then
    szS = " bottle"
    endif

    transmit szS
    transmit " of beer on the wall.^M^M"
    endif

    endwhile


    transmit "No more bottles of beer...^M"
    transmit "Go to the store and buy some more...^M"
    transmit "99 bottles of beer.^M"

    delay 99
endproc
10. ASP JScript и JavaScript. Одновременно. Первый - серверный язык, второй - клиентский. Испытано под IE 5.0, Opera 5.01, Netscape 4.75, Netscape 6.0 и IIS5.
<!-- <%@ LANGUAGE = JScript %>

<% //>
//</%> --> <SCRIPT LANGUAGE=JavaScript>
for (k = ' of beer on the wall',o='', i = 99; i>0; i--)
{
    a = i+' bottle'+(i-1?'s':'')
    o+= a+k+', '+a+' of beer...<BR>'+
    'Take one down, pass it around.<BR>'+
    (i-1?i-1:'No ')+' bottle'+(i-2?'s':'')+k+'.'+
    '<BR><BR>'
}

o+= 'No more bottles of beer...<br>'+
'Go to the store and buy some more...<br>'+
'99 bottles of beer.'

if (typeof(document)!='undefined') document.write (o); else
if (typeof(Response)!='undefined') Response.Write (o)
// </SCRIPT> <!-- // < %> -->
9. Parser (втрой версии) студии Артемии Лебедева. Предпроцессор для генерации Веб-страниц "на лету".
^var[i;99]
^while[i>0;

^var[i] bottle^if[i!=1;s;] of beer on the wall, ^var[i]
bottle^if[i==1;s;] of beer.<BR>
Take one and pass it around,<BR>
^var[i;-;1]
^if[i;^var[i];No] bottle^if[i!=1;s;] of beer on the wall.<BR>
<BR>
]
No more bottles of beer...<BR>
Go to the store and buy some more...<BR>
99 bottles of beer. 
8. Price Contertor Small Talk 2.00rc2. Этот язык я придумал сам, реализован он был примерно в 1998 году, как внутреннее средство управления программой обработки прайсов, представленных виде файлов Excel. Проект закрытого типа, так что ссылки в Интернете на него нет.
BEGIN
    "99"
    mov a "bottle(s) of beer on the wall."
END
WORK    "*"
    eq "No"
    if
        echo "No more bottles of beer..."
        echo "Go to the store and buy some more..."
        echo "99 bottles of beer."
        break ""
    endif

    else
        delete
        mov Y a
        .
        echo
        echo "Take one and pass it around,"
        mov Y "1"
        -
        eq "0"
        if
            mov Y "No"
        endif

        delete
        mov Y a
        .
        echo
    endelse
    prev
END
7. Small HTTP Server SSI. Вариант реализации SSI для SHS, написанного Максом Фиоктистовым. Файл должен называться index.shtm.
<!--#if expr="$b=No" -->
<BODY BGCOLOR=BLACK TEXT=WHITE>
No more bottles of beer...<BR>
Go to the store and buy some more...<BR>
99 bottles of beer.</BODY>
<!--#break -->
<!--#endif -->
<!--#set var="" value="" -->
<!--#set var="N" value="No" -->
<!--#set var="9" value="8" -->
<!--#set var="8" value="7" -->
<!--#set var="7" value="6" -->
<!--#set var="6" value="5" -->
<!--#set var="5" value="4" -->
<!--#set var="4" value="3" -->
<!--#set var="3" value="2" -->
<!--#set var="2" value="1" -->
<!--#set var="1" value="0" -->
<!--#set var="0" value="9" -->

<!--#if expr="!$a" -->
<!--#set var="a" value="9" -->
<!--#set var="b" value="9" -->
<!--#set var="s" value="bottles" -->
<!--#set var="m" value="$s" -->
<!--#endif -->
<!--#set var="t" value="$a" -->

<!--#if expr="$b=0" -->
<!--#set var="c" value="$a" -->
<!--#elif expr="$a>0" -->
<!--#set var="c" value="t" -->
<!--#endif -->
<!--#set var="d" value="$b" -->

<!--#if expr="$a=||$a=0||$c=1" -->
<!--#set var="c" value="" -->
<!--#endif -->

<!--#if expr="$d=1&&$c=" -->
<!--#set var="d" value="N" -->
<!--#elif expr="$d=2&&$c=" -->
<!--#set var="m" value="bottle" -->
<!--#endif -->

<HEAD>
<META HTTP-EQUIV="Refresh" Content="1;URL=index.shtm?a=<!--#echo var="$c" -->
&b=<!--#echo var="$d" -->&m=<!--#echo var="m" -->
&s=<!--#echo var="m" -->">
</HEAD>
<BODY BGCOLOR=BLACK TEXT=WHITE>
<!--#echo var="a" --><!--#echo var="b" -->
<!--#echo var="s" --> of beer on the wall,<BR>
Take one and pass it around,<BR>
<!--#echo var="$c" --><!--#echo var="$d" -->
<!--#echo var="m" --> of beer on the wall.
</BODY>
6. JUnix Shell. Коммандный интерпретатор JUnix (junix.kzn.ru) Предупреждаю: JUSH работает настолько медленно, что вы вряд ли дождетесь результата работы. Для испытания лучше уменьшить константу «beer» до 4-х.
set beer=99
set s=s
while ($beer gt 0)
echo $beer bottle$s of beer on the wall, $beer bottle$s of beer.
echo Take one and pass it around,
set beer--
if ($beer==1) set s=
if ($beer) echo $beer bottle$s of beer on the wall.\n
end
cat <<T
No more bottles of beer on the wall.

No more bottles of beer...
Go to the store and buy some more...
99 bottles of beer.
T
5. PHP.
<?
for ($s='s' and $beer=99;$beer;)
{
    echo "$beer bottle$s of beer on the wall, $beer bottle$s of beer.<br>",
    "\nTake one and pass it around,<br>";
    $beer--;
    $s = $beer==1?'':'s';
    if ($beer) echo "$beer bottle$s of beer on the wall.<br><br>";
};
?>
No more bottles of beer on the wall.<br><br>
No more bottles of beer...<br>Go to the story and buy some more...<br>
99 bottles of beer.
4. Win2000 batch file.
@ECHO OFF
REM Evgeny.Stepanischev

FOR /L %%B IN (99,-1,1) DO CALL :PROG %%B
ECHO No more bottles of beer...
ECHO Go to the store and buy some more...
ECHO 99 bottles of beer. 
GOTO :EOF

:PROG
ECHO %1 bottle(s) of beer on the wall, %1 bottle(s) of beer.
ECHO Take one and pass it around,
SET /A S=%1-1
IF %S% EQU 0 SET S=No
ECHO %S% bottle(s) of beer on the wall.
ECHO.
3. xSSI для Apache

Знаком "@" обозначено место, где перевод строки _не_ нужен, просто строчки такие длинные, что пришлось их разбить.
<!-- Written by Evgeny.Stepanischev -->
<!--#if expr="$D=A || $D=B" -->
    <!--#if expr="$K=/${D}8/" -->
    <!--#set var="D" value="8" -->
    <!--#set var="M" value="7" -->
    <!--#elif expr="$K=/${D}7/" -->
    <!--#set var="D" value="7" -->
    <!--#set var="M" value="6" -->
    <!--#elif expr="$K=/${D}6/" -->
    <!--#set var="D" value="6" -->
    <!--#set var="M" value="5" -->
    <!--#elif expr="$K=/${D}5/" -->
    <!--#set var="D" value="5" -->
    <!--#set var="M" value="4" -->
    <!--#elif expr="$K=/${D}4/" -->
    <!--#set var="D" value="4" -->
    <!--#set var="M" value="3" -->
    <!--#elif expr="$K=/${D}3/" -->
    <!--#set var="D" value="3" -->
    <!--#set var="M" value="2" -->
    <!--#elif expr="$K=/${D}2/" -->
    <!--#set var="D" value="2" -->
    <!--#set var="M" value="1" -->
    <!--#elif expr="$K=/${D}1/" -->
    <!--#set var="D" value="1" -->
    <!--#set var="M" value="0" -->
    <!--#elif expr="$K=/${D}0/" -->
    <!--#set var="D" value="0" -->
    <!--#else -->
    <!--#set var="D" value="9" -->
    <!--#set var="M" value="8" -->
    <!--#endif -->

<!--#else -->

    <!--#set var="D" value="A" -->
    <!--#set var="K" value="$QUERY_STRING" -->
    <!--#include virtual="$DOCUMENT_NAME" -->
    <!--#set var="A" value="$D" -->
    <!--#set var="Am" value="$M" -->

    <!--#set var="D" value="B" -->
    <!--#include virtual="$DOCUMENT_NAME" -->
    <!--#set var="B" value="$D" -->
    <!--#set var="Bm" value="$M" -->

    <!--#if expr="$A=0 && $B=0" -->
        <BODY BGCOLOR="BLACK" TEXT="WHITE"><B>
        No more bottles of beer...<br>
        Go to the store and buy some more...<br>
        99 bottles of beer.
        </BODY>
    <!--#else -->

        <HEAD>
        <!--#if expr="$B=0" -->
            <!--#set var="A1" value="$Am" -->
            <!--#set var="B1" value="9" -->
        <!--#else -->
            <!--#set var="A1" value="$A" -->
            <!--#set var="B1" value="$Bm" -->
        <!--#endif -->
        <META HTTP-EQUIV="Refresh" Content="1;@
URL=http://<!--#echo var="HTTP_HOST" --><!--#echo var="DOCUMENT_URI" -->?A@
<!--#echo var="A1" -->B<!--#echo var="B1" -->">
        </HEAD>

        <BODY BGCOLOR=BLACK TEXT=WHITE><B>
        <!--#if expr="$A>0" --><!--#echo var="A" --><!--#endif -->@
<!--#echo var="B" -->
        bottle<!--#if expr="$A$B>1" -->s<!--#endif -->
        of beer on the wall, <!--#if expr="$A>0" -->@
<!--#echo var="A" --><!--#endif --><!--#echo var="B" -->
        bottle<!--#if expr="$A$B>01" -->s<!--#endif --> of beer.<br>
        Take one and pass it around,<br>

        <!--#if expr="$A1$B1>00" -->
            <!--#if expr="$A1>0" --><!--#echo var="A1" -->@
<!--#endif --><!--#echo var="B1" -->
            bottle<!--#if expr="$A1$B1>01" -->s@
<!--#endif --> of beer on the wall.
        <!--#else -->
            No more bottles of beer on the wall.
        <!--#endif -->
        <!--#set var="C" value="" -->
        <BR>
        </B></BODY>
    <!--#endif -->
<!--#endif -->
2. MySQL. YourTable - это ваша таблица с числом строк более 100.
/* Program by Evgeny.Stepanischev*/
SET @beer:=100;
SET @w:=' on the wall';
SELECT IF(@beer<2,'\nNo more bottles of beer...\n\
Go to the store and buy some more...\n99 bottles of \
beer.',CONCAT(CONCAT('\n',@str:=CONCAT(@beer:=@beer-1,\
@bot:=CONCAT(' bottle',IF (@beer>1,'s',''),' of beer')),\
@w,', ',@str,'.\nTake one and pass it around,\n'), IF \
(@beer-1=0,'No more ',@beer-1),@bot,@w,'.')) as beer
FROM YourTable LIMIT 100;
1. PostgreSQL. YourTable - это ваша таблица с числом строк более 100.
-- Written by Evgeny.Stepanischev
-- 
CREATE SEQUENCE temp_beer_seq INCREMENT -1 MINVALUE 0 MAXVALUE 99 START 99;
CREATE FUNCTION temp_b() RETURNS text
AS 'SELECT \' bottle\'||CASE WHEN last_value=1 THEN
\'\'::text ELSE \'s\'::text END||\' of beer\' FROM temp_beer_seq'
LANGUAGE 'sql';
    
CREATE FUNCTION temp_b_out() RETURNS text
AS 'SELECT s.last_value||temp_b()||\' on the wall, \'||
s.last_value||temp_b()||\'.\\n Take one and pass it around,\\n \'||
CASE WHEN NEXTVAL(\'temp_beer_seq\')=0 THEN \'No\'
 ELSE text(s.last_value-0) END||
temp_b()||\' on the wall.\\n\'
FROM temp_beer_seq s'
LANGUAGE 'sql';

SELECT CASE WHEN temp_beer_seq.last_value=0
THEN 'No more bottles of beer...\n Go to the store and buy some more...\n
 99 bottles of beer.' ELSE temp_b_out() END
FROM YourTable LIMIT 100,1;
                    -- 

DROP SEQUENCE temp_beer_seq;
DROP FUNCTION temp_b();
DROP FUNCTION temp_b_out();
-- END