Friday, December 14, 2007

Erlang @ Amazon

А между тем замечательный язык erlang действительно напрашивается на то чтоб стать next big thing в веб-приложениях. Последнее время все больше и больше интересных новостей из этой области — особенно тут отличился Amazon.

Однако ж обо всем по порядку.

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

Первой ласточкой был EC2 — нечто, крайне напоминающее обычный VPS хостинг — амазон предоставляет вам в пользование виртуальные машины с операционной системой на выбор, однако деньги берет не помесячно, а за машино-часы и переданные гигабайты (от $0.10 до $0.80 за машино-час, плюс $0.10-$0.20 за переданный гигабайт).

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

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

Народ сразу оживился — действительно, EC2 и распределенный erlang будто созданы друг для друга. Можно запускать сколько нужно нодов на нужном количестве инстансов EC2, при этом не заморачиваясь никакими оргвопросами связанными с покупкой и администрированием настоящих серверов.

Второе — это S3, сервис по хранению данных. Деньги амазон берет за количество запросов + гигабайты в месяц, без всяких фиксированных тарифных планов.

И теперь амазон объявляет о запуске еще одного сервиса под названием SimpleDb — и все встает на свои места.

Это база данных, однако больше всего она похожа на большой excel-евский spreadsheet:

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

Если кто читал про ерланговскую родную базу данных mnesia, сразу увидит много знакомых фраз. Точнее, практически все эти фичи есть и у mnesia.

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

И действительно, в блоге амазоновского разработчика находим подтверждение: SimpleDb построена на erlang!

Если SimpleDb будет популярна — а предпосылки для этого есть (это ж Amazon) — это будет самый убийственный пример применения erlang в боевых условиях.

Да и просто факт, что уже доступна отличная и недорогая платформа для хостинга эрланговских приложений — уже очень хорошая новость.


Tuesday, November 27, 2007

Erlang Job

Для тех, кто не читает форумы рсдн (что, конечно, идеологически правильно): cовершенно неожиданно оказалось что Joel Reymont (чувак с покером на эрланге) родился в Санкт-Петербурге и отлично говорит по-русски. И вообще треть жизни прожил тут.

Оказалось это в связи с тем, что Джоель сейчас ищет программистов на Erlang и OCaml (пока part-time). На сайте у него говорится про разработку бэкенда для того самого OpenPoker, но из треда на рсдне видно что планы у него намного глобальнее.

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


Thursday, November 08, 2007

Угадайка

Как думаете, какой язык поддерживает сразу

  • First-class функции, лямбды и замыкания;
  • параметризованные типы;
  • хвостовые вызовы;
  • array comprehensions;
  • ООП с классами и интерфейсами;
  • ООП на основе прототипов;
  • мультиметоды;
  • coroutines (оператор yield);
  • структурные и номинальные подтипы;
  • перегрузку операторов;
  • Nullable/Non nullable аттрибуты для всех типов.

Ну и по мелочи: for-each, array slicing а-ля питон, регулярные выражения, открытые пространства имен и пр.

Однако ж это все ожидается в чудесном новом Javascript ECMAScript 4!

Еще  одна из самых интересных возможностей в четвертой версии — опциональная статическая проверка типов. Это должно упростить написание сложных систем (засчет строго описанных интерфейсов), и помочь [jit] компиляторам иногда генерировать более эффективный код. Опциональные статические типы, похоже, становятся модными: в Python 3000 тоже не так давно добавили что-то похожее.

Четвертая версия пока получается довольно пестрой — появилась куча новых механизмов и языковых конструкций (см. выше), а совместимость с предыдущей версией надо, по возможности, сохранить — поэтому синтаксис местами получился довольно странный: скажем, [int] это массив целых чисел, а [int, string] — это уже кортеж из целого и строки.

Еще из забавных вещей — явная поддержка структурных типов. В частности, с помощью специального оператора like можно задать переменной структурный тип (то есть ей можно присвоить только объект, обладающий набором заданных свойств):

var foo : like {x : int, y : int};

А переменная, объявленная с ключевым словом wrap автоматически дополняет хранимый в ней объект нужными свойствами:

var bar : wrap foo { x : int, y : int} = {x : 10, y : 20}.

Может и не революционная фича, конечно, но выглядит крайне интересно.

В ECMAScript 4 обещают также обязательную оптимизацию хвостовых вызовов. В Python 3000 их точно не будет, с руби ситуация туманна —что делает ES4 лучшим выбором в качестве платформы для компиляторов с функциональных языков. В общем-то уже сейчас есть компиляторы, как минимум, OCaml, SML и Haskell, генерирующие код на ECMASCript 3.

Собственно мощь и текущей-то версии js во многом недооценена. Кстати, только я не знал, что автор один из авторов первой версии Javascript — Гай Стил мл., а в качестве основных источников вдохновения при разработке Javascript 3 авторы называют языки Scheme и Self?

Новый Javascript явно претендует на что-то большее. Если он действительно будет "принят на вооружение" — определенно можно ожидать появления изрядного количества серверных приложений и фреймворков на js. Во всяком случае, язык получился явно не слабее питона и руби — хотя, конечно, вряд ли средства интеграции с кодом на C и C++ будут тут столь же развиты, ниша у языка все-таки другая.

Ссылки:


Thursday, October 25, 2007

Пятиминутка ненависти к C++

..на этот раз не моя, однако почитать другим пострадавшим будет довольно забавно. Автор — yousefk, видимо, годами записывал в книжечку все подлянки, которые ему устраивал C++, и в результате у него получился вот такой весьма объемный документ.

Называется это C++ Frequently Questioned Answers, и проезжается он практически по всем сколько-нибудь заметным фичам C++.

За основу взят широко известный C++ FAQ Lite, дополненный "альтернативными" ответами в среднеиздевательском тоне — то есть автор, к счастью, не совсем сваливается в непрерывное брюзжание (как я иногда), что сделало бы такой огромный труд невыносимо скучным.

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


Monday, October 08, 2007

Эзотерические языки - самый полный список

..найден на вики-сайте канала #esolangs в irc-сети freenode.

За ссылку спасибо жж сообществу ru_brainfucker.

Языков там какое-то дикое количество, а особенно выдающимся создателем странных языков оказался некто Дэвид Морган-Мар, очевидно, тру программист. В числе его творений:

  • язык Petrovich (назван в честь И.П. Павлова), основанный на концепции наград и наказаний и выработки у программы нужных "условных рефлексов" :

Petrovich> do something
11:15:23 11 June 2005
Petrovich> reward
Petrovich>

  • язык Haifu, где программы выглядят как хокку
  • язык Piet, исходники выглядят как абстракционистские произведения живописи:

Это собственно программа на Piet, печатающая первые сто чисел Фибоначчи.

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


Monday, September 24, 2007

Ссылки: Erlang for .NET, Python 3000 и все все все

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

  • Некий товарищ тут вот собирается писать erlang для .NET, при этом подробно комментируя процесс в блоге. Не знаю надолго ли его хватит (блогу всего неделя), но начало интригующее. Например пост про внутренности виртуальной машины эрланга — BEAM. У эрланга вообще всплеск популярности, вон даже у O'Reilly в ONLamp появилось небольшое введение в Erlang. И еще вот неплохое интервью про практическое применение Erlang некими австралийцами.

  • Гвидо ван Россум и Брюс Эккель в своих блогах интересно спорят о Python 3.0, многопоточности в питоне и возможности/невозможности убрать из питона Global Interpreter Lock, вот ссылки на последние посты про питон 3.0 и про GIL (на первые посты ссылки давать бессмысленно, поскольку они там в форме "мой ответ на этот ответ Гвидо на мой пост...")

  • Двигаясь в сторону теоретических основ — отличный пост про связь между замыканиями (в смысле closures) и ООП, с иллюстрациями на Scheme.

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

  • Ну и в заключение опять немножко суровых практических вещей: интересная библиотека для генерации парсеров бинарных протоколов, "binpac: A yacc for Writing Application Protocol Parsers": Юзер гайд, whitepaper[PDF].


Saturday, September 08, 2007

Seaside: веб-фреймворк на основе continuations

[Довольно длинное введение]

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

Написание сложных (и не очень) веб-приложений обычно наталкивается на кучу проблем, и основная — это то, что протокол HTTP не подразумевает никакого состояния — и поэтому это состояние приходится за собой таскать в виде cookies, скрытых полей в формах и букета параметров методов GET/POST. Плюс к этому, линейные переходы между страницами — по сути, аналог оператора goto — приводят к тому что дизайн многих веб приложений представляет из себя мешанину из процедурного и как-бы-объектно-ориентированного кода, сумбурных обращений к базе данных, разбавленных HTML разметкой.

Проблемы эти стараются решить современные фреймворки для веб-разработки, прежде всего Django, CakePHP и Ruby on Rails, в которых авторы постарались максимально отделить представление от логики, упростить работу с базой данных засчет всяких ORM подсистем и вообще структурировать приложение (в той или иной степени) заставляя его следовать классическому, но подзабытому в 90-е паттерну Model-View-Controller. В Ruby on Rails, скажем, под моделью понимаются данные, хранящиеся в БД, view — это система шаблонов, на основе которых генерируются страницы и контроллер — это собственно бизнес-логика.

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

[Па-пам]

Старики помнят, что термин "объектно-ориентированный" был изобретен для того чтобы назвать так язык Smalltalk. В дискуссиях о том, насколько тот или иной язык ОО обычно гуру ссылаются именно на него, как на эталон тру ОО языка.

Более того, паттерн MVC у тех же стариков ассоциируется прежде всего с GUI библиотеками Smalltalk, именно там этот паттерн родился и получил широкое применение (потом эта вся идеология перекочевала в ОС NextStep, а из нее в Mac OS(X), если кто не в курсе).

Возвращаясь к веб-разработке, многие наверное читали эссе Пола Грэма Beating the Averages, как Пол с товарищами написали на лиспе систему для создания веб-магазинов и потом продали ее за много миллионов баксов Yahoo!. Там они, кроме всего прочего, использовали continuations как механизм передачи управления между страницами. Continuation'ы хранились на сервере в словаре, а ссылки на страницах содержали как параметр id того continuation, который надо выполнить для генерации страницы.

Если сложить вместе концепцию continuations, MVC в качестве основного паттерна для архитектуры всего приложения и smalltalk в качестве языка разработки — получим Seaside, фреймворк для разработки сложных веб-приложений, не думая о большинстве вышеописанных проблем.

[Немножко подробнее про continuations в вебе]

С логикой и control flow в вебе проблем несколько — во первых, вышеупомянутое состояние сессии: таскать его между страницами через параметры POST/GET довольно неудобно да и иногда просто нереально, а наличие у юзера кнопок "назад" и "открыть в новом окне" создает проблемы, если мы храним состояние в куках или сразу сохраняем в базе данных введенные в формы данные.

Но отличное решение этой проблемы уже давно существует и реализовано во многих динамических языках, начиная с лиспа. Называется continuation — тут я описывал подробнее, что это, но если в двух словах — мы можем поставить выполнение программы в каком-то месте "на паузу", и потом с объектом "поставленная на паузу программа" обращаться как с любым другим — продолжить выполнение с того места (сколько угодно раз, заново), сохранить, передать, удалить за ненадобностью.

Например, представим себе такой пример: пользователь заполняет форму, нажимает ОК, но одно поле заполнено неверно, и мы хотим показать ему страничку с предупреждением и кнопкой ОК, и вернуться обратно к той (уже частично заполненной им) форме.

В стандартном случае мы передаем скрипту, выводящему страницу с предупреждением значения заполненных полей, а он потом передает их обратно. Как-то так:

/show_form.php 
-> validate_form.php?userName=John&phone=02
-> show_warning.php?userName=John&phone=02
-> show_form.php?userName=John&phone=02

В фреймворках, основанных на continuations метод showForm() просто вызывает validateForm(), которая вызывает showWarning(), и на время, когда юзеру надо показать отрендеренную страницу все состояние сохраняется в continuation. Потом, когда юзер жмет OK — все возобновляется с того места где приложение остановилось.

По сравнению с традиционным подходом тут целых несколько преимуществ: во-первых, мы не заботимся о том, как таскать состояние через страницы; во-вторых, структура программы становится понятнее, это своего рода переход от GOTO к процедурам; в-третьих, поскольку состояние теперь не наша забота, куски кода становятся более модульными, функции showWarning() уже не надо знать ничего ни о каких формах.

Последнее особенно хорошо иллюстрируется примером из дистрибутива Seaside: пять компонентов (счетчиков) на одной странице, состояние обо всех некоторым образом передается между страницами, но каждый счетчик ничего не знает о других — вся логика и представление сосредоточено внутри класса, отвечающего за компонент, а не размазана по скрипту сгенерить_страницу_с_пятью_счетчиками.php. Это именно благодаря тому, что состояние сохраняется и передается автоматически между вызовами. И кнопка back в браузере отлично работает без всяких усилий со стороны разработчика.

[Seaside]

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

Немаловажный момент — Seaside принципиально не использует никакой системы шаблонов, подобно Ruby on Rails и Django — XHTML код генерится с помощью набора специальных классов, благодаря чему генерацию XHTML можно разносить по методам, применять к ним инструменты для рефакторинга Smalltalk-овского кода (а среда тут предоставляет их очень богатый набор). Конечно, дизайнерам править XHTML будет немного сложнее, но, по-хорошему, им и не надо: XHTML призван отвечать за "семантику" страницы, а для представления ее существует CSS.

Вообще среда разработки в Smalltalk (точнее Squeak, основная но не единственная реализация Smalltalk, в которой работает Seaside)  заслуживает отдельного большого поста — настолько это инопланетное создание. Чего стоит только тот факт что там нету понятия исходных файлов — есть только один большой рантайм, все классы и методы правятся "на лету", не останавливая работы приложения. Система контроля версий тоже своя, и diff работающий не на уровне текста, а на уровне классов и методов. Поначалу больше всего расстраивает то, что в Squeak нельзя воспользоваться своим любимым редактором, но мало какой редактор предоставляет столько инструментов для рефакторинга и автоматической генерации кода, как System Browser в Squeak.

Кроме всего этого, к Squeak/Seaside прилагаются очень неплохие инструменты для отладки, тестирования и настройки производительности. В отладочном режиме вообще много приятностей — когда в приложении происходит какой-то эксепшен, можно нажать кнопку Debug и начать отлаживать с этого места в Squeak. Для десктопных средств разработки в этом ничего выдающегося нету, но для веб — это большой шаг вперед.

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

Лучше, конечно один раз увидеть: скринкаст здесь — рефакторинг приложения (не веб-) в squeak, не останавливая его работы; и тут — создание блога за 15 минут в Seaside. Заметьте, как товарищ ловко фиксит там баг на лету, опять же без остановки приложения.

[Кто-то же должен за это платить?]

Естественно, все это оборачивается несколько более высокими аппаратными требованиями. Seaside изначально ставит стоимость времени программиста много выше стоимости железок. Squeak кушает изрядно памяти и процессорного времени (хотя по скорости выполнения, говорят, как минимум не медленнее питона и руби). По стабильности рантайма проблем нету, если кого-то беспокоит что это все может быть несколько "сыровато" — виртуальная машина squeak разрабатывается уже лет 10 как, причем довольно серьезными и профессиональными дядьками, начиная с того же Алана Кея.

[Ну и..]

В общем, крайне рекомендую поиграться, особенно тем кто занимается веб-разработкой профессионально. Получите, как минимум, массу удовольствия.

[Ссылки. Много ссылок]

  • Блог "On Smalltalk" много про squeak, smalltalk и seaside
  • Блог "HREF Considered Harmful" про про seaside и внутренности squeak
  • Подробно о continuations в вебе Статья "Seaside - a Multiple Control Flow Web Application Framework" [PDF]
  • Сравнение Rails Vs Seaside (+ в комментах интересная битва между любителями Rails и автором)
  • Другое интересное сравнение Rails и Seaside от опытного программиста на java Дэвида Поллака. Судя по всему, Дэвида все-таки не устроило ни то, ни другое, поэтому сейчас он активно разрабатывает фреймворк на базе Scala, это отдельная интересная тема :)
  • Сайт Seaside
  • Сайт Squeak
  • Бесплатный хостинг для некоммерческих Seaside приложений
  • Туториалы к Seaside: вот и вот, и еще несколько в гугле можно найти. К сожалению, кое-какие из них местами устарели.


Friday, August 31, 2007

Блог: монстры геймдева

Группа широко известных в узких кругах отечественных разработчиков компьютерных игрушек (и не только) с недавних пор ведет коллективный блог по адресу http://blog.gamedeff.com

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

Всячески рекомендую, в общем.


Wednesday, August 29, 2007

Самый популярный функциональный язык

... чей рантайм установлен практически на каждом компьютере — это XSLT, язык для трансформации XML документов.

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

Все это в изобилии можно наблюдать в замечательной XSLT-библиотеке FXSL, разработанной Димитром Новачевым. Реализации большинства функциональных идиом, таких как композиция функций, операций со списками по мотивам хаскелевской стандартной библиотеки — map/filter/foldl/zipWith и т.п. Более того, в cvs-версии библиотеки можно найти даже реализацию небольшого LR-парсера на чистом XSLT 2.0

Конечно, выглядит не очень прозрачно, вот например использование foldl для вычисления произведения элементов списка:

<xsl:stylesheet version="2.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:foldl-func="foldl-func"
xmlns:f="http://fxsl.sf.net/"
exclude-result-prefixes="f foldl-func"
>

   <xsl:import href="../f/func-foldl.xsl"/>

<!--
    This transformation must be applied to:  
        ../data/numList.xml                  
                                             
        Expected result: 3628800 or 3.6288E6 
-->
   <foldl-func:foldl-func/>
   <xsl:variable name="vFoldlFun" select="document('')/*/foldl-func:*[1]"/>
    <xsl:output  encoding="UTF-8" omit-xml-declaration="yes"/>

    <xsl:template match="/">
      <xsl:value-of select="f:foldl($vFoldlFun, 1, 1 to 10 )"/>
    </xsl:template>
    
    <xsl:template match="*[namespace-uri() = 'foldl-func']"
     mode="f:FXSL">
         <xsl:param name="arg1" select="0"/>
         <xsl:param name="arg2" select="0"/>
         
         <xsl:value-of select="$arg1 * $arg2"/>
    </xsl:template>

</xsl:stylesheet>

Created with colorer-take5 library. Type 'xslt2'

В качестве примеров более серьезных программ на XSLT — решалка головоломки Sudoku и CSV2XML конвертер,написанные товарищем по имени Andrew Welch, у которого есть еще очень интересный блог по XSLT.

Если захочется поиграться, берите saxon в качестве XSLT процессора — поддержка XSLT 2.0 в MSXML только планируется (а в Orcas ее точно еще не будет)

Ссылки:


Friday, August 24, 2007

Код Adobe

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

Провели конкурс, и выиграл проект художника Бена Рубина: на последнем этаже здания с помощью мощных светодиодов (количеством >23000 шт) выводится четыре ярких световых пятна, поворачивающихся на разные углы каждые 7.2 секунды. Одновременно с этим вблизи здания на волне 1680 кГц можно услышать саундтрек, состоящий из не менее странного набора звуков. Все это еще реагирует на пролетающие самолеты (рядом аэропорт).

Называется это "Семафор Сан-Хосе", на сайте можно найти и видео того, как вся композиция выглядит:

Плюс к этому, автор зашифровал в последовательности этих вращений и звуков некий набор осмысленных данных, и объявил в августе 2006 года вместе с Adobe конкурс на расшифровку этого сообщения.

Уже через месяц код был расшифрован двумя местными учеными, однако по по правилам конкурса результаты были объявлены только через год — 14 августа 2007.

Вот тут можно почитать довольно увлекательный отчет о том как они пытались сломать этот код, а тут — описание собственно алгоритма.

Ничего сверхъестественного внутри не оказалось — каждому символу ASCII соответствовало определенное сочетание положений дисков / звуков, а данные состояли из заголовка и зашифрованного (вариантом шифра Вижинера) текста.

 

27723148.0f886b0078628df55b2305efb1cb3729.1188550416.ad19e9ea28e0c0f82d80c4e264544d86


Tuesday, August 21, 2007

Типы: ссылки

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

В этом посте я собрал немножко разных ссылок по теме, часть из них я уже приводил — пускай будут в одном месте:

Вообще:

  • Отличные слайды к лекциям по курсу "Types and programming languages" университета Глазго (это там, где появился GHC).
  • "Types and Programming Languages The Next Generation" — лекция Бенджамина Пирса о том что вообще в теории типов сейчас происходит.
  • Лука Карделли тоже много разных интересных научно-популярных вещей написал, например вот("Type Systems") и вот("On Understanding Types, Data Abstraction, and Polymorphism").

Про подтипы:

Про наследование:

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

Еще есть глава про типы в книжке И. Дехтяренко "Декларативное программирование" — сам я, правда, ее подробно еще не смотрел.


Monday, August 20, 2007

Типы: Top и Bottom

Для полноты картины нужно упомянуть еще два специальных крайних случая — типы Top и Bottom.

Тип Top (записывается как ) — это специальный тип, являющийся супертипом для всех остальных. Если быть ближе к математике — для любого t: t <: T.


В Java и C#, например, ему соответствует тип Object (правда, он не является супертипом для простых unboxed типов вроде int). Вообще в большинстве ОО языков (кроме C++) такой тип присутствует.

Другой полезный элемент системы типов — это тип Bottom , который является подтипом для любого типа. Как правило, нет ни одного значения этого типа — в противном случае, это значение допустимо было бы использовать и в контексте когда нужен тип функции (a → b), и, скажем, когда требуется тип сложной структуры данных.

Несмотря на это, тип bottom весьма полезен в некоторых случаях — он может обозначать тип функции, которая никогда не возвращает значений, например, входит в бесконечный цикл или кидать exception:

function div(a : float, b : float) : float = 
    if (a != 0)
      a / b
    else
      error 

Выражение error имеет тип bottom, технически оно выкидывает эксепшен. Благодаря этому выражение if в целом отлично проходит проверку типов1 (имеет тип float).
Однако, введение в систему типов такого специального случая ее неслабо усложняет — кроме Haskell Scala такого типа нет, вроде бы, нигде из более-менее мейнстримных языков.

1 Тут имеется ввиду выражение if, а не statement (как в C++/C#/Java). В C++/C#/Java этому соответствует тернарный оператор ?:


Thursday, August 16, 2007

Подтипы и наследование

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

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

Обычно есть несколько видов наследования. Первый — самый понятный и полезный — это наследование интерфейса. Он есть во все ОО-языках.

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

Другими словами, конкретный класс Cow, реализующий интерфейс IAnimal, должен иметь соответствующий подтип Cow <: IAnimal. То есть везде, где используется IAnimal можно впихнуть Cow и все будет все ок. По сути, так оно и работает.

 

Но ситуация заметно усложняется, если наследование происходит не от абстрактного интерфейса, а от другой реализации. В C++ это public наследование, в Java — кейворд extends.

Жизнь усложняется из-за двух основных обстоятельств: Во-первых, поскольку в классах обычно есть какое-то состояние, две эти реализации это состояние по разному дергают. А во-вторых, в большинстве языков есть такая фича: пусть функция sayMoo() в Cow вызывает Cow::open(), и если open() в наследнике переопределено, а sayMoo() — нет, то sayMoo() будет вызывать переопределенную версию open(). Это называется "открытой рекурсией" (open recursion).

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

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

Чистое же наследование реализации (private inheritance в C++) страдает похожими недостатками. Только подкласс при таком наследовании уже подтипом родителя не является совсем.

Ссылки:


Wednesday, August 15, 2007

Типы и подтипы

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

Подтип типа τ — это такой тип τ', значения которого можно безболезненно подставлять везде, где предполагается значение типа τ. Записывается это как

τ' <: τ

При этом τ называется супертипом для τ' .

Подтипы очень полезная в хозяйстве вещь: интуитивно понятно, например, что int <: float, то есть везде, где некая функция предполагает на входе действительное число, ей можно передать и целое. Еще очень широко подтипы используются нынче в ООП — когда тип (конкретный класс) "корова" является подтипом интерфейса "животное", другими словами, когда используется наследование интерфейса. Но тут есть уже очень много подводных камней, и к подтипам в ООП лучше вернемся попозже.

Логичное развитие идеи подтипов — это применение ее к параметризованым типам. В том числе ко всяким контейнерам.

Вопрос: если τ' <: τ, то следует ли из этого что List<τ'> будет подтипом List<τ>?

Если да, то тип List<T> называется ковариантным по параметру T, если наоборот (то есть List<τ> <: List<τ'>) — контравариантым.

Классический пример тут это параметризованный тип функции,

X → Y

то есть, она берет значение типа X в качестве аргумента, а возвращает Y. (X,Y - переменные типа, aka имена параметров шаблона/генерика).

Такой тип будет контравариантным по типу аргумента, и ковариантным по типу возвращаемого значения. И правда:

float → float <: int → float 

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

int → int <: int → float

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

Теперь вернемся к контейнерам. Возьмем некий шаблонный массив Array<T>. Пускай Cow <: Animal.

 function boogaga(Array<Animal> animals)
 {
   foreach (i in animals)
     i.go_home()
 }

С точки зрения этой функции, Array<Cow> похоже, вполне себе подтип Array<Animal>. И он таковым является в C#, Java и, в общем-то, C++. Однако, если наша функция захочет добавить еще один элемент в массив как animals.add(new Animal) — все сразу поломается, потому как где-то выше этот массив объявлен как Array<Cow>.

 function boogaga(Array animals)
 {
   animals.add(new Animal);
 }

 Array<Cow> cows;
 boogaga(cows);                         
 foreach(i in cows)
   i.sayMoo(); //  у Animal нет метода sayMoo!

 

Зачем тогда делать массивы ковариантными — это удобно для всяких операций сортировок и поиска, и других операций, навроде первой функции boogaga. А чтобы избежать подобных ошибок, при добавлении в массив элемента не того типа (Animal вместо Cow) в Java и C# при выполнении программы вылетит специальный эксепшен.

Что касается C++, то тут, как обычно, все хуже. Из-за того что типы указателей неявно конвертятся в массивы и наоборот. Очевидно, что Cow * есть подтип Animal * — но благодаря неявным преобразованиям, Cow[] будет подтипом Animal[], и это практически всегда будет приводить к ошибкам при вычислении смещений на элементы массива. см. C++ FAQ Lite.

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

Немножко ссылок по теме:


Tuesday, August 14, 2007

Cтатическая и динамическая системы типов: распространенные заблуждения

В продолжение предыдущего поста. В основном, по мотивам этого эссе

Для начала факты:

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

А теперь несколько самых распространенных заблуждений о системах статической и динамической типизации:

1. Статическая типизация подразумевает объявления типов

Дело в том, что Java, Pascal, C++ и C не просто языки со статической типизацией — это языки с явным объявлением типов. Многим не нравится тратить кучу времени на описание типов функций и переменных, и они не любят статически типизированные языки именно по этой причине. Это зря, потому как, скажем в ML и Haskell типы объявлять в большинстве случаев не нужно, при этом они являются на 100% языками с развитой системой статической проверки типов. Вот и в C# (и C++) сейчас видны подвижки в сторону включения в язык неявного вывода типов в некоторых случаях.

2. Динамическая типизация = "слабая" типизация

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

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

А все дело в том, что в динамических языках сам подход другой, главным образом это быстрое написание кода и интенсивное тестирование потом. В динамических языках есть отличные средства для быстрого и четкого отлова рантайм ошибок, с диагностикой, которая покажет вам, почему именно ошибка произошла (см. идеологию "Let it crash" в Erlang.)

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

Некоторые статически типизированные языки и правда устроены так, чтобы стимулировать определенный подход к процессу разработки. Пример этого — требование объявлять все переменные заранее в Паскале, заголовочные файлы в C++ (хотя там это отчасти продиктовано практическими соображениями).

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

4. Языки с динамической типизацией не предоставляют средств для поиска багов на этапе разработки

Распространенный аргумент против динамических языков — это то, что ошибки вылезают у пользователя, а не у разработчика. Однако, в реальности это происходит очень редко, так что аргумент хреновый — программы на динамических языках в среднем содержат не особенно больше ошибок чем на языках вроде C++ и Java. Если это вообще можно измерить.

5.  Статическая типизация ведет к более объемным исходникам

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

Красивый пример из Haskell: есть функция lookup, которая ищет в Map (ассоциативном массиве) значение по ключу. Тип у нее такой:

lookup :: (Monad m, Ord k) => k -> Map k a -> m a

Если кто с хаскелем не знаком — у функции два аргумента, ключ типа k и ассоциативный массив с типом ключа k и типом значений a. Возвращает функция значение типа a, завернутое в монаду m.

Вроде все просто, но что она должна делать если ключа такого нет? Возвращать специальное "пустое" значение? Прерывать вычисления и переходить к обработчику ошибок? Или вообще завершать выполнение программы? Фишка в том что функция эта может делать все вышеперечисленное, вот как это выглядит:

case (lookup bobBarker employees) of
    Nothing -> hire bobBarker
    Just salary -> pay bobBarker salary

Как Хаскель узнал что мы хотим именно первый вариант, получать значение Nothing в случае ошибки? Он увидел что мы сравниваем результат с Nothing, и вывел соответствующий конкретный тип для монады m. Если б мы не написали этого куска кода, обрабатывающего ошибки сразу, а воткнули бы обработчик ошибок где-нибудь несколькими уровнями выше по стеку — Хаскель тоже правильно вывел бы тип, и можно было б вызывать lookup несколько раз, не заботясь о том, что ключа может не оказаться.

Оригинал: "What To Know Before Debating Type Systems"

 


Monday, August 13, 2007

Типы: микроFAQ/ликбез

В основном это вольный перевод избранных мест из "What To Know Before Debating About Type Systems" и статьи L. Cardelli "Type Systems".

Итак,

Определение

Одного простого и общепринятого определения понятия "тип" или "система типов", как ни странно, нету. Основное назначение системы типов это обнаружение ошибок, которые могут возникнуть при выполнении программы. Весьма известный деятель в области computer science, лауреат премии Тьюринга Лука Карделли приводит такое несложное определение:

Тип переменной -- это множество значений которые может принимать переменная во время выполнения программы.

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

Если хотите чего-нибудь более философского, то можно обратиться к книжке Б. Пирса "Types and Programming Languages", где он дает более хитрое определение для системы типов:

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

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

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

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

Строгая типизация

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

Статическая vs Динамическая система типов

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

Если такие операции приводят к каким-то непредсказуемым в общем случае последствиям, можно смело говорить что типов нету вообще. Товарищ Карделли вот называет это untyped unsafe languages, и приводит в пример ассемблер.

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

Карделли вот вообще осознанно не использует термин "динамическая типизация" — вместо этого у него "динамические проверка [значений]", а подобные языки называет untyped safe languages. Это он не потому что считает, что динамические языки это не тру, а потому что путаница получается серьезная.

 Продолжение следует


Дисклеймер / Анонс

Поскольку я неожиданно узнал как делать урезанные посты в блоггере (с кнопочкой Read More), потоки моего графоманства теперь ограничивает только отсутствие свободного времени :)

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


Monday, July 30, 2007

Simon Peyton Jones на OSCON 2007

На прошлой неделе, на весьма известной конференции O'Reily Open Source Convention, пару докладов делал наш любимый Simon Peyton Jones.

Первый — "A Taste Of Haskell", очень краткое введение в хаскель — однако Саймон успел затронуть очень много интересных моментов. Почитать слайды можно тут (6.8 MB).

Второй, про Software Transactional Memory, можно даже посмотреть, тут (44 MB, 16 мин).

В качестве бонус-трека — Саймон в двух словах рассказывает о том, как мы достигнем Programming Language Nirvana (114 MB, 6 мин).


Friday, July 27, 2007

Ruby On Rails сделает вас счастливыми

Если б я не имел понятия что такое Ruby On Rails, прочитав этот пост "The Business Advantage of Rails", я бы очень испугался. Нормальные люди не могут излучать столько немотивированного позитива. Не удивлюсь если автор является еще и предводителем секты "Свидетели Руби".

Programmer happiness is a guiding design principle in both Ruby and Rails. One reason people work with Rails is because they value their own happiness.

В общем нанимайте программистов на руби -- они счастливые люди, и делают все вокруг счастливым. В том числе и ваш бизнес.

The politics of happy people are infinitely preferable to the politics of unhappy people.

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

Рекомендуется к прочтению, особенно в пятницу вечером ;)


Monday, July 23, 2007

Динамические языки под .net продолжают размножаться

Прошло всего-то два месяца после выхода библиотеки Microsoft DLR, а реализации разных динамических языков растут буйным цветом. Основные все уже на подходе:

  • Python — ну IronPython не в счет, потому как из него DLR собственно и вырос
  • Nua - проект интерпретатора lua под .net было загнулся, но теперь авторы его активно реанимируют и переносят на рельсы DLR.
  • И, наконец, Ruby - исходники IronRuby сегодня выложены в открытый доступ, под Microsoft Permissive License. Говорят, по синтетическим тестам уже эта версия кое-где обгоняет Ruby 1.8.6.

Ожидается также в скором времени реализация "самого недооцененного" языка — ECMAScript, он же javascript.

Все это довольно радужно, интегрировать какой-нибудь скриптовый движок в свое десктопное приложение получается совершенно раз плюнуть. Не нужен ни громоздкий windows scripting host, все получается даже проще чем подход в boost::python/lua и SWIG.

Веб-приложения тоже выигрывают, можно, скажем, иметь IronPython / IronRuby как фронтенд для интерфейса и всяких несложных операций, и C#/F# как бэкенд. Правда, насколько я понимаю, связь тут обычно все равно через RPC идет, но общая платформа (.net) это дело должна все равно упростить.

Усиленно надеюсь на ответный удар от Sun — хорошо работающий и отлаженный набор Java/Scala + JRuby/JPython.


Thursday, July 19, 2007

Software Engineering Radio

Открыл для себя отличный подкаст по всяких теме языков программирования, методик разработки и пр.: "Software Engineering Radio". У кого нету особенных проблем с английским — очень рекомендую: www.se-radio.net

Несколько интересных передачек:

  • Мартин Одерски рассказывает про Scala
  • Неизвестный мне Laurence Tratt рассказывает про придуманный им диалект питона с поддержкой compile-time metaprogramming
  • Интервью с Гради Бучем (не знал, что он так похож на хиппи, прям вылитый Ричард Столман):

 

  • Интервью с Гаем Стилом мл. (да-да, тот который один из разработчиков Явы и Fortress)

Там много еще интересного, в том числе подкаст про внутренности gcc, про статический анализ кода, про разработку DSL и пр.

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


Sunday, July 15, 2007

Тру программист Olin Shivers

Решил чуточку реанимировать серию постов про тру программистов, начатую этим постом.

Olin Shivers — разработчик scsh, unix shell, основанный на синтаксисе Scheme. Был среди организаторов соревнования по функциональному программированию ICFP'98, редактором на нескольких конференциях по функциональному программированию вообще, и Scheme в частности. Автор многих работ, в основном по Scheme и по Control Flow Analysis.

Заслуживает звания тру программиста главным образом за замечательный раздел Acknowledgements к мануалу к scsh (смотреть тут):

...A 10 oz. Jack 'n Zac helps me get through the meetings without one of my students winding up with his severed head in a bowling-ball bag. They look at me funny; they think I twitch a lot. I'm not twitching. I'm controlling my impulse to snag my 9mm Sig-Sauer out from my day-pack and make a few strong points about the quality of undergraduate education in Amerika...

Думал перевести, но вряд ли мне бы удалось точно передать настроение.

Автор всячески отжигает и у себя на страничке.


Sunday, July 08, 2007

Open Source 3D принтер за 500$

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

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

Принтер в общем-то уже работоспособен, на сайте у них можно посмотреть кучу видео, как он с переменным успехом "печатает" разные пластиковые штуковины.

Работает по принципу напыления какого-то специального полимера тонкими слоями -- то есть, насколько я понимаю, может и внутренние полости, скажем, делать.

Сайт проекта тут: reprap.org
Блог тут: blog.reprap.org
Страничка проекта на sourceforge тут: sourceforge.net/projects/reprap/

Да, написано все в основном на яве. Даже не на RTS.


Tuesday, June 26, 2007

Стековые языки

Почему-то наиболее активно пишущими блоггерами в области языков программирования и computer science в моей rss читалке последнее время оказываются авторы двух стековых языков -- Cat и Factor. Если пробежаться по ссылкам — оказалось в этой области происходит много интересного.

 * * *

Наиболее известным и распространенным стековым языком до сих пор является Forth, а в 80-е он вообще очень широко использовался в embedded системах. Чуть ли не каждый третий девайс программировался на Форте.

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

Вот функция которая возводит аргумент в квадрат

SQUARE ( a -- b ) DUP * ;

В скобочках это комментарий (обозначает что на входе одно число, на выходе одно), DUP клонирует значение на вершине стека, * берет со стека два значения, умножает, и кладет результат на стек.

Затем году в 2001-м появился чисто функциональный стековый язык Joy. Состояния, как и полагается в функциональном языке — нету, абстракций (формальных параметров у функций) нету тоже, в целом все весьма похоже на point-free стиль в Хаскеле. Функции рассматриваются как пробразования Stack -> Stack. Есть higher-order функции и прочие замечательные вещи.

Joy в свою очередь вдохновил еще нескольких товарищей на создание еще нескольких интересных вариантов стековых языков.

Во-первых, Factor — динамически типизированый стековый язык, с функциями высшего порядка, сборкой мусора. Портированый на приличное количество платформ и динамично развивающийся.

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

И, в-третьих — Enchilada, тоже чисто функциональный язык, предназначенный для параллельных вычислений. Замечателен тем, что строго статически типизирован, но тип в нем всего один — это список. То есть, скажем, число 3 считается эквивалентным списку, содержащему три пустых значения. В общем почитать очень интересно, например, умножение чисел там реализовано через декартово произведение таких списков, а по дизайну Enchilada очень напоминает APL-подобные языки, только с более человеческим лицом.

Ссылки:


Ну и про форт немного интересного до кучи:

1Получается это вроде как засчет использования equirecursive типов. Почему в Хаскеле/ML используются isorecursive типы я еще не осознал, если кто объяснит -- буду очень благодарен :)


Saturday, June 09, 2007

Indeed Job Trends - Тенденции на рынке труда

Набрел на отличную игрушку -- поисковик по рынку труда indeed.com (не нашему, конечно, но все равно интересно), но самое замечательное там -- это тулза наподобие google trends, только по предложениям работы. Сижу развлекаюсь вот.

C++ против C# против java

Python против Руби против Лиспа

Окемл и F# (по F# скорее всего неправильные данные -- у него и у хаскеля вообще неудобные названия для поисковиков :)


Tuesday, June 05, 2007

Новая серия Design & Evolution of C++

По сцылке с ltu можно найти статью-продолжение бестселлера известного датского писателя Б. Страуструпа "Дизайн и эволюция C++", охватывающее период с 2001 года по настоящее время.

Не сильно интересующиеся процессом люди (типа меня), могут узнать много нового. Например, я наконец увидел ту фичу, до которой Страуструп мог бы додуматься и 20 лет назад, которой так сильно начинает не хватать в C++ после знакомства с любым нормальным (особенно функциональным) языком программирования -- итак, в C++ будут наконец более-менее нормальные enum типы. *Аллилуйя*. Они не будут неявно конвертится в int, у которых будет определен физический размер, которые можно будет нормально использовать в качестве параметра шаблона и имена которых будут определены внутри пространства имен, задаваемого именем enum'а (т.е. enum E { A } будет доступен как E::A). Это пока только предложение, но отец всех C++ программеров считает, что наверное его примут.

Другой интересный документ, к которому он и сам приложил руку  -- это предложение включить лямбды с замыканиями в C++. Мысль неплохая, но без GC все это, естественно, будет еще одним месторождением тормозов и граблей (в виде, преимущественно, висячих ссылок).

Глючить будет так:

tr1::function<int(int)> foo() {
 A a;
 A *b = &a;
 return (<>(int) { *b = 3; return 0; });
}

tr1::function<int(int)> a = foo();
a(1); // локальная переменная а 
 // внутри foo() уже уничтожена, но
 // лямбда ее использует
Сравним это все с garbage-collected языками где все объекты на хипе, и убиваются когда надо.

А тормозить будет поскольку для локальных объектов которые использует замыкание, по дефолту создается копия. Сравним это с garbage-collected языками, где замыканию достаточно указателя на объект.

Ну и для тех кому не интересны технические подробности, в статье можно почитать про процесс принятия стандарта и включения в него STL, а также причитания по поводу java, особенно понравилось вот это

I see Java as a Sun commercial weapon aimed at Microsoft that missed and hit an innocent bystander: the C++ community.

Вообще яве там целых несколько страниц посвящено, видно, годы аггрессивной рекламы явы как убийцы С++ не прошли даром для бедняги Страуструпа.

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


Tuesday, May 29, 2007

Функциональные языки: вести с полей

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

Haskell

Мейнстримом, понятно, ему не быть, слишком много сложных экспериментальных фич, язык, крутая learning curve -- учитывая все это, можно сказать что хаскель уже популярен донельзя. Кое-где даже встречается в объявлениях о поиске сотрудников, у "них" вот Credit Suisse его использует. Pugs тоже сыграл большую роль в том что название "хаскель" слышали даже не очень сильно интересующиеся вопросом товарищи. Насчет того чтоб он как-то серьезно применялся в России -- не слышно и не видно.

O'Caml

Окемлу лет тоже уже много, так что резкие всплески популярности он уже пережил -- самый прагматичный язык, с замечательным оптимизирующим компилятором. В Jane's Capital вроде как его активно любят (почитать можно тут). Рекрутеры продвинутые тоже знают. Вот тут  люди в Москве на нем даже игры разрабатывают.

F#

Бурно развивающийся диалект Ocaml'а для .net. Точнее от ocaml он уже довольно-таки далеко. Огромный плюс в том что засчет использования .net нахаляву получаем интеграцию с C#, гуи и IDE. В этом году выходят сразу три книжки по F#,  активно пиарятся две консалтинговые конторы специализирующиеся на F#: вот и вот. ИМХО вполне себе положительный знак. Программеров на F# правда пока никто не ищет.

Scala

Новый язык, на базе JVM, поддерживает кучу интересных фишек, типа GADT, ОО модель плотно интегрирована с функциональщиной. Больше всего сейчас слышно про веб-фреймворк на scala -- lift. В качестве killer app приводится клон вебдваноль сервиса twitter в 800 строчек, вроде как способный обслуживать до миллиона юзеров с одного сервера. В общем, по мне так -- язык просто замечательный, даже приятнее окемла.

Становится все популярнее и популярнее -- у меня в google alerts уже половина упоминаний scala относится к языку программирования, а не к одноименному оперному театру. Полгода назад показатель составлял 20%.

Erlang

Эрлэнг это, кажется, наиболее успешный функциональный язык после excel'я -- потому что изначально создавался для решения практических задач, и рассчитан на относительно низкий порог вхождения для обучаемых программистов. Killer App из мира open source это jabber-сервер ejabberd. Ну и хрестоматийный пример про маршрутизатор AXD301 на эрланге.

В плане работы -- есть несколько организаций в России которые, похоже, используют Erlang вполне промышленно. Судя по объявлениям о приеме на работу в Питере это StanaPhone (российское отделение крупной американской компании, разрабатывающей VoIP приложения). А в Москве прям сейчас ищет Erlang-программистов довольно крупная медиа-компания A1.


Sunday, May 13, 2007

Новый C++09 ISO Standard Draft

..если кому интересно, можно взять тут.

Тут вот также пост Герба нашего Саттера, а так же видео (по ссылкам от [info]aruslan   ). Те, кто немного следит за процессом, вряд ли увидят там что-то новое — Саттер вот пишет про typedef templates и темплейты с произвольным количеством параметров. Для меня правда новостью было нечто под названием programmer-directed garbage collection.

 

В затихших нынче holy wars на тему C#(Java) vs C++ обычно рано или поздно всплывал тезис "да в C++ можно с полпинка сделать gc, тока кому это надо?" — поэтому почитать proposal на эту тему вдвойне интересно.

Авторы, в лучших традициях C++, подошли к вопросу аккуратно, чтобы никакой имеющийся код не поломать — и у них получилось, но, как обычно, те, кто будет этот самый GC все-таки использовать, получают дополнительный лес граблей.

В двух словах — сборщик мусора тупо сканит все объекты на наличие указателей (на уровне бинарного представления, независимо от типа). А чтобы он не надорвался, программист может ему поклясться в type safety для конкретного класса/структуры/модуля/переменной — то есть обещает с поинтерами никаким сексом не заниматься (прежде всего в int'ы, char[] и другие неподходящие места их не записывать). Тогда сборщик мусора будет обрабатывать только переменные, имеющие C++-тип указателя.

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

Плюс к этому, не совсем ясно будет ли gc двигать в памяти объекты — если не будет, то эффективность его под вопросом, если будет — всплывет изрядное количество всяких неочевидных проблем. Например, непонятно что будет с конструкциями типа std::map<Foo *, ...> в случае если объект может "плавать" в памяти.

В общем Саттеру с Мейерсом и Александреску материала для книжек "как обойти все подводные грабли C++" хватит еще надолго.


Monday, May 07, 2007

Компилятор C++ MADE IN RUSSIA

Конечно, новость не очень свежая, но я вот только недавно узнал о существовании натурального компилятора C++, полностью разработанного в России для нужд военных и всяких ФГУПов.

Компилятор в довольно-таки большой степени соответствует стандарту (ну, по крайней мере, явных косяков не видно). Плюс IDE на базе Eclipse/CDT. Плюс к нему прилагается набор тулзов для анализа программ, включая реверс-инжиниринг исходник->UML.

Есть онлайн-компилятор (а-ля comeau), сам компилятор скачать нельзя (а так хотелось проверить — вдруг там и export template реализован?).

Забавно: это все разрабатывалось для нужд разных государственных предприятий, и этот факт наложил таки отпечаток: во всех мануалах абсолютно все термины переведены на русский ("компилятор переднего плана"), а в самом компиляторе есть даже возможность заменить все ключевые слова на русские эквиваленты ("конст_прив" это const_cast, например). Но тут по-моему это только придает некоторый шарм :)

Единственный(похоже) реализованый пока back-end для компилятора тоже заслуживает внимания — он генерит код для российского сигнального процессора "Мультикор" ([имхо] наивысшее достижение отечественной микроэлектроники за последние 15 лет).

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


Friday, May 04, 2007

Динамические языки внутри .net и JVM

В продолжение к предыдущему посту — а собственно почему столько шума? Зачем столько пафоса при релизе DLR?

А дело все в том, что и sun и microsoft последние несколько лет внимательно смотрят в сторону динамических языков. Потому как различные php, python'ы и ruby играют нынче мощную роль на рынке — и на этот рынок, конечно, хочется влиять.

Когда создавались .net и JVM основной их задачей было соответственно выполнение C# и Java программ, об остальном их создатели думали не столь внимательно. Как заметил автор этой презентации, по аналогии с известным высказыванием Г. Форда, "вы можете запустить на .net любой язык, если это C#".

Однако вскоре стало понятно что одной явой и C# при написании веб-приложений сыт не будешь, тут-то собственно языки тоже заинтересовали и sun, и ms — последняя наняла Jim Huguin'а, автора JPython, а sun прошлым летом наняла авторов JRuby.

Проблемы реализации прежде всего вырастают из того факта, что и CLI, и JVM прежде всего ориентированы на языки со статической типизацией — у них даже байт-код строго статически типизированный. А динамическому языку нужно позднее связывание (оно же динамическая диспетчеризация) — при вызове a.someMethod() какой именно метод вызывать выясняется во время выполнения, основываясь на динамическом типе значения a. Причем a вообще может не иметь такого метода — это заранее неизвестно.

А при вызове call, callvirt в .net мы должны заранее, статически, знать класс объекта (как и при вызове метода — обычном или виртуальном — в C++).

Конечно, проблема решается довольно-таки очевидным способом — в CLR и java все классы наследуются от корневого Object — соответственно процедуры в динамическом языке получают тип Object someMethod(Object[] args), и в местах вызова вставляется код который ищет в словаре соответствующий метод у объекта. С одной стороны тут возникает некоторое количество сложностей, с другой — благодаря развитому reflection'у и генерации кода на лету — все проблемы решаются, и даже получается оптимизировать такие вызовы — если в o.someMethod() значение переменной o имеет всегда один и тот же тип, каждый раз тратить O(logN) времени на поиск по словарю не надо, и т.п.

Эффективные, обкатанные на IronPython решения для этой и других (динамическая типизация, изменение классов на лету, closures...) проблем как раз и предоставляет DLR. Для JVM кстати что-то похожее уже создавалось — однако то ли эту библиотеку вообще не релизили, то ли я плохо искал. А вообще уже несколько лет тянется процесс добавления в яву байт-кода invokedynamic — который будет как раз реализовывать позднее связывание на уровне виртуальной машины.

Теперь интересные линки:
Итого, что мы имеем из динамических языков, компилируемых в байт-код:
на JVM: JPython, JRuby, Groovy на CLI: IronPython, JScript.Net, VB.NET, PHP (На самом деле динамических языков намного больше, но остальные вроде как в байт-код напрямую не компилируются).

JVM:



.NET:


Tuesday, May 01, 2007

Microsoft Dynamic Language Runtime

Сегодня наш любимый большой брат microsoft сделал еще шаг навстречу динамическим языкам на платформе .net: на конференции mix'07 объявил о релизе DLR -- Dynamic Language Runtime, по аналогии с известным всем Common Language Runtime.

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

А библиотека эта выросла из проекта IronPython -- реализации Python под .net созданной CLR Team. Основной в этой команде инжынер Jim Hugunin, до того как его взяли в майкрософт, написал на досуге компилятор Python под JVM. Дядька, в общем, в высшей степени интересный, блог его тут.

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

Да, все это происходит в контексте усиленного продвигания майкрософтом своего веб2десктоп фреймворка Silverlight, так что по ссылкам он упоминается очень интенсивно -- не удивляйтесь :)

Еще пара ссылок:


Monday, April 23, 2007

DirectX 10 на Windows XP

Повеселила новость с этим заголовком на theinquirer'е сегодня -- суть в том что некий товарищ обещает скоро выдать некий мега-интерпретатор для запуска виндовых программ на MacOS и linux (меньше, быстрее и удобнее чем wine в стотыщраз).

Решил он начать с малого -- сначала сделать мега-интерпретатор не для всех программ, а только для игрушек с поддержкой DX10 ;)

А на днях вот с пафосом зарелизил альфа-версию интерпретатора, якобы позволяющую пускать DX10 приложения под XP. Лучше б он этого не делал, а продолжал себе собирать по полтиннику уе за доступ к альфа-превью-версии мегаинтерпретатора. Потому как эти 50 баксов служили, видимо, фильтром, допускающих к телу мегапроджекта только идиотов, а теперь любой здравомыслящий человек может взять дизассемблер и увидеть что мега-интерпретатор является лишь хреновой попыткой реализовать интерфейсы DX через OpenGL, и реализовано там только полторы несложных функции типа CreateTexture().

У товарища явно большое большое будущее в PR. И зря он себя в профиле блога скромно называет software reverse engineer'ом :)


Friday, April 20, 2007

VB for DOS

Сейчас вот наткнулся на ностальгический пост Нейла Митчелла (рекомендую, кстати, блог) про версии Visual Basic'а которые он юзал, и вспомнил про намного более гламурный чем все эти VB 3,4,5,6 настоящий Visual Basic 1.0 for DOS

Мега-вещь была, дельфи отдыхает -- настоящая RAD среда под DOS, рисование мышкой контролов, назначение всяких событий им, и все в стандартном 80x25 текстовом режиме!
Если вдруг кому-то тоже хочется поностальгировать, тут валяется дистрибутив :)


Sunday, March 18, 2007

Компилятор CAML в 2000 строк

Часть курса по процессорам и компиляторам из японского Tohoku University -- написание маленького оптимизирующего компилятора CAML.

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

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


Tuesday, March 06, 2007

Очень параллельные языки

В продолжение к предыдущему посту, как пример параллельного языка который мог бы неплохо лечь на GPU (с серьезными изменениями конечно) -- ZPL.

Намного более дружественный синтаксис чем у APL (не нужна специальная клавиатура :), и даже чем у его диалектов J и K.

Выглядит вот так:

region R = [1..n, 1..n ];
RowVect = [ * , 1..n ];
ColVect = [ 1..m, * ];
var M: [ R ] double;
    V: [ RowVect ] double;
    S : [ ColVect ] double;
  [ ColVect ] S := +<<[R ] (M * V);

Замечательное введение в ZPL в комиксах можно смотреть тут.

В общем-то влияние APL на него чувствуется весьма, жалко в отличие от J он функциональным таки не является.

Зато есть функциональный язык NESL, умножение матрицы на вектор на нем выглядит вообще довольно непримечательно для тех кто видел какой-нибудь непараллельный функциональный язык:
 sum({v * x[i] : (i,v) in row});

Что неудивительно, поскольку любой функциональный язык, все эти filter'ы и map'ы просто так и просят чтоб их распараллелили.

Ну и естественно Data Parallel Haskell наше все:
smvm sm vec = 
[: sumP [:x * (vec!:col)|(col, x)<-row :]|row<-sm:]
Это опять таки умножение матрицы на вектор, и неспроста авторы DPH главным прототипом своей библиотеки считают NESL. Поэтому можно было и не приводить этот пример, но не упомянуть про Хаскел я не cмог :)