войти зарегистрироваться

Io programming language

По факту защиты мной диплома образовалось некоторое свободное время и я таки решил собраться и написать про эту чудесную штучку.
Мы в последнее время видим всплеск интереса ко всяким языкам очень высокого уровня, с анонимными функциями, каррингом, мапом/фолдом, метапрограммированием и прочим блэкджэком. Слава богу, я считаю.
Задачи усложняются и если люди применяют относительно низкоуровневые средства разработки зачастую наступает ситуация, когда набор абстракций оказывается мал в рамках решаемой задачи, примерно так появляется «спагетти» и велосипеды. Хорошего мало. Хотя умалять роль низкоуровневого программирования не хочется совершенно, по понятным причинам.

Совсем недавно, в 2002 году, бравый американец Стив Декорте понял, что ему как-то все вокруг не нравится. Ну то есть нравится, но как-то по частям. Нравится Smalltalk своей Ъ-ООП природой, нравится Lisp своей системой метапрограммирования и общей мегаизвратностью, нравится Self своими прототипами, нравится Lua, потому что маленькая и клево встраивается куда угодно. А вот что бы все и сразу — что-то не то. Погоревал бравый американец, да и наколбасил свой собственный язык программирования — Io.

Io


Io это маленький, полностью объектно-ориентированный язык программирования с динамической типизацией и развитой системой метапрограммирования, анонимными функциями и вытекающими отсюда плюшками. Кроме того, Io невероятно прост, как в синтаксисе, так и внутри. Существуют всего две сущности: объекты и сообщения. На этом базисе построено все остальное. Вообще весь язык следует дзенскому духу минимализма и простоты.
В Io нет понятия класс, только объект. Объект может быть склонирован и изменен, таким образом мы получаем другой объект (Это и есть прототипы). Все типы данных, значения и прочая — объекты.

Ну что, поехали.

Io в примерах


"Hello world" print

Это самизнаетечто. Многих (да и меня в самом начале моих платонических отношений с Io) сильно смутило, какого хрена так странно вызывается print? Тут все просто, главно понять, что в Io нет методов и свойств, есть слоты и сообщения. В данном примере строке "Hello world" отправляется сообщение print. В более традиционных ООП языках это будет выглядеть примерно так:
"Hello world".print()

Это что бы было проще понять.

Теперь непосредственно про хваленое прототипное ООП:

Mushroom := Object clone
Mushroom isPoison := false
Mushroom whenEaten := method(person,
if(self isPoison == true,
person kill
)
)

В этом фрагменте кода мы создаем объект Mushroom, определяем его как съедобный и создаем метод whenEaten убивающий съевшего в случае, если гриб оказался ядовитым.

Man := Object clone
Man state := "Living"
Man eat := method(food,
food whenEaten(self)
)
Man kill := method(
self state := "Dead"
)

Определяем объект «Мужыг», как видно из кода, Мужыг можеть есть и умереть (ну вот как-то так).
Как доказал Сергей Анатольевич Курёхин — Ленин был грибом. Таким образом мы можем определить ленина через клонирование класса Mushroom:

Lenin := Mushroom clone
Lenin isPoison := false
Lenin speak := method(
"Патриотизм - одно из наиболее глубоких чувств,
закрепленных веками и тысячелетиями обособленных отечеств." println
)

Так же, для разнообразия, можно определить ядовитый гриб:

InfectedMushroom := Mushroom clone
InfectedMushroom isPoison := true

Теперь мы можем попробовать накормить мужика чем-нибудь:

Man eat(Mushroom)
Man state println

Напечатает «Living».

Man eat(InfectedMushroom)
Man state println

Соответственно «Dead»

В то время, пока Ленин говорил:

Lenin speak

Пришел мужик съел его:

Man eat(Lenin)

И остался жив.

Метапрограммирование


Система метапрограммирования в Io в тысячу раз проще чем в том же Lisp'е, но не менее мощная. Здесь нет понятия «макрос», тут просто все дерево кода доступно в рантайме. Не надо извращений со сложными синтаксическими конструкциями, просто изменяй код «on fly» как тебе захочется.
Мой любимый пример — реализация Singleton'а в Io:

Singleton := Object clone
Singleton clone := Singleton

Тут я просто переопределил стандартный метод clone, что бы он возвращал тот же объект.

Напоследок


Io очень молодой, но не по годам прикольный язык. Несмотря на его мегаизвратность и мощность он крайне простой. Сам язык расчитан на легкость встраивания в чужеродные системы, к нему легко писать модули на низкоуровневых языках, когда требуется перфоманс. Для него уже сейчас написано достаточно библиотек.
Существуют несколько проектов, активно использующих Io, например проект It — скриптовый язык основанный на Io, разработанный в Pixar.
Сейчас я занимаюсь переводом документации по Io на русский язык. Конечно, я затронул очень мало в этом посте, так что продолжение следует (-;

Ссылки


http://iolanguage.com

(Из моего блога)

upd: продолжение цикла: Синтаксис Io

комментарии (135)

  • Большое спасибо :)
    Как раз хотел присмотреться к какому-нибудь неизвестному мне языку программирования, для повышения профессионального уровня. Похоже, этим языком программирования будет Io.
    • Всегда пожалуйста (:
      Вот только есть предложение не хвататься за Io, а схватиться за Lisp, например.
      В Io желательно приходить уже зная, что могут дать метапрограммирование, лямбда-функции и прочее. К тому же пока по Io очень мало толковой документации, но мы работаем над этим (:
      • А я рубист, у нас тоже есть всякие вкусные высокоуровневые штуки. Так что вполне представляю, что и почем.
        Правда, с Lisp'ом я знакомился один семестр на третьем курсе, и воспоминания не слишком приятные :)
        • Академический лисп и лисп производственный это настолько разные вещи, что аж зубы сводит. Чаще всего в университетах даже lisp-код форматировать не умеют, не говоря уж о метапрограммировании (которое там совершенно офигенное).
          Почитайте «On Lisp» Грэма или «Practical Common Lisp». Ну и «SICP», конечно.
          Хотя да, рубистам в Io будет приятно и легко.
          • Почитаю, спасибо.
            • Настаиваю, чтобы в русскоязычных текстах язык назывался «Ё»! ;)
              • Бггг, отличное предложение (:
      • А на тему метапрограммирования, лямбда-функций и прочего куда сунуться можно?
        • Эээ, вопрос интересный. Вообще лямбда-функции вытекают из лямбда-исчисления, это раздел математики (см. википедию). Про метапрограммирование можно почитать учебники по лиспу, например.
          А если одним словом, все хорошо расписано в книжке «Структура и интерпретация компьютерных программ». Она вышла у нас на русском и есть в pdf в интернетах.
          • Дай ссылочку пожевать. И это, почему её до сих пор не задефунил?
    • Для повышения профессионального уровня советую присмотреться к языку Oz вместе с книгой CTMCP
      • Спасибо за наводку, непременно попробую и погляжу.
    • Попробуйте какой нибудь из диалектов Smalltalk, например Dolphin. Обещаю скучно вам не будет и уровень свой поднимите сильно.
      • Да, надо будет обязательно посмотреть. Спасибо.
  • Хорошо пишешь.
    • Спасибо, Сашо.
  • Синтаксис и вообще подход похож на ruby. я не помню есть ли в нем лямда функции :)
    • Между Io и Ruby очень много общего, например один из разработчиков (:
    • Ну и да, в Ruby есть lambda-функции, они называются блоки.
      В общем-то в Io любое сообщение method — лямбда функция. Есть еще block, который еще более лямбда-функция, но про него я как-нибудь в следующий раз.
      • Тут стоит отметить, что в самом Руби лямбда и блок - разные вещи, хотя с точки зрения лямбда-исчисления, рубишный блок - как раз и есть лямбда-функция :)
    • как можно программить на руби и не знать про лямда функции???
      • Очень просто: программировать на языке "ruby on rails" :)
      • не знать нельзя. а вот написать такое можно когда устал и болеешь.. не возмущайтесь тут :)
      • НЛО прилетело и опубликовало эту надпись здесь.
        • лямбда-функции, делегаты.
          это что-то вроде typedef int (*PFUNC) (int);
          ?
          • да, делегат это объектно-ориентированная версия указателя на функцию, скажем так :)
          • НЛО прилетело и опубликовало эту надпись здесь.
            • У нас на курсе, где практика была на OCaml, это называлось каррирование. Я бы назвал это «возможностью каррирования»
            • В C# замыкания как раз реализуются через статические переменные-члены класса, но это делает за нас компилятор.
    • Ещё бы они не были похожи - и туда и туда они пришли из Smalltalk-а :-)
  • было бы еще лучше, если бы не было столько лишних переносов строк.
    • Проблема в том, что их там нет, это интервал в тэге pre. Меня тоже драконит
      • именно поэтому я пишу тексты для хабры в чистом штмле и не пользуюсь автоформатированием :)

        В данном случае их можно заменить на blockquote
        • угу, и слетят отступы, или предполагается использования Вуду- ?
          • Можно просто переводы строк заменить на <br />
      • НЛО прилетело и опубликовало эту надпись здесь.
  • Здорово, только пример с синглтоном к метапрограммированию как-то мне особо наглядным не показался. Не проникаешься сутью того, что обработчик сообщения может сделать со своими аргументами.
    • Про метапрограммирование я поподробнее напишу чуть позже, довольно тяжело объяснять систему метапрограммирования, когда она настолько тривиальна, как ни странно.
      Из фишек на затравку, Io умеет:

      • На лету брать полную информацию о слотах объекта

      • На лету «декомпилировать» слоты

      • На лету изменять любой фрагмент кода в рантайме

      • Последнее это что-то вроде лексического замыкания как в Лиспе? Или иное?
  • Mushroom := Object clone

    В этом фрагменте кода мы создаем класс Mushroom


    Классов-то нет.

    Тут все просто, главно понять, что в Io нет методов и свойств, есть слоты и сообщения.


    И чем по-вашему метод «отличается» от «сообщения», а «свойство» от «слота»? По-моему ничем, если учесть что «метод — кусок кода, ассоциированный с объектом или классом».

    Больше всего это напоминает мне JavaScript со стейтментами в стиле лисп (с лиспом не знаком).
    • Про класс мой косяк --- поправил, спасибо.
      А про отличия: слот --- абстрактный контейней, который может содержать как значение, так и «метод». Все это в общем случае --- сообщения.
      • а, да, слоты отличаются
        ____

        интересно, как в более-менее сложном коде предполагается создать два объекта одного типа в разных местах (где клонирование недоступно)… предполагаю, будет уже не так красиво
        • Вообще Io умеет асинхронные сообщения, через них можно получить доступ к любому месту системы, даже к сильно удаленному (другая нода кластера, например). Проблемы не вижу пока (:
          • Ну вот в JS я бы написал так:

            function Human(name, age, city) {
            this.name = name
            // что-нить сложное
            }

            fuction one() { new Human("Elsa", 19, "Hamburg") }
            fuction two() { new Human("Egor", 32, "spb") }

            Как в данном случае обойтись одним клонированием, мне не оч. понятно… Т. е. извернуться можно, но красиво пока не входит.
            • Эээ, а почему одним-то клонированием-то? У вас тут два new, значит два поколения, так же и там.

              Human := Object clone
              Human init := method(name, age, city,
              self name := name
              self age := age
              self city := city
              )

              One := Human clone
              One init("Elsa", 19, "Hamburg")
              Two := Human clone
              Two init("Egor", 32, "spb")
            • Собственно, new в JavaScript - это аналог clone в io.
      • "В Io нет понятия класс, только объект"
        А мне кажется, что объект - это экземпляр класса. Класс — это тип, описывающий устройство объектов — экземпляров.
        • А вы где-то видите в примерах описание типов?
          • нет описания типов и есть объекты ;)
    • Про метод/сообщение: метод вызывается, а сообщение посылается. Разница хорошо видна, если попытаться вызвать несуществующий метод - в случае "вызова метода" либо среда исполнения сгенерирует исключение, либо просто всё упадёт, и мы сможем обработать эту ситуацию только в _вызывающем_ объекте, но не в _вызываемом_. При посылке же сообщения мы легко можем обработать ситуацию отсутствия соответствующего метода непосредственно в том объекте, которому посылается сообщение. Такое поведение периодически используется в зрелых динамически типизированных языках. Чем-то это похоже на кодогенерацию на лету, но даёт гораздо больше возможностей.
      • Спасибо, понял :)
  • Введение в Io посредством примера, основанного на теории "Ленин - гриб (и радиоволна)" - это круто :)
  • название плохое, гуглить плохо +)
    • Это точно.
    • НЛО прилетело и опубликовало эту надпись здесь.
  • НЛО прилетело и опубликовало эту надпись здесь.
  • Спасибо. Давно намеревался посмотреть на родственничков любимого Смоллтолка, вот и повод будет.
  • Вот блин спасибо!!! Узнал новое, посмеялся над туториалом. Пошло говоря, в рот мне щупальца!
  • Шикарные примеры =))
  • а как у него с юникодом? опять все плохо?
    • Да нет, вроде. Изначально разрабатывался с его поддержкой.
      Вот конкретно в модуле Directory под винду есть косяки с юникодом, но только в этом модуле и только под винду.
      • хм, молодцы, если так

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

        да и пример работы со строкой, где по индексу возвращается число, а не символ, тоже усилил подозрения
        • У чисел есть метод asCharacter, насколько я помню, с его помощью можно сконвертить все куда угодно. Юникод же тоже числами кодируется.
          • да, но все равно напомнило си и пхп — похоже на отношение к строке как к массиву символов-байтов
            • Насколько я знаю, пока это самый удобный способ.
              Строка в Io это объект наследуемый от Sequence, со всеми вытекающими map/fold и итераторами.
              • я имею в виду, что си и пхп считают элементы строки байтами, и это не очень сочетается с юникодом ; )
                • тут int (-: больше поле для размаху
                  • то есть, строка в cp1251 будет увеличиваться в 4-8 раз при преобразовании ко внутреннему формату? 0_0
  • весьма
    даешь еще статей по ИО
  • перфоманс, блин... а по русски нельзя?
    • А слова типа "Сконвертить", "отгрепать" и "программинг" вас не смущают?
      Жаргон, фигли, а так можно конечно.
      • глаз зацепился почему-то только за перфоманс :) ну уж совсем редко используется, нежели остальное. Профессионализмы это, конечно, хорошо, но мера-то должна быть...
        • Хехе, видимо мы с вами в разных областях обитаем, для меня слово "перфоманс" настолько же привычно, как и "сконвертить" (:
      • Смущают. Сконвертировать, например, а не сконвертить.
  • НЛО прилетело и опубликовало эту надпись здесь.
    • Ой не уверен на счет академичности ФП. Когда заканчвали курс ФЛП (функц. лог. прог.) в универе, то для получения зачета нужно было найти ссылки и материалы по реально существующим применениям данных парадигм для разработки коммерческого ПО. Как оказалось не так уж и мало.
      • НЛО прилетело и опубликовало эту надпись здесь.
  • подача хороша.
  • што то можно тут почитать http://www.myjavaserver.com/~livesystems/stor/IoProgrammingGuide.ru.html
    • вставил ссылку в адресбар, увидел, что там я уже был. Сёмка, ты съел мой мозг и теперь принялся за хабраразум? ;)
      • Давно его пора!
      • ээ вы собсно к кому ?
        • Ну мне, в целом если. Просто Леня — мой дежурный мозг для изнасилования всяким извратом типа io, haskell и лиспа.
  • там есть полноценные замыкания (с захватом контекста)?
    • есть
      • разве?
        • yeld не игого?
          • а ну вроде покатит ага
  • Не программист, но прочитал с интересом. Блин, ну почему предки не купили мне компьютер, когда я учился в школе. Ну или хотя бы магнитофон к спектруму для записи кода. Аыыыыы (((
  • НЛО прилетело и опубликовало эту надпись здесь.
  • Язык весьма интересный. А что насичот производительности?
    Вот тут что-то совсем нерадостно.
  • С производительностью у него пока беда: http://shootout.alioth.debian.org/gp4/be…
    И это при условии, что MRI (Ruby 1.8) сам по себе достаточно медленный.

    А вообще язык симпатичный.
  • копетц.

    > Совсем недавно, в 2002 году,

    это всё было давно опубликовано в 1969 году в спецификации на forth
    • Круто. Давно форт стал объектно ориентированным? А тем более Ъ-Объектно-ориентированным?
      • как и любой метаязык он позволяет создать такую объектную модель, которая больше нравится. труъ - у каждого своё.
        • вы знаете, вот чуть ниже вы хаете метаязыки. не странно ли вам?
          на лиспе тоже можно реализовать что угодно. Кроме того у ТруЪ-ООП есть всего одно мерило --- smalltalk.
          • ну, самый мощный метаязык - это ассемблер ;-) и многие из "простых, но мощных" языков типа лиспа, форта, хаскела - не слишком далеко от него ушли. всё-равно для написания более-менее крупного приложения придётся писать нефиговый "фреймворк" реализующий ту или иную парадигму.

            а в смалтолк, хотя и замечательный ооп, но тоже не идеален. например, в нём нет интерфейсов, нет локальной перегрузки стандартных типов. ну и больше всего убивает - ориентированность на то, что пользователь работающий с программой и разработчик оной - одно лицо.
  • Блин, пока не увидел ссылку, думал, что язык называется "Lo"
  • Полный вынос...

    Я так и не понял, в чем его ценность.
  • > "Hello world" print

    принт куда? возможность "печатать" - это свойство принтера, а не бумаги.

    лучше бы сделали так:

    con.print( "Hello world" )

    при этом метод print должен вызывать "Hello world".toString

    это с точки зрения ооп.
    с точки зрения синтаксиса, лучше подход цпп:

    con все дерево кода доступно в рантайме

    только не вздумайте его менять, иначе замучаетесь с отладкой.

    два различных синтаксиса вызова методов (со скобочками и без) - это очень плохо.

    есть ли возможность перегружать присваивания? например, когда я хочу генерировать ошибку при попытке изменения какого-либо слота (ридонли свойство).
    • ну вот что за придурки писали движок хабра? неужели кроме стриптэгс ничего умнее в голову не пришло?

      цпп код: console
      • console << "Hello World"

        ну и далее у меня было написано что-то про то, что все эти новомодные языки по сути своей ущербны, ибо на них нельзя написать ядро ос и другие рилтайм приложения. для эффективного использования ресурсов остаются только цпп и ада. печально всё это =(
        • НЛО прилетело и опубликовало эту надпись здесь.
          • одно исключает другое? неужели существует какая-то принципиальная невозможность создания выразительного и в то же время эффективного языка?
            • ну вот взять, например, цпп. отрезать нафик указатели, шаблоны, сделать всё объектами, добавить возможность расширения синтаксиса (добавление своих операторов, например), отрезать типизацию, добавить интерфейсы, избавиться от "заканчивающихся нулём строк" и замечательный ведь язык получится. но нет, все лезут в метапрограммирование, рефлексию, полный динамизм, виртуальные машины, автоматические сборщики мусора... и огребают тормоза и повышенное потребление памяти. причём пользы от всего этого не слишком много. высокодинамичные программы сложно отлаживать. сборщик мусора работает не ахти как. байткод не учитывает специфику железа. итд итп
              • Польза появляется только тогда, когда начинаешь думать что ты делаешь, а не тогда, когда у тебя в руках быстрые костыли в виде плюсов. Высокоуровневый подход банально удобнее и выразительней, а производительности мне зачастую не жалко. А где жалко я напишу на C/Object C, но, упаси господи, не на C++.
                • угу, так в итоге и получается, что для комфортной работы нехватает гига памяти и всё тормозит. в то время как какая-нибудь миньетОС умещается на дискетку и летает.
                  • Вы точно не путаете Энтерпрайз с динамическими языками со сверхвысокими абстракциями? Тормозят больше всего, почему-то, всякие энтерпрайз монстры написанные на C++.
                    • тормозит всё, что угодно, когда разработчику "зачастую не жалко производительности"
                      • НЛО прилетело и опубликовало эту надпись здесь.
                        • неправда. седьмой зип в зависимости от настроек либо быстрее либо лучше жмёт. только что замерил.
                          но это не самое главное. фишка в том, что потоковая обработка - это халява для функциональных языков. их бич - активная работа с памятью. например, наложение фильтров на изображение.

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

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

                            а вот винрар - да, хотя и быстрее обоих, но жмёт хуже.
                            • НЛО прилетело и опубликовало эту надпись здесь.
                              • мне как-то нет дела до всяких "независимых бенчмарков". своим глазам я доверяю больше.

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

                                не надо путать декларативные языки с функциональными. на чисто функциональном языке, например, невозможо сделать простой чекбокс на форме. чтобы изменить его состояние, нужно отправить всё окно на съедение автоматическому сборщику мусора и с нуля сгенерировать новое, но с другим состоянием чекбокса.
                                по этой причине чистый функциональный подход нигде и не применяется - только для отдельных вычислительных тасков.
                                в то же время декларативный подход вполне допускает динамическое изменение состояния.
                                например: <a href="javascript:this.innerHTML='yes'">no</a>

                                не надо судить об императивном программировании лишь по одному убогому, но крайне популярному представителю.

                                там, где программисты просто используют цикл - там уже нет ФП. это самый обычный императивный язык с функциями, где программа из проского списка комманд переписана через последовательность вызова этих самых функций.
                                • НЛО прилетело и опубликовало эту надпись здесь.
                                  • 1. сам-то замерял?
                                    2. наоборот. ртфм.
                                    3. и что, каждый раз при изменении окна разворачивать по новой?
                                    4. конкретные языки назови.
                                    5. кроме сипипи
                                    • НЛО прилетело и опубликовало эту надпись здесь.
                                      • мда.. не густо. даже смалтолка нет.
                                        • НЛО прилетело и опубликовало эту надпись здесь.
                          • >естественных для человека циклов

                            То-то я смотрю у нас вся математик в циклах! Для человека циклы настолько же неестественны как и рекурсия, вощемто.
                            А рекурсия намного более выразительно в большинстве случаев. И довольно глупо тащить на процессор языки отличные от машинных комманд, все равно ведь компилятор их туда развернет.
                            • если показать человеку запись: n! = (n-1)*(n-2)*...*(2)*(1)
                              он сразу поймёт, что энфакториал - это произведение всех чисел от 1 до эн.
                              однако в математическую формулировку: n!= n ? n*(n-1)! : 1 - ещё придётся повъезжать, раскладывая мысленно в указанный выше ряд
                              • НЛО прилетело и опубликовало эту надпись здесь.
                  • НЛО прилетело и опубликовало эту надпись здесь.
                    • затем, что каждое приложение стремится заюзать всю свободную память. чем больше среднему пользователю доступно памяти, тем более развязно пишут свои программы разработчики. как не мог я пять лет назад запустить больше десяти средних приложений без риска угодить в своп, так не могу и сейчас.

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

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

                      затем, что на гигабайт usb-диска я лучше залью сотню-другую песен и буду наслаждаться разнообразием репертуара в дороге.
                      • НЛО прилетело и опубликовало эту надпись здесь.
            • НЛО прилетело и опубликовало эту надпись здесь.
    • Прозреваю сиплюсплюсера. Никогда не упирались в потолок выразительности своего языка? Довольно безответсвенно заявлять о ущербности языка, потому что на нем нельзя написать ОС. Гуглить IoL4 до просветления.
      • Прозреваю очередного тролля, предпочитающего навешивать ярлыки.
        l4 - это ядро, написанное на цпп. под ним запускается iovm - виртуальная машина ио, написанная на си. и уже под ней - приложения, написанные на io.
        • L4 если чо, это не ядро, это спецификация интерфейсов ядра. Насколько я знаю само ядро может быть реализовано на чем угодно. Да, загрузчик на C, а дальше хоть на хаскеле реализуй интерфейсы. Вам что, правда кажется, что все на свете удобно реализовывать на C++?
          • http://os.inf.tu-dresden.de/L4/impl.html
            активных имплементаций всего четыре. 3 из них на цпп, одна - на си. iol4 использует первую - Pistachio.

            на цпп я не программировал уже лет пять. и совершенно не хочу к нему возвращаться. но и новые веяния не слишком радуют...

            ещё вопросы?
  • Группа вконтакте, посвященная Ио:
    http://vkontakte.ru/club3618361
Только авторизованные пользователи могут оставлять комментарии. Авторизуйтесь, пожалуйста.