tag:blogger.com,1999:blog-327579022024-03-13T22:25:07.906+03:00Как сломать мозг за 21 день.lrrrhttp://www.blogger.com/profile/12742106367384624657noreply@blogger.comBlogger72125tag:blogger.com,1999:blog-32757902.post-75703845507169321102009-07-21T13:45:00.002+04:002009-07-21T13:49:59.866+04:00Практика ФПХотя у всех заинтересованных лиц рсс ридер уже наверняка забит пеаром первого выпуска журнала <a href="http://fprog.ru/2009/issue1/">"Практика функционального программирования"</a>, не могу не отметиться тоже.lrrrhttp://www.blogger.com/profile/12742106367384624657noreply@blogger.com12tag:blogger.com,1999:blog-32757902.post-88637303344967606382009-07-21T02:45:00.006+04:002009-07-21T11:52:28.814+04:00Concepts Get Voted Off The C++0X<p>Вот тут, по <a href="http://lambda-the-ultimate.org/node/3518">ссылке с ltu</a>: — из C++0x решили убрать concepts! :)</p>
<p>Мне не то чтобы C++0x интересен с практической точки зрения, но это просто мощнейший ход. </p>
<p>Почему убрали: с одной стороны, часть ортодоксов не поняла зачем оно надо, и испугалсь что будет слишком легко отстрелить себе ногу (и это они про C++ говорят, хехе). С другой стороны, комитет по стандартизации испугался что авторы фичи не успеют ее допилить.</p>
<p>Кроме того, примечателен первый же камент от одного из авторов этой фичи — судя по тому, что он три раза упоминает там хаскель, становится совсем уж окончательно понятно откуда чуваки черпали вдохновение.</p>
<p>(<i>Поскольку не все читатели моего бложека являются сиплюсплюс программерами, вкратце поясню — concepts была одной из наиболее ожидаемых фич нового стандарта популярного когда-то языка сиплюсплюс, что-то похожее на type classes в хаскеле</i>)</p>lrrrhttp://www.blogger.com/profile/12742106367384624657noreply@blogger.com4tag:blogger.com,1999:blog-32757902.post-23528995856414630242009-01-25T00:06:00.006+03:002009-01-25T13:31:15.868+03:00Yaws и потребление памяти<p>Уважаемые телерадиослушатели, мегаблог не совсем умер :) </p> <p>В комментариях к <a href="http://brainslugs.blogspot.com/2008/02/yaws-erlang.html">записи про Yaws</a> жжюзер <span style="display: inline-block; white-space: nowrap; height: 17px"><a href="http://alekciy.livejournal.com/profile"><img style="border-top-width: 0px; display: inline-block; line-height:18px; padding: 0px; margin: 0px; border-left-width: 0px; border-bottom-width: 0px; vertical-align: bottom; border-right-width: 0px" height="17" alt="[info]" src="http://stat.livejournal.com/img/userinfo.gif" width="17" /></a><a href="http://alekciy.livejournal.com"><b>alekciy</b></a></span> поинтересовался, сколько yaws будет хавать памяти на одно HTTP соединение. Понятно, что немного, но конкретные циферки всегда красноречивее слов. Не вопрос — на коленке собрался небольшой test suite. По хорошему тут надо было бы взять нормальный стенд — сервер и пяток клиентов (давняя мечта, повторить <a href="http://www.sics.se/~joe/apachevsyaws.html">тот самый тест</a> самому, так как его справедливо критикуют за отсутствие подробного описания условий тестирования), но под рукой только рабочий нотебук с убунтой 8.04 (Celeron 1.7, 2G памяти). </p> <p>Итак, берем yaws 1.79, в качестве генератора траффика программка на C, за основу взял пример работы с epoll <a href="http://asistobe851.hp.infoseek.co.jp/C-and-C++/epoll-client.html">какого-то японца</a>. </p> <p>Тупо создаем соединения к серверу, запрашиваем файл и мееедленно (по байту) читаем ответ. </p> <pre class="console">$ uname –a
Linux lrrr-laptop 2.6.24-23-generic #1 SMP Thu Nov 27 18:44:42 UTC 2008 i686 GNU/Linux </pre>
<p><a href="http://ajaxie.com/http-conn-test.tar.gz.gz">Исходники клиента.</a> </p>
<p>График: </p>
<p> <a href="http://ajaxie.com/images/yaws_15134/yawsmem.png"><img title="yaws-mem" style="border-right: 0px; border-top: 0px; display: block; float: none; margin-left: auto; border-left: 0px; margin-right: auto; border-bottom: 0px" height="182" alt="yaws-mem" src="http://ajaxie.com/images/yaws_15134/yawsmem_thumb.png" width="242" border="0" /></a> </p>
<p>По оси X — количество одновременных соединений, по Y resident size процесса в килобайтах. Понятно, тут хватило б и двух точек, но мало ли что, вдруг, например, gc стал бы захлебываться с какого-то момента, надо было удостовериться.</p>
<p>После 10000 соединений у меня yaws начинает их дропать, хотя наверняка можно это как-то победить, в связи с убогостью тестовых условий я решил не заморачиваться. </p>
<p>Итого, если поделить — отжирается <strong>14 кб памяти на коннект</strong>. Неплохо. Yaws (ожидаемо) не кушал CPU (показатель болтался около 1-2%), <del>но, почему-то, довольно медленно принимал соединения — удавалось создать порядка 10 коннектов в секунду.</del> </p>
<p>Попытка поставить в те же условия nginx пока не увенчалась успехом, соединения создаются раз в десять быстрее, но в районе 700 коннектов nginx сначала отдает 500 ошибку, потом молча закрывает соединения, а потом начинает приходить ECONNRESET. Думаю, он это делает из лучших побуждений, но я пока не нашел как на это повлиять. </p>lrrrhttp://www.blogger.com/profile/12742106367384624657noreply@blogger.com15tag:blogger.com,1999:blog-32757902.post-45608624835558481192008-07-02T19:36:00.001+04:002008-07-02T19:36:45.661+04:00Erlang job 2<p>И, чтоб два раза не вставать: тут обнаружилась еще одна интересная вакансия в России (Москва) на Эрланге, в стартап <a title="http://artytalk.com/" href="http://artytalk.com/">http://artytalk.com/</a>:</p> <blockquote> <p>Server-side developer:<br>— Писать вместе с командой application server под нагрузку в миллионы пользователей (Erlang, Amazon Elastic Cloud)<br>— Иметь серьезный опыт разработки высоконагрузочных масштабируемых приложений<br>— И снова — любить наш проект, быть хорошим и веселым человеком с мотивацией сделать мир лучшим местом</p></blockquote> <p><a href="http://rsdn.ru/Forum/message/3009393.flat.aspx">Подробнее здесь</a></p> lrrrhttp://www.blogger.com/profile/12742106367384624657noreply@blogger.com9tag:blogger.com,1999:blog-32757902.post-36408749088182006202008-07-02T19:26:00.001+04:002008-07-02T19:26:12.614+04:00Io<p>Тут <a href="http://sdfgh153.ru">Семка</a> после сдачи диплома активно взялся за язык <a href="http://iolanguage.com">io</a>, и генерирует чуть ли не ежедневно крайне познавательные статьи про него, очень рекомендую: <a href="http://sdfgh153.ru/2008/06/io-programming-language.html">раз</a>, <a href="http://sdfgh153.ru/2008/06/io-language.html">два</a>, <a href="http://sdfgh153.ru/2008/07/io-language.html">три</a>. </p> <p>Язык крайне приятный, очень объектно-ориентированный и минималистичный, любителям smalltalk, javascript, ruby или lisp должно понравиться. </p> <p>Кроме того, у нас есть целый irc канал #io-ru на <a href="http://freenode.net/">freenode</a>, так что если ио заинтересовал — присоединяйтесь, да и просто заходите, там уже тусуется некоторое количество знатных рубихакеров и хаскелеводов.</p> lrrrhttp://www.blogger.com/profile/12742106367384624657noreply@blogger.com1tag:blogger.com,1999:blog-32757902.post-50968965186292654732008-05-21T02:35:00.004+04:002008-05-21T17:40:14.588+04:00Map/Reduce своими руками — Apache CouchDb<p> </p> <p>Предупреждаю — мой взгляд совершенно не претендует на какую бы то ни было объективность. Но реляционные базы данных <br />меня никогда, мягко говоря, не вдохновляли. </p> <p>Нет, я вполне понимаю когда у вас <strong>действительно</strong> приложение ориентировано на обработку и хранение больших массивов данных. Ну, ERP-системы, всякие хранилища, статистика там, "в прошлом месяце продали сто тыщ карандашей, в этом двести". </p> <p>С другой стороны, в большинстве случаев, когда речь идет о десктопных (или веб-) приложениях, где не нужно ворочать миллионами примитивных записей,  а приложение работает с относительно высокоуровневыми, сложными объектами, суть "дизайна и проектирования баз данных" заключается в повторении двух действий: </p> <span class="fullpost"> <p>а) расколупать эти высокоуровневые объекты на кучу простейших полей — чисел, строк и сложных зависимостей между ними, и раскидать  между десятками таблиц. Обычно это не очень сложно, однако некоторые (или многие?) типы данных не так уж приятно и органично раскладываются в этой модели — например, теги у записей в блоге; </p> <p>б) затем упорно собирать эти поля в объекты обратно, пользуясь четырехэтажными JOIN'ами, мегабайтами кода врапперов, кривыми и не очень слоями <a href="http://en.wikipedia.org/wiki/Object-relational_mapping">ORM</a> — в зависимости от квалификации разработчика, в общем, всячески преодолевать пресловутый <a href="http://en.wikipedia.org/wiki/Object-Relational_impedance_mismatch">O/R impedance mismatch</a>. При этом и рукописные JOIN'ы не показывают чудеса производительности и гибкости, а сгенеренные автоматически умным слоем врапперов — тем более. </p> <p><a href="http://true.programmer.blog.googlepages.com/SageCRMSalesLogix_v7_Database_Schem.html"><img style="margin: 0px 15px 5px 0px" height="240" alt="SalesLogix v7 Database Schema" src="http://www.ajaxie.com/images/mapreduceApacheCouchdb_EB06/SageCRMSalesLogix_v7_Database_Schema_thumb.gif" width="167" align="left" /></a>В принципе, ORM-библиотеки в динамических языках (см. <a href="http://www.sqlalchemy.org">SQLAlchemy</a>) довольно приятны в обращении, однако и они не позволяют элегантно решить еще один болезненный вопрос — с апгрейдом схемы. </p> <p> </p> <p>В общем, немало приложений используют базы данных для хранения сложных структур данных, и при этом действительно сложные запросы с использованием внутренних зависимостей к этим данным им на практике нужны редко, или вообще не нужны (если не считать мега-JOIN'ов для того, чтобы просто обратно выковырять эти свои структуры из БД). Похоже, обычная RDBMS мало подходит для них — упомянутые выше проблемы довольно болезненно решаются, а миллионы человекочасов тратятся разработчиками БД на реализацию других, бесполезных для них возможностей. </p> <p>Одним решением являются объектно-ориентированные хранилища, они действительно становятся довольно популярны и заслуживают отдельного разговора. Они прозрачно решают проблему с ORM, но, если говорить о веб-приложениях (которые весьма интересуют нас в свете обещаной новой версии <a href="http://defun.ru/">defun.ru</a> :), объектно-ориентированные базы это таки не совсем то, что доктор прописал — они не решают проблем горизонтальной масштабируемости и распределенности данных, да и веб — это прежде всего много текстовой информации, неплохо было бы как-то учесть и это. </p> <p><a href="http://www.ajaxie.com/images/mapreduceApacheCouchdb_EB06/couchdblogo.png"><img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="155" alt="Логотип CouchDb" src="http://www.ajaxie.com/images/mapreduceApacheCouchdb_EB06/couchdblogo_thumb.png" width="174" align="right" border="0" /></a> </p> <p>Итак, <a href="http://incubator.apache.org/couchdb/">CouchDb</a> — документоориентированная база данных. Хранить она умеет <strong>документы</strong> — объекты, состоящие из кучи полей с произвольной структурой. У каждого документа есть только два обязательных служебных поля: имя и версия, имена уникальны и находятся в линейном пространстве — представьте себе гигантскую директорию с файлами-документами, вроде такого: </p> <pre class="json">{
"_id":"63086444D554D3094C080F96D5005B03",
"_rev":"1837603925",
"author":"lrrr",
"tags":["baz","test","ru"],
"url":"http:\/\/incubator.apache.org/couchdb",
"title":"couchdb home",
"description":"boo boo ba ba",
"type":"story",
"comments":1,
"votes":2
}</pre>
<p>Версии нужны для организации параллельного доступа к базе данных — вспомните как работает ваша система контроля версий — если мы хотим изменить документ, мы просто берем его, меняем и пытаемся положить обратно — если за это время его версия не поменялась, все отлично, если поменялась — можно просто попробовать внести те же изменения еще раз, с новым документом, или еще как-то сделать merge (в зависимости от приложения). Это называется optimistic locking, основной плюс — никто не блокирует документ на время редактирования, и поэтому не нужно ждать разблокировки. Кстати, такой механизм может применяться и в некоторых современных RDBMS, только на уровне строк в таблице (см. <a href="http://www.google.com/search?q=%22row+versioning%22">http://www.google.com/search?q=%22row+versioning%22</a>). </p>
<p><a href="http://www.ajaxie.com/images/mapreduceApacheCouchdb_EB06/image.png"><img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; margin: 0px 10px 5px 0px; border-right-width: 0px" height="244" alt="Архитектура CouchDb " src="http://www.ajaxie.com/images/mapreduceApacheCouchdb_EB06/image_thumb.png" width="210" align="left" border="0" /></a>Интерфейс к CouchDb — исключительно HTTP, исключительно  <a href="http://en.wikipedia.org/wiki/Representational_State_Transfer">REST</a>, а ответ от сервера приходит в формате <a href="http://www.json.org/">JSON</a>. Поначалу это несколько настораживает — не самый эффективный протокол, но с учетом того что высокоуровневые документы хранятся в ней целиком, делать по 5-10 запросов к базе на каждый чих и не нужно. А плюсов куча: во-первых, любой язык умеет работать с HTTP и JSON (а если не умеет, легко научить), во-вторых — легко отлаживать, в третьих — CouchDb понимает <a href="http://en.wikipedia.org/wiki/HTTP_ETag">HTTP Etag</a> и If-None-Match, а значит можно без особых усилий прикрутить к базе HTTP кэш.  </p>
<p>Зато масштабироваться вширь все должно отлично — в конце концов, примерно по такой схеме построены и Amazon SimpleDb, и Google BigTable. Удивительное, кстати совпадение, но и SimpleDb, и CouchDb написаны на эрланге ;) </p>
<p> </p>
<p> <a href="http://www.ajaxie.com/images/mapreduceApacheCouchdb_EB06/mapreduce.png"><img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; margin: 10px 0px 0px; border-right-width: 0px" height="130" alt="map & reduce" src="http://www.ajaxie.com/images/mapreduceApacheCouchdb_EB06/mapreduce_thumb.png" width="364" border="0" /></a></p>
<p>Что выгодно отличает CouchDb от сервисов гугла и амазона, так это более "продвинутая" функциональность в области запросов к данным. </p>
<p>Естественно, что менее структурированные данные обрабатывать сложнее, и, раз уж мы так заботимся о масштабируемости — запросы эти тоже должны легко распределяться по кластеру серверов БД. Для этого CouchDb использует паттерн map/reduce, описаный в <a href="http://labs.google.com/papers/mapreduce.html">известной статье</a> инженеров Google.</p>
<p>На практике выглядит это так: на сервере, в специальных документах хранятся view-функции (собственно map() и reduce()), преобразующие набор документов нужным образом, и к ним можно обращаться с помощью того же REST интерфейса. Вычисляться они умеют постепенно, с сохранением промежуточных результатов, то есть, если между двумя вызовами view добавился или изменился один два документа, то функция будет вызвана только для них. Пишутся они на JavaScript, но можно несложно подключить вместо этого python/ruby/что-то еще. </p>
<p>В качестве дополнительного бонуса — поддержка полнотекстового поиска по документам, с помощью любой внешней библиотеки (пока авторы прикрутили к CouchDb поисковик <a href="http://lucene.apache.org/">Apache Lucene</a>). </p>
<p>* * * </p>
<p>В конце обычно принято немного попинать рассматриваемую технологию, но CouchDb мне пинать пока жалко — слишком приятное впечатление производит. Хотя, конечно, это пока всего лишь альфа-версия, со всеми вытекающими последствиями (reduce, скажем, появился в транке три дня назад). Да, она очень небыстрая — пока умеет обрабатывать порядка десятков insert'ов в секунду (если не использовать режим bulk update) и да, она жрет очень много дискового пространства — так как все промежуточные версии документа сохраняются, если их периодически не удалить специальной функцией "Compact Database" — впрочем, это можно делать параллельно, не останавливая приложение. Однако для альфы система весьма стабильна и уже имеет, среди всего прочего, очень приятный и функциональный веб-интерфейс для администрирования и разработки. </p>
<p> </p>
<p>Ссылки: </p>
<ul>
<li><a href="http://incubator.apache.org/couchdb/">Официальный сайт проекта</a>  </li>
<li><a href="http://damienkatz.net/">Damien Katz — ведущий программист CouchDb</a> </li>
<li>Блоги еще двоих: <a href="http://www.cmlenz.net">Christopher Lenz</a>, <a href="http://jan.prima.de/plok/">Jan Lehnardt</a> </li>
<li><a href="http://rashkovskii.com/articles/2008/4/26/top-10-reasons-to-avoid-document-databases-fud">Top 10 Reasons to Avoid Document Databases FUD</a> — хорошая статья, почему не надо бояться нереляционных баз данных </li>
<li><a href="http://www.automatthew.com/2007/12/amazon-simpledb-and-couchdb-compared.html">Amazon SimpleDB and CouchDB compared</a> </li>
<li><a href="http://www.ajatus.info">Ajatus</a> — распределенная CRM-система, использующая CouchDb </li>
</ul>
<p> </p>
<p style="font-size: 1px">27723148.0f886b0078628df55b2305efb1cb3729.1211322056.6554977ddd1d9ebd9f3e14154e6e8540</p>
</span>lrrrhttp://www.blogger.com/profile/12742106367384624657noreply@blogger.com27tag:blogger.com,1999:blog-32757902.post-30864893857811672852008-04-11T14:32:00.002+04:002008-04-11T15:45:12.176+04:00Анонс<p>Тем временем мы с <a href="http://sdfgh153.ru/">Сёмкой</a> организовали тут недодигг для программистов, утилизировав под это его давно пустовавший домен defun.ru</p> <p><a href="http://defun.ru/"><img height="100" alt="header_logo_t" src="http://ajaxie.com/images/56eeebfa82dd_BEB5/header_logo_t.gif" width="102" align="left" border="0" style="border: 0px;"></a> </p> <p>Основная тема — новости и ссылки о функциональном программировании, разных альтернативных и перспективных языках, ну и про computer science вообще. Ключевые слова — хаскель, erlang, lisp, smalltalk, ocaml. Ruby, groovy и питон туда тоже отлично впишутся.</p> <p>Сервис находится в состоянии лямбда-тестирования <a href="http://sdfgh153.livejournal.com/52804.html">©</a>, так что некоторое время все еще будет несколько глючить и тормозить, так что баг репортам мы будем рады -> пишите на <a href="mailto:lrrr@defun.ru">lrrr@defun.ru</a> или <a href="mailto:semka@defun.ru">semka@defun.ru</a>.</p> <p>Надеемся, что когда-нибудь в светлом будущем это станет аналогом <a href="http://www.dzone.com">dzone</a> или вроде того ;)</p>lrrrhttp://www.blogger.com/profile/12742106367384624657noreply@blogger.com25tag:blogger.com,1999:blog-32757902.post-40611516530956383152008-03-03T21:27:00.001+03:002008-03-03T21:27:17.710+03:00Мои пять инструментов<p>Про эрланг серия немного прервалась в связи с отпуском, но продложение обязательно будет — про более прикладную часть, и веб-приложения тоже. Оставайтесь на линии.</p> <p>А пока присоединяюсь к <a href="http://alenacpp.blogspot.com/2008/02/5.html">флешмобу</a> про пять инструментов —правда, не буду здесь особенно оригинален.</p> <ol> <li>Far + <a href="http://colorer.sourceforge.net/">Colorer</a> — лучшая среда обитания <li>MS Visual Studio + <a href="http://www.wholetomato.com/">Visual Assist</a> — лучшая IDE для C++ <li>python для всего, мелкого и среднеразмерного, что надо сделать быстро (иногда еще люблю в этом качестве sh и <a href="http://www.haskell.org/ghc/">ghci</a>) <li>subversion — ну куда ж без контроля версий. Давно порываюсь попробовать bazaar/darcs/mercurial, но все как-то недосуг.. <li>Для коммуникации — gmail — исключительно в качестве почтового сервиса и клиента, и <a href="http://www.gajim.org/">gajim</a> — в качестве IM</li></ol> <p>Последние продуктивность скорее снижают, но и без них я обойтись не могу никак :)</p> <p>А вот любимого редактора для петона/erlang/haskell у меня пока нету — во-первых, стараюсь как раз не особенно привыкать к конкретному редактору, чтоб поменьше таскать с собой настроек с одной системы на другую, а во-вторых, я нахожусь в состоянии медленного переползания на линукс с винды, и окончательного выбора emacs/vim/netbeans/... пока не сделал (хотя vim пока лидирует).</p> lrrrhttp://www.blogger.com/profile/12742106367384624657noreply@blogger.com29tag:blogger.com,1999:blog-32757902.post-42960931647369441382008-02-09T14:49:00.001+03:002008-02-09T16:30:47.893+03:00Yaws — веб-сервер на Erlang<p>В самом начале обещал рассказать про веб-приложения на эрланге. Наверное, пора сворачивать ближе к теме.</p> <p>В качестве веб-сервера для Erlang-приложений лучшим вариантом является написанный на эрланге же веб-сервер Yaws. Чем он хорош — он довольно сильно заточен под высо­копро­изво­ди­тельные приложения, и динамические страницы там удобно генерировать на эрланге.</p> <p>Сначала насчет производительности:</p><span class="fullpost"> <p><img height="288" src="http://www.sics.se/~joe/images/apachevsyaws.jpg" width="400"> </p> <p>Картинка известная, подробнее узнать, как она получена можно <a href="http://www.sics.se/~joe/apachevsyaws.html">тут</a>. По горизонтали это количество параллельных запросов к серверу (очень медленных клиентов), по вертикали — сколько кб/с при этом параллельно может отдавать сервер одному быстрому клиенту. Красненькое это yaws, синенькое и зелененькое это Apache, который после нескольких тысяч тихо умирает.</p> <p>Конечно, Apache сравнивать с yaws не очень честно — все-таки апач продукт сложный и намного более многофункциональный, с кучей дополнительных модулей и настроек, и, в общем-то использовать его для отдачи статических страниц не очень принято. Однако ж картинка все-таки очень показательна, возможность держать много параллельных соединений важна в любом случае, да и с динамикой дела у yaws должны быть тоже хорошо (см. например <a href="http://shootout.alioth.debian.org/gp4/benchmark.php?test=all&lang=hipe&lang2=php">Erlang vs PHP</a> на Computer Language Shootout).</p> <p>Пару слов об установке Yaws — с линуксом проблем, конечно, нет, на винду поставить тоже можно из-под <a href="http://www.cygwin.com">Суgwin</a>, но чтобы избежать лишней головной боли, обратите внимание, чтобы в пути к эрлангу и директории home не было пробелов (а последняя по умолчанию в "Documents And Settings" находится). Еще пара полезных замечаний про процесс установки есть <a href="http://bloggablea.wordpress.com/2007/04/21/building-yaws-for-windows/">тут</a>.</p> <p> </p> <p>Настраивается yaws с помощью конфиг-файла, там все довольно тривиально — дефолтный файл можно пока особенно не менять, разве что установить root директорию (параметр docroot).</p> <p>Простейшее приложение с использованием yaws:</p><pre class="erlang"><span class="Operator"><</span>head<span class="Operator">><</span>title<span class="Operator">></span>Hello world using Yaws<span class="Operator"></</span>title<span class="Operator">></</span>head<span class="Operator">></span>
<span class="Operator"><</span>body<span class="Operator">></span>
<span class="Operator"><</span>erl<span class="Operator">></span>
<span class="Special">out</span>(A) <span class="Operator">-></span>
<span class="Keyword">case</span> queryvar(A, <span class="String">"name"</span>) <span class="Keyword">of</span>
{ok, Name} <span class="Operator">-></span>
{html, <span class="String">"<div style=\"font-size: 12pt;\"> Hello, "</span> <span class="Operator">++</span> Name <span class="Operator">++</span><span class="String">"</div>"</span>};
undefined <span class="Operator">-></span>
{html, <span class="String">"<b> Name parameter required </b>"</span>}
<span class="Keyword">end</span><span class="Special">.</span>
<span class="Operator"></</span>erl<span class="Operator">></span>
<span class="Operator"></</span>body<span class="Operator">></span>
</pre>
<p> </p>
<p>Сохраняем его как hello.yaws в root директории.</p>
<p><a href="http://www.ajaxie.com/images/YawsErlang_5BF/helloyaws.png"><img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="276" alt="hello-yaws" src="http://www.ajaxie.com/images/YawsErlang_5BF/helloyaws_thumb.png" width="405" border="0"></a> </p>
<p>.yaws файл, как уже видно, это просто HTML шаблон. Каждый блок между тегами <erl> и </erl> компилируется в отдельный Erlang модуль. Каждый такой блок должен содержать функцию out/1, которой в качестве параметра передается структура, содержащая параметры запроса. Есть много вариантов как можно возвращать ответ, наиболее интересны два:</p>
<p>использованный выше</p><pre class="erlang">{html, HtmlString}</pre>
<p>Где HtmlString — просто кусок HTML в виде строки, как в примере выше.</p>
<p>И чуть более удобный</p><pre class="erlang">{ehtml, Term}</pre>
<p>Где Term — тот же HTML в виде терма Erlang, где тэги представляются кортежами или списками кортежей. Например, вот такой терм</p><pre class="erlang">{p, [],
[
{b, [], <span class="String">"Hello World"</span>},
{a, [{href, "http<span class="Special">:</span><span class="Operator">//</span>www<span class="Special">.</span>example<span class="Special">.</span>com"}],
<span class="String">"link"</span>}
]
}
</pre>
<p>преобразуется сервером в HTML-строку
<p></p><pre class="erlang"><p>
<b>Hello World</b>
<a href="http://example.com">link</a>
</p></pre>
<p>Выглядит немного жутковато, но быстро привыкаешь и работать с кортежами становится намного удобнее чем со строками.</p>
<p>Еще Yaws, кроме того что является просто веб-сервером, предоставляет немало дополнительных инструментов, таких как автоматическая поддержка сессий, cookie, механизмов удаленного вызова процедур на основе SOAP и JSON-RPC.</p>
<p>Для полноценного фреймворка — аналога Ruby on Rails и прочих, API Yaws, конечно, не дотягивает (для этого есть библиотека <a href="http://erlyweb.org/">ErlyWeb</a>), но для небольших приложений этого должно быть вполне достаточно.</p><pre></pre></span>lrrrhttp://www.blogger.com/profile/12742106367384624657noreply@blogger.com25tag:blogger.com,1999:blog-32757902.post-5170587939465903132008-02-06T00:19:00.001+03:002008-02-06T00:20:14.221+03:00Erlang: инструменты<p>Наверное, в самом начале неплохо было б написать про средства отладки, установке Erlang и так далее — так вот, исправляюсь. <p>Вообще, некоторая проблема с Эрлангом состоит в том, что его разработчики очень не любят писать статьи для начинающих, рисовать туториалы с красивыми скриншотами. Документации по некоторым модулям вообще минимум, по другим — в основном user reference, иногда маленький юзер гайд. Поэтому сначала кажется что разработчик вынужден жить исключительно наедине с консолью интерпретатора — однако это не так! <h5>IDE</h5> <p>В качестве IDE можно использовать <a href="http://sourceforge.net/projects/erlybird">ErlyBird</a> — IDE для Эрланга на платформе NetBeans, соответственно получаем от нее все соответствующие плюшки, выглядит очень красиво: <span class="fullpost"> <p><a href="http://www.ajaxie.com/images/12e3f699c7ce_10274/ScreenshotErlyBird070930.png"><img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; margin: 0px 10px 5px 40px; border-right-width: 0px" height="172" alt="Screenshot-ErlyBird 070930" src="http://www.ajaxie.com/images/12e3f699c7ce_10274/ScreenshotErlyBird070930_thumb.png" width="244" border="0"></a> <p>Есть еще проект <a href="http://sourceforge.net/projects/erlide">ErlIDE</a> на базе Eclipse, но про него ничего сказать не могу — не пробовал. <p>Ортодоксальные товарищи также, конечно, могут заюзать vim, emacs или Far под виндой (простенькими hrc файлами для colorer могу поделиться). <h5>Интерпретатор </h5> <p>erl это собственно интерпретатор Эрланга. Я, кстати, тут везде подразумеваю, что у вас установлен последний релиз R12 — там действительно есть порядочное количество новых полезных плюшек. <p>Полезные функции интерпретатора: <p>- скомпилировать и загрузить модуль <pre class="console">> <strong>c(boo.erl).</strong>
{ok}
</pre>
<p> </p>
<p>- установить текущую директорию </p><pre class="console">> <strong>file:set_cwd(Dir).</strong>
</pre>
<p> <p>Запустить программу на Erlang отдельно, не из интерпретатора чуть сложнее чем в других языках — видимо, потому что большинство приложений на Erlang запускается один раз и потом работает годами.
<p>Можно это сделать с помощью того же интерпретатора: <pre class="console">> <strong>erl -noshell -run <module> <function> [Params]</strong></pre>
<p>(Модуль предварительно надо скомпилировать в байт-код, из интерпретатора или с помощью компилятора erlc).
<p>После окончания работы функции интерпретатор останется висеть, чтобы он закрывался автоматически, можно добавить флаг "- s init stop" (тут за подсказку спасибо анонимному комментатору предыдущего поста).
<p>Либо, для большего удобства, предусмотрен вариант запуска программы как скрипта — с помощью утилиты <strong>escript</strong>. Ей в качестве единственного аргумента передается имя скрипта, а сам он должен экспортировать функцию main(ArgList): <pre class="erlang"><span class="Type">-module</span>(test)<span class="Special">.</span>
<span class="Type">-export</span>(<span class="Operator">[</span>main<span class="Operator">/</span><span class="Number">1</span><span class="Operator">]</span>)<span class="Special">.</span>
main(Args) <span class="Operator">-></span>
<span class="Function">io</span><span class="Special">:</span><span class="Function">format</span>(<span class="String">"Hello world</span><span class="Special">~n</span><span class="String">"</span>)<span class="Special">.</span>
</pre><pre class="console"><b>> escript test.erl</b>
test.erl:4: Warning: variable 'Args' is unused
Hello world
</pre>
<p> <h5>Отладчик</h5>
<p>Кроме этого есть вполне функциональный отладчик с GUI. Если мы хотим поотлаживать наш модуль foo:<br>- компилируем его и загружаем его с отладочной информацией <pre class="console">1> <strong>c(foo, [debug_info]).</strong>
{ok, foo}
</pre>
<p> <p>- Вызываем монитор эрланговских процессов <pre class="console">2> <strong>im().</strong>
<0.181.0>
</pre>
<p><a href="http://www.ajaxie.com/images/12e3f699c7ce_10274/ScreenshotMonitor.png"><img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; margin: 0px 0px 5px 50px; border-right-width: 0px" height="128" alt="Screenshot-Monitor" src="http://www.ajaxie.com/images/12e3f699c7ce_10274/ScreenshotMonitor_thumb.png" width="244" border="0"></a>
<p>- загружаем модуль в отладчик <pre class="console">3> <strong>ii(foo).</strong>
{module, foo}
</pre>
<p> <p>- ставим брейкпоинт на загрузку модуля <pre class="console">4> <strong>iaa([init]).</strong>
true
</pre>
<p><a href="http://www.ajaxie.com/images/12e3f699c7ce_10274/ScreenshotAttachProcess_0.31.0_.png"><img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; margin: 0px 0px 5px 60px; border-right-width: 0px" height="244" alt="Screenshot-Attach Process _0.31.0_" src="http://www.ajaxie.com/images/12e3f699c7ce_10274/ScreenshotAttachProcess_0.31.0__thumb.png" width="218" border="0"></a>
<p>Отладчик, естественно, умеет работать по сети, отслеживать сообщения, приходящие процессам, и много всего другого.</p>
<h5>Остальное</h5>
<p>Если приложение использует эрланговскую распределенную БД mnesia, то нередко нужен удобный способ заглянуть что лежит в табличках. Для этого есть table viewer, который загрузить можно функцией<pre class="console">> <strong>tv:start().</strong></pre>
<p><a href="http://www.ajaxie.com/images/12e3f699c7ce_10274/Screenshottv2.png"><img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; margin: 0px 0px 5px 60px; border-right-width: 0px" height="177" alt="Screenshot-tv2" src="http://www.ajaxie.com/images/12e3f699c7ce_10274/Screenshottv2_thumb.png" width="240" border="0"></a>
<p>Dialyzer — утилита для статического анализа модулей. Иногда позволяет найти интересные ошибки без запуска программы. Запускается так:<pre class="console">> <strong>dialyzer:gui().</strong> </pre>Хотя с некоторых пор dialyzer идет как отдельное приложение в пакете с Erlang.
<p><a href="http://www.ajaxie.com/images/12e3f699c7ce_10274/ScreenshotDialyzerv1.7.0lrrrdesktop.png"><img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; margin: 0px 0px 5px 60px; border-right-width: 0px" height="191" alt="Screenshot-Dialyzer v1.7.0 @ lrrr-desktop" src="http://www.ajaxie.com/images/12e3f699c7ce_10274/ScreenshotDialyzerv1.7.0lrrrdesktop_thumb.png" width="244" border="0"></a>
<p>Интерфейс всех инструментов, конечно, весьма неказист, но интуитивно понятен, и их вполне хватает для полноценного процесса разработки. </p></span>lrrrhttp://www.blogger.com/profile/12742106367384624657noreply@blogger.com6tag:blogger.com,1999:blog-32757902.post-11306868302314440382008-02-02T20:00:00.001+03:002008-02-06T12:14:06.690+03:00Erlang: распределенные приложения<p>Основная фишка erlang — это все-таки его жуткая распределенность. <p>Модель программирования основана исключительно на посылке сообщений. То есть никакой расшаренной памяти, никаких, <br>мьютексов, евентов и прочей ерунды, обычно ассоциирующейся с параллельными (concurrent) приложениями. <span class="fullpost"> <p>Примитивных операций есть три:<br>- можно создать процесс с помощью функции spawn: <pre class="erlang"><span class="Function">spawn</span>(Function)</pre>
<p>- можно ему послать сообщение с помощью выражения ! <pre class="erlang">Pid <span class="Operator">!</span> Message</pre>
<p>- и получить сообщение <pre class="erlang"><span class="Keyword">receive</span>
<span class="Normal">Pattern1</span> <span class="Operator">-></span> <span class="Special">...</span>
<span class="Normal">Pattern2</span> <span class="Operator">-></span> <span class="Special">...</span>
<span class="Normal">Pattern3</span> <span class="Operator">-></span> <span class="Special">...</span>
<span class="Keyword">after</span> N <span class="Operator">-></span>
<span class="Special">...</span>
<span class="Keyword">end</span>
</pre>
<p> </p>
<p> Конструкция receive очень похожа на выражение case, только для обработки таймаутов можно добавить кейс after N, <br>где N — время в мс, по истечении которого перестаем ждать ответа.
<p>[Избитый] простейший пример, с процессами, пингующими друг друга: <pre class="erlang"><span class="Type">-module</span>(<span class="Normal">ping_test</span>)<span class="Special">.</span>
<span class="Type">-compile</span>(<span class="Normal">export_all</span>)<span class="Special">.</span>
ping() <span class="Operator">-></span>
<span class="Comment">% создаем процесс pong</span>
Pid <span class="Operator">=</span> <span class="Function">spawn</span>(<span class="Statement">fun</span> pong<span class="Operator">/</span><span class="Number">0</span>),
<span class="Comment">% посылаем ему сообщение -- атом ping и свой Pid</span>
Pid <span class="Operator">!</span> {ping, <span class="Function">self</span>()},
<span class="Comment">% ждем от него сообщений</span>
<span class="Normal">ping_loop</span>(Pid)<span class="Special">.</span>
<span class="Comment">% обработка сообщений от процесса pong</span>
<span class="Normal">ping_loop</span>(Pid) <span class="Operator">-></span>
<span class="Keyword">receive</span>
{pong, Pid} <span class="Operator">-></span>
<span class="Comment">% получили сообщение pong и Pid отправителя</span>
<span class="Function">io</span><span class="Special">:</span><span class="Function">format</span>(<span class="String">"received pong</span><span class="Special">~n</span><span class="String">"</span>),
<span class="Comment">% ждем случайный интервал времени от 0 до 1200 мс.</span>
<span class="Special">timer</span><span class="Special">:</span>sleep(<span class="Function">random</span><span class="Special">:</span><span class="Function">uniform</span>(<span class="Normal">1200</span>)),
<span class="Comment">% шлем ему опять сообщение ping</span>
Pid <span class="Operator">!</span> {ping, <span class="Function">self</span>()},
<span class="Normal">ping_loop</span>(Pid) <span class="Comment">% и опять ждем...</span>
<span class="Keyword">after</span> <span class="Normal">1000</span> <span class="Operator">-></span>
<span class="Function">io</span><span class="Special">:</span><span class="Function">format</span>(<span class="String">"pong timed out</span><span class="Special">~n</span><span class="String">"</span>)
<span class="Keyword">end</span><span class="Special">.</span>
<span class="Comment">% входная точка процесса pong</span>
pong() <span class="Operator">-></span>
<span class="Keyword">receive</span>
{ping, Pid} <span class="Operator">-></span>
<span class="Comment">% получили сообщение ping и Pid отправителя</span>
<span class="Function">io</span><span class="Special">:</span><span class="Function">format</span>(<span class="String">"received ping</span><span class="Special">~n</span><span class="String">"</span>),
<span class="Comment">% подождем..</span>
<span class="Special">timer</span><span class="Special">:</span>sleep(<span class="Function">random</span><span class="Special">:</span><span class="Function">uniform</span>(<span class="Normal">1200</span>)),
<span class="Comment">% шлем обратно pong</span>
Pid <span class="Operator">!</span> {pong, <span class="Function">self</span>()},
pong() <span class="Comment">% цикл</span>
<span class="Keyword">after</span> <span class="Normal">1000</span> <span class="Operator">-></span>
<span class="Function">io</span><span class="Special">:</span><span class="Function">format</span>(<span class="String">"ping timed out</span><span class="Special">~n</span><span class="String">"</span>)
<span class="Keyword">end</span><span class="Special">.</span>
</pre>
<p> <p>Задержки там я вставил чтобы сымитировать как будто процессы действительно как-то серьезно обрабатывают сообщения, причем иногда не укладываются с этим в таймаут в одну секунду. Итак, запускаем: <pre class="console">1> c(ping_test).
{ok,ping_test}
2> ping_test:ping().
received ping
received pong
received ping
received pong
received ping
received pong
received ping
connection to pong timed out
ok
3> connection to ping timed out
</pre>
<p> <p>Рантайм обеспечивает, что сообщения доставляются в том же порядке, как и были отправлены, и никогда не выпадают из последовательности (то есть, если процесс N+1 сообщение не будет доставлено, если пропало N-ное). </p>
<p>Процессы можно легко и непринужденно запускать и на удаленных машинах, с помощью разновидности той же функции spawn. В большинстве случаев никакой разницы между локальными и удаленными процессами нет.
<p>Чтобы превратить пример с ping в распределенное приложение, нужно просто заменить вызов<pre class="erlang"><span class="Function">spawn</span>(<span class="Statement">fun</span> <span class="Special">...</span>)</pre>
<p>на</p><pre class="erlang"><span class="Function">spawn</span>(<span class="Special">node</span>, <span class="Statement">fun</span> <span class="Special">...</span>)</pre>
<p>Где node это атом-имя узла на котором требуется запустить процесс. виртуальной машины. (А узел (node) — это просто запущенный экземпляр виртуальной машины Erlang).
<p>Итак, немножко изменим функцию ping (модифицированный исходник <a href="http://true.programmer.blog.googlepages.com/ping_distrib.erl.html">тут</a>):<pre class="erlang">ping(Node) <span class="Operator">-></span>
Pid <span class="Operator">=</span> <span class="Function">spawn</span>(Node, <span class="Statement">fun</span> pong<span class="Operator">/</span><span class="Number">0</span>),
Pid <span class="Operator">!</span> {ping, <span class="Function">self</span>()},
<span class="Normal">ping_loop</span>(Pid)<span class="Special">.</span></pre>
<p>Теперь запустим два интерпретатора в качестве узлов с именами boo и foo (оба должны иметь доступ к скомпилированному модулю, так что проще запустить их из одной директории): <pre class="console">$ erl -name foo@127.0.0.1
</pre><pre class="console">$ erl -name boo@127.0.0.1<p></p>
(boo@127.0.0.1)2> c(ping_distrib).
{ok,ping_distrib}
(boo@127.0.0.1)1> ping_distrib:ping('foo@127.0.0.1').
received ping
received pong
received ping
received pong
received ping
received pong
received ping
connection to pong timed out
ok
(boo@127.0.0.1)2> connection to ping timed out
</pre>
<p>Создание процесса в Эрланге — очень дешевая операция (цифры — порядка <strong>сотен тысяч</strong> созданных и убитых процессов в секунду, см. бенчмарк <a href="http://www.lshift.net/blog/2006/09/10/erlang-processes-vs-java-threads">здесь</a> <a href="http://www.lshift.net/blog/2006/09/10/erlang-processes-vs-java-threads)">)</a>. </p>
<p>Запущенные процессы также жрут очень мало памяти, а в режиме ожидания сообщений — еще и не жрут CPU (например, 500000 таких спящих процессов у меня ест 0% CPU и 600 Мб памяти — около 1.4 кб на процесс). </p>
<hr>
<p>Механизмы обработки ошибок в Erlang, конечно, тоже распределенные.</p>
<p>В случае ошибки процесс умирает, и система рассылает всем процессам, <em>связанным</em> с ним специальное сообщение exit. Если тот процесс эти сообщения не отлавливает (для чего у процесса должен быть установлен специальный флаг trap_exit), то система убивает и его, и так далее по цепочке.</p>
<p><a href="http://www.ajaxie.com/images/Erlang_11E23/erlangprocesscrash.png"><img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; margin: 0px 15px 5px 60px; border-right-width: 0px" height="205" alt="erlang-process-crash" src="http://www.ajaxie.com/images/Erlang_11E23/erlangprocesscrash_thumb.png" width="221" border="0"></a> </p>
<p>Связываются процессы с помощью функции link/2. Для удобства есть еще spawn_link/2, и если ее использовать в нашем примере вместо spawn, а также выходить из процессов не нормально, а с помощью erlang:error/1 (см. модифицированный исходник <a href="http://true.programmer.blog.googlepages.com/ping_test.2.erl.html">тут</a>), вывод будет немного другим:</p><pre class="console">4> ping_test:ping().
received ping
received pong
connection to ping timed out
=ERROR REPORT==== 2-Feb-2008::14:30:23 ===
Error in process <0.43.0> with exit
value: {ping_timeout,[{ping_test,pong,0}]}
** exception exit: pong
in function ping_test:pong/0
</pre>
<p> </p>
<p>Не рекомендуется использовать другие механизмы, такие как коды ошибок — идеология "let it crash". Скажем, если функция принимает на вход строку — это проблема вызывающего не передавать туда атомы, числа и прочую хрень. </p>
<p>Хотя эти механизмы в Erlang не кажутся на первый взгляд чем-то сверхпродвинутым, именно они помогают писать сложные отказоустойчивые серверные приложения, уделяя при этом минимум времени на написание кода, обрабатывающего ошибки.</p></span>lrrrhttp://www.blogger.com/profile/12742106367384624657noreply@blogger.com13tag:blogger.com,1999:blog-32757902.post-80605891085440684202008-01-30T21:29:00.001+03:002008-02-05T21:18:55.788+03:00Синтаксис Erlang в двух словах.<p>Чтобы писать веб-приложения на эрланге, надо его хотя бы немного знать, поэтому попробую в пару постов уложить основные понятия. <p>Тут лучше конечно почитать какой-нибудь более серьезный туториал, начиная с собственно <a href="http://www.erlang.org/download/getting_started-5.4.pdf">"Getting Started with Erlang"</a> (<a href="http://gzip.rsdn.ru/article/erlang/GettingStartedWithErlang.xml">русский перевод на рсдн</a>), или <a href="http://chuffyrodents.org/erlang.pdf">"Thinking In Erlang"</a>. Однако ж, поскольку 30-50 страниц осилить не у каждого поднимется мозг, я здесь изобразил небольшую шпаргалку (не претендующую на полноценное введение). <p>В принципе Эрланг весьма прост, по крайней мере для тех, кто хоть краем глаза видел какой-нибудь другой функциональный язык. <p>Для начала самые примитивные вещи:</p><span class="fullpost"> <ul> <li> <p>Прежде всего, Эрланг — это язык с динамической типизацией, никакой статической проверки типов тут нет.</p> <li>Литералы-числа в Erlang: 1, 4, 15, 25, 16#1F (в шестнадцатеричной системе), 2#01110110 (в двоичной).<pre class="console"><strong>> 1.</strong><br> 1<br><strong>> 1+2.</strong><br> 3<br><strong>> 1+1.5.<br></strong> 2.50000 </pre>
<li>Литералы-символы: на самом деле это не отдельный тип, а просто целое число — код символа : $a, $b, $\n $_<pre class="console"><strong>> $a.<br></strong> 97<br><strong>> $\n.<br></strong> 10 </pre>
<li>Списки задаются в квадратных скобках:<pre class="console"><strong>> [].</strong><br> []<br><strong>> X = [1,2].</strong><br> [1,2].<br><strong>> [3 | X].<br></strong> [3, 1, 2] </pre>
<li>Строки — "aba a", "ga a ga". <pre class="console"><strong>> [$a, $b, $c].</strong>
"abc"</pre>Строки — это на самом деле просто списки символов. Поэтому памяти они занимают немало — в общей сложности 8 байт на один символ строки (на 32-битной машине). <br>
<li>Битовые строки (binaries) — эффективное представление бинарных данных<pre class="console"><strong>> <<1, 3, "ba">>.</strong>
<<1,3,98,97>>
</pre>Их можно сопоставлять с шаблонами, и быстро передавать туда-сюда. Очень полезная фича Эрланга (правда мы ее использовать сильно не будем).
<li>Атомы <pre class="console">abds
more
hello
ok
undefined
</pre>Начинаются с маленькой буквы, и представляют собой что-то среднее между enum'ами и константными строками, пишутся без кавычек и удобны для разных меток и идентификаторов. Атомы очень похожи на строки, но их нельзя склеивать, вычислять длину и пр., длина их ограничена 256 байтами. Они существенно эффективнее строк в обращении.
<li>Еще любые значения еще можно объединять в пары, тройки, четверки, пятерки и так далее, с помощью фигурных скобок: <pre class="console">{14, 15}
{0, "ba", 3}
{$a, [1,2], {3,4}}
</pre></li></ul>
<p>Имена переменных всегда начинаются с большой буквы (несмотря на то что они везде называются "переменными", менять их нельзя).
<p>Имена функций и модулей обязательно начинаются с маленькой буквы. Сигнатура функции состоит из ее имени и количества параметров — то есть <em>format/2</em> и <em>format/3</em> это разные функции.
<p>Паттерн матчинг (сопоставление с шаблоном) в Erlang выглядит так: <pre class="erlang"><span class="Keyword">case</span> A <span class="Keyword">of</span>
<span class="Normal">Pattern1</span> <span class="Operator">-></span> <span class="Special">...</span>;
<span class="Normal">Pattern2</span> <span class="Operator">-></span> <span class="Special">...</span>;
<span class="Normal">Pattern3</span> <span class="Operator">-></span> <span class="Special">...</span>;
<span class="Keyword">end</span>
</pre>
<p>В паттернах можно использовать значок _ который матчит все что угодно (wildcard). В жизни используется как-то так:<pre class="erlang"><span class="Keyword">case</span> Foo <span class="Keyword">of</span>
{<span class="String">"HELLO"</span>, Name} <span class="Operator">-></span> send_response(<span class="String">"Hello, "</span> <span class="Operator">++</span> Name);
<span class="String">"BYE"</span> <span class="Operator">-></span> send_response(<span class="String">"Bye")</span>;
<span class="Special">_</span> <span class="Operator">-></span> send_response(<span class="String">"Unknown command")</span>
<span class="Keyword">end</span>
</pre>
<p>Еще паттерны можно использовать прямо в списке параметров функции: <pre class="erlang">foo({<span class="Special">_</span>, B}) <span class="Operator">-></span>
<span class="Special">...</span>;
foo(X) <span class="Operator">-></span>
<span class="Special">...</span>
</pre>
<p>что эквивалентно</p><pre class="erlang">foo(Y) <span class="Operator">-></span>
<span class="Keyword">case</span> Y <span class="Keyword">of</span>
{<span class="Special">_</span>, B} <span class="Operator">-></span> <span class="Special">...</span>
X <span class="Operator">-></span> <span class="Special">...</span>
<span class="Keyword">end</span><span class="Special">.</span>
</pre>
<p><br>Плюс, значения можно матчить с помощью знака "равно":</p><pre class="erlang">X <span class="Operator">=</span> {<span class="Number">1</span>, <span class="Number">3</span>},
{A, B} <span class="Operator">=</span> X.
</pre>
<p>теперь A = 1, а B = 3
<p>Причем, если переменная <em>слева </em>уже определена, в паттерне используется ее значение: <pre class="console"> > B = 4.</pre>
<p>Получаем run-time ошибку badmatch, потому что B у нас уже равно трем.</p>
<p>С операторами все почти как обычно:</p>
<ul>
<li>арифметические, +-/*%
<li>сравнения =/ , ==, =>, =<
<li>склеивание списков ++
<li>декомпозиция списков (оператор <a href="http://en.wikipedia.org/wiki/Cons">cons</a>) |
<li>битовые <strong>band</strong>, <strong>bor</strong>, <strong>bxor</strong>, <strong>bnot</strong> </li></ul>
<p>Вот, собственно, практически все. Раздражают в Эрланге поначалу только немного странные правила расстановки точек, запятых и точек с запятой. В двух словах — точка ставится в конце определения функции, запятая — между выражениями в определении функции, а точка с запятой разделяет выражения в <strong>case .. of</strong> и <strong>if</strong>. </p>
<p> </p>
<hr>
<p>В качестве примера — функция, получающая md5 хэш строки. В стандартной библиотеке уже есть функция md5(), которая получает хэш в виде битовой строки. </p><pre class="console"><strong>> H = erlang:md5("boooo").</strong><br><<174,62,131,226,250,179,167,216,104,61,142,239,171,209,231,77>> </pre>
<p>Нам же понадобится хэш в виде обычной строки, в шестнадцатиричном представлении, поскольку он используется в процедуре аутентификации на last.fm
<p>Для начала можно преобразовать битовую строку в список байт с помощью стандартной функции: <pre class="console"><strong>> binary_to_list(H).</strong><br>[174,62,131,226,250,179,167,216,104,61,142,239,171,209,231,77] </pre>
<p>Теперь функция, которая преобразует 4 бита в один hex символ:</p><pre class="erlang">hex(V) <span class="Operator">-></span>
<span class="Keyword">if</span>
V <span class="Operator"><</span> <span class="Normal">10</span> <span class="Operator">-></span>
<span class="Number">$0</span> <span class="Operator">+</span> V;
<span class="Statement">true</span> <span class="Operator">-></span>
<span class="Number">$a</span> <span class="Operator">+</span> (V <span class="Operator">-</span> <span class="Normal">10</span>)
<span class="Keyword">end</span><span class="Special">.</span>
</pre>
<p>Да, <strong>if</strong> в erlang — лишь упрощенный вариант <strong>case</strong> .. <strong>of, где в</strong>место паттернов — булевые выражения. Так что кейс "<strong>true</strong> ->" тут играет роль else </p>
<p>Теперь один байт можно преобразовать в hex так:<br></p><pre class="console"><p><strong>> E = 31.</strong><br><strong>> [hex(E bsr 4), hex(E band 16#F)].<br></strong>"1f" </p></pre>
<p>Ну и с помощью функции lists:<strong>foldl </strong>применить это ко всей исходной строке: <pre class="erlang"><span class="Normal">binary_to_hex</span>(Bin) <span class="Operator">-></span>
<span class="Function">lists</span><span class="Special">:</span><span class="Function">foldl</span>(<span class="Statement">fun</span> (E, Acc) <span class="Operator">-></span>
[hex(E <span class="Operator">bsr</span> <span class="Number">4</span>) | [hex(E <span class="Operator">band</span> <span class="Normal">16</span>#F) | Acc]] <span class="Keyword">end</span>,
[],
<span class="Function">lists</span><span class="Special">:</span><span class="Function">reverse</span>(<span class="Function">binary_to_list</span>(Bin)))<span class="Special">.</span>
<span class="Comment">% returns hex representation of md5 in reverse byte order</span>
<span class="Normal">md5_hex</span>(Bin) <span class="Operator">-></span>
<span class="Normal">binary_to_hex</span>(<span class="Function">erlang</span><span class="Special">:</span><span class="Function">md</span><span class="Number">5</span>(Bin))<span class="Special">.</span></pre>
<p>Тут </p>
<ul>
<li><strong>fun</strong> (E, Acc) -> ... <strong>end<br></strong> это определение лямбда-функции
<li>lists:foldl() это известный функциональным программистам <a href="http://ru.wikipedia.org/wiki/Свёртка_списка">foldl</a>.
<li>lists:<strong>reverse</strong>() разворачивает список задом наперед
<li>Конструкция вида [A | B] приклеивает в начало списка B элемент A (см. <a href="http://en.wikipedia.org/wiki/Cons">cons</a>). </li></ul>
<p>Итого получаем</p><pre class="console"><p><strong>>md5_hex("booo").<br></strong>"1c052f260d1b34423c32e7c7b29026b9"</p></pre>
<p style="border-left: 1px dotted;border-right: 1px dotted;border-top: 1px dotted;border-bottom: 1px dotted;"><a href="http://true.programmer.blog.googlepages.com/utils.erl.html"> Весь исходник (utils.erl) </a> </p>
<em>Про ключевую фичу Erlang — поддержку распределенных приложений поговорим в следующей серии.</em></span>lrrrhttp://www.blogger.com/profile/12742106367384624657noreply@blogger.com25tag:blogger.com,1999:blog-32757902.post-34368704738106783952008-01-30T20:04:00.001+03:002008-01-30T20:06:20.283+03:00Crash Course: веб приложения на Erlang [Дисклеймер]<p><a href="http://ajaxie.com/images/CrashCourseErlang_11A4B/erlang.gif"><img style="margin: 0px 15px 5px 0px" height="96" alt="erlang" src="http://ajaxie.com/images/CrashCourseErlang_11A4B/erlang_thumb.gif" width="114" align="left"></a> Почему-то зима выдалась крайне скудной на интересные новости.<br>Однако это не так уж плохо, можно нормально, не отвлекаясь на чтение RSS заняться непосредственно работой, да и появляется время поковырять разнообразные перспективные технологии, в частности — <a href="http://www.erlang.org">Erlang</a>, неспроста я ему так уделял внимание последнее время. <p>В общем, по мотивам своих экзерсисов в erlang, я решил написать небольшой туториал, такой crash course про erlang, причем как средство программирования именно веб-приложений. В качестве примера и сверхзадачи я выбрал веб-клиент (прокси) для социального интернет радио <a href="http://last.fm">last.fm</a>. <p>Плюс к этому, меня <a href="http://softwaremaniacs.org/blog/2007/09/26/couchdb/">тут</a> даже рекламировали как пишущего про эрланг — будем оправдывать ;) <p><em>"Прокси для ласт.фм", мягко говоря, не очень насущная проблема, но, во-первых, кое-где его действительно блокируют, да и удобно — можно слушать радио в любимом плеере, не используя официальный клиент (раньше такая возможность была, сейчас, кажется, ее убрали). </em> <p><em>В конце концов можно слушать ласт.фм без установки клиента, например, на КПК/мобильнике с вайфаем.</em></p>lrrrhttp://www.blogger.com/profile/12742106367384624657noreply@blogger.com5tag:blogger.com,1999:blog-32757902.post-669379820761013822007-12-14T14:04:00.001+03:002007-12-15T16:13:20.127+03:00Erlang @ Amazon<p></p> <p>А между тем замечательный язык erlang действительно напрашивается на то чтоб стать next big thing в веб-приложениях. Последнее время все больше и больше интересных новостей из этой области — особенно тут отличился <a href="http://www.amazon.com/AWS-home-page-Money/b/ref=sc_iw_l_0_3435361_2?ie=UTF8&node=3435361&no=3435361&me=A36L942TSJ2AJA">Amazon</a>. <p>Однако ж обо всем по порядку. <p>Последнее время Amazon становится одним из основных ньюсмейкеров со своими весьма инновационными сервисами по хостингу данных и приложений. <p>Первой ласточкой был <a href="http://www.amazon.com/b/ref=sc_fe_l_2?ie=UTF8&node=201590011&no=3435361&me=A36L942TSJ2AJA">EC2</a> — нечто, крайне напоминающее обычный VPS хостинг — амазон предоставляет вам в пользование виртуальные машины с операционной системой на выбор, однако деньги берет не помесячно, а за машино-часы и переданные гигабайты (от $0.10 до $0.80 за машино-час, плюс $0.10-$0.20 за переданный гигабайт). <p>При этом машины легко включать-выключать и добавлять новые, для этого есть отдельный API. Скорость передачи данных между ними в сети амазона <a href="http://info.rightscale.com/2007/11/29/network-performance-in-ec2-and-s3">вполне на уровне</a>. <p>Таким образом за приемлемые деньги можно получить небольшой (или большой) кластер из виртуальных машин. <p>Народ сразу оживился — действительно, EC2 и распределенный erlang будто созданы друг для друга. <a href="http://wagerlabs.com/archives/121.html">Можно запускать</a> сколько нужно нодов на нужном количестве инстансов EC2, при этом не заморачиваясь никакими оргвопросами связанными с покупкой и администрированием настоящих серверов. <p>Второе — это <a href="http://www.amazon.com/S3-AWS-home-page-Money/b/ref=sc_fe_l_2?ie=UTF8&node=16427261&no=3435361&me=A36L942TSJ2AJA">S3</a>, сервис по хранению данных. Деньги амазон берет за количество запросов + гигабайты в месяц, без всяких фиксированных тарифных планов. <p>И теперь амазон объявляет о запуске еще одного сервиса под названием <a href="http://www.amazon.com/b/ref=sc_fe_l_2?ie=UTF8&node=342335011&no=3435361&me=A36L942TSJ2AJA">SimpleDb</a> — и все встает на свои места. <p>Это база данных, однако больше всего она похожа на большой excel-евский spreadsheet: </p> <ul> <li>данные организуются в таблицы (которые называются доменами), </li> <li>никаких сложных запросов, но работает, говорят крайне быстро -- чуть ли не реалтайм;</li> <li>в одной ячейке можно хранить несколько значений (как список или кортеж)</li> <li>никаких типов у хранимых данных нет</li> <li>таблицы распределены по многим серверам </li></ul> <p>Если кто читал про ерланговскую родную базу данных <a href="http://www.erlang.org/doc/apps/mnesia/index.html">mnesia</a>, сразу увидит много знакомых фраз. Точнее, практически все эти фичи есть и у mnesia. <p>Вкупе с распределенным подходом в EC2 это начинает казаться не случайным совпадением — похоже, в амазоне появилась ячейка любителей ерланга. <p>И действительно, в блоге амазоновского разработчика находим <a href="http://www.satine.org/archives/2007/12/13/amazon-simpledb/">подтверждение</a>: SimpleDb построена на erlang! <p>Если SimpleDb будет популярна — а предпосылки для этого есть (это ж Amazon) — это будет самый убийственный пример применения erlang в боевых условиях. <p>Да и просто факт, что уже доступна отличная и недорогая платформа для хостинга эрланговских приложений — уже очень хорошая новость.</p>lrrrhttp://www.blogger.com/profile/12742106367384624657noreply@blogger.com14tag:blogger.com,1999:blog-32757902.post-9679391958718336432007-11-27T21:13:00.001+03:002007-11-27T21:14:38.213+03:00Erlang Job<p>Для тех, кто не читает форумы рсдн (что, конечно, идеологически правильно): cовершенно неожиданно оказалось что Joel Reymont (<a href="http://brainslugs.blogspot.com/2007/02/erlang-success-story.html">чувак с покером на эрланге</a>) родился в Санкт-Петербурге и отлично говорит по-русски. И вообще треть жизни прожил тут.</p> <p>Оказалось это в связи с тем, что Джоель сейчас <a href="http://rsdn.ru/forum/message/2742286.flat.aspx">ищет</a> программистов на Erlang и OCaml (пока part-time). На сайте у него <a href="http://wagerlabs.com/archives/133.html">говорится</a> про разработку бэкенда для того самого OpenPoker, но из <a href="http://rsdn.ru/forum/message/2742286.flat.aspx">треда</a> на рсдне видно что планы у него намного глобальнее.</p> <p>Так как это уже <a href="http://www.sql.ru/forum/actualthread.aspx?bid=9&tid=421905">не первое</a> предложение работы на erlang на русском языке за последнее время, уже очень хочется это назвать тенденцией.</p>lrrrhttp://www.blogger.com/profile/12742106367384624657noreply@blogger.com3tag:blogger.com,1999:blog-32757902.post-65062354060436598232007-11-08T11:08:00.001+03:002008-02-11T21:57:19.280+03:00Угадайка<p>Как думаете, какой язык поддерживает сразу</p> <ul> <li>First-class функции, лямбды и замыкания;</li> <li>параметризованные типы;</li> <li>хвостовые вызовы;</li> <li>array comprehensions;</li> <li>ООП с классами и интерфейсами;</li> <li>ООП на основе прототипов;</li> <li>мультиметоды;</li> <li>coroutines (оператор yield);</li> <li>структурные и номинальные подтипы;</li> <li>перегрузку операторов;</li> <li>Nullable/Non nullable аттрибуты для всех типов.</li></ul> <p>Ну и по мелочи: for-each, array slicing а-ля питон, регулярные выражения, открытые пространства имен и пр.</p> <span class="fullpost"> <p>Однако ж это все ожидается в чудесном новом <strike>Javascript</strike> ECMAScript 4!</p> <p>Еще одна из самых интересных возможностей в четвертой версии — <em>опциональная</em> статическая проверка типов. Это должно упростить написание сложных систем (засчет строго описанных интерфейсов), и помочь [jit] компиляторам иногда генерировать более эффективный код. Опциональные статические типы, похоже, становятся модными: в Python 3000 тоже не так давно добавили что-то похожее.</p> <p>Четвертая версия пока получается довольно пестрой — появилась куча новых механизмов и языковых конструкций (см. выше), а совместимость с предыдущей версией надо, по возможности, сохранить — поэтому синтаксис местами получился довольно странный: скажем, [int] это массив целых чисел, а [int, string] — это уже кортеж из целого и строки.</p> <p>Еще из забавных вещей — явная поддержка структурных типов. В частности, с помощью специального оператора <strong>like</strong> можно задать переменной структурный тип (то есть ей можно присвоить только объект, обладающий набором заданных свойств):</p> <p>> <strong>var</strong> foo : <strong>like</strong> {x : int, y : int};</p> <p>А переменная, объявленная с ключевым словом <strong>wrap </strong>автоматически дополняет хранимый в ней объект нужными свойствами:</p> <p><strong>var </strong>bar :<strong> wrap</strong> foo { x : int, y : int} = {x : 10, y : 20}.</p> <p>Может и не революционная фича, конечно, но выглядит крайне интересно.</p> <p>В ECMAScript 4 обещают также обязательную оптимизацию хвостовых вызовов. В Python 3000 их <a href="http://www.artima.com/weblogs/viewpost.jsp?thread=211430">точно не будет</a>, с руби ситуация туманна —что делает ES4 лучшим выбором в качестве платформы для компиляторов с функциональных языков. В общем-то уже сейчас есть компиляторы, как минимум, OCaml, SML и Haskell, генерирующие код на ECMASCript 3.</p> <p>Собственно мощь и текущей-то версии js во многом недооценена. Кстати, только я не знал, что <strike>автор</strike> один из авторов первой версии Javascript — <a href="http://en.wikipedia.org/wiki/Guy_L._Steele,_Jr.">Гай Стил мл.</a>, а в качестве основных источников вдохновения при разработке Javascript 3 авторы называют языки Scheme и Self?</p> <p>Новый Javascript явно претендует на что-то большее. Если он действительно будет "принят на вооружение" — определенно можно ожидать появления изрядного количества серверных приложений и фреймворков на js. Во всяком случае, язык получился явно не слабее питона и руби — хотя, конечно, вряд ли средства интеграции с кодом на C и C++ будут тут столь же развиты, ниша у языка все-таки другая.</p> <p>Ссылки:</p> <ul> <li><a href="http://www.ecmascript.org/es4/spec/overview.pdf">Proposed ECMAScript 4th Edition – Language Overview</a> [PDF]</li> <li>Официальный сайт <a href="http://www.ecmascript.org">www.ecmascript.org</a></li> <li><a href="http://www.ecmascript.org/download.php">Прототип интерпретатора</a> (написан он, кстати, на SML)</li></ul> </span>lrrrhttp://www.blogger.com/profile/12742106367384624657noreply@blogger.com7tag:blogger.com,1999:blog-32757902.post-86446041157350184812007-10-25T09:58:00.000+04:002007-10-25T10:29:32.301+04:00Пятиминутка ненависти к C++<p>..на этот раз не моя, однако почитать другим пострадавшим будет довольно забавно. Автор — <a href="http://yosefk.livejournal.com/">yousefk</a>, видимо, годами записывал в книжечку все подлянки, которые ему устраивал C++, и в результате у него получился вот такой <a href="http://yosefk.com/c++fqa/">весьма объемный документ</a>. </p>
<p>Называется это C++ Frequently Questioned Answers, и проезжается он практически по всем сколько-нибудь заметным фичам C++.</p>
<p>За основу взят широко известный <a href="http://www.parashift.com/c++-faq-lite/">C++ FAQ Lite</a>, дополненный "альтернативными" ответами в среднеиздевательском тоне — то есть автор, к счастью, не совсем сваливается в непрерывное брюзжание (как я иногда), что сделало бы такой огромный труд невыносимо скучным.</p>
<p>Причем критика там действительно весьма обоснованная и грамотная, что встретишь не так уж часто. Правда, местами получается таки чересчур эмоционально, но, наверное, только сам автор знает, сколько горя и несчастья причинил ему злой гений Страуструпа за эти годы.</p>lrrrhttp://www.blogger.com/profile/12742106367384624657noreply@blogger.com8tag:blogger.com,1999:blog-32757902.post-59441122329434760862007-10-08T21:22:00.001+04:002007-10-09T08:54:41.364+04:00Эзотерические языки - самый полный список<p>..<a href="http://esolangs.org/wiki/Language_list">найден</a> на вики-сайте канала #esolangs в irc-сети freenode.</p> <p>За ссылку спасибо жж сообществу <a href="http://community.livejournal.com/ru_brainfucker/profile">ru_brainfucker</a>.</p> <p>Языков там какое-то дикое количество, а особенно выдающимся создателем странных языков оказался некто <a href="http://www.dangermouse.net/">Дэвид Морган-Мар</a>, очевидно, тру программист. В числе его творений:</p> <ul> <li>язык <a href="http://www.dangermouse.net/esoteric/petrovich.html">Petrovich</a> (назван в честь И.П. Павлова), основанный на концепции наград и наказаний и выработки у программы нужных "условных рефлексов" :</li></ul> <div align="center"> <div align="left"> <p align="left"><pre>Petrovich> do something
11:15:23 11 June 2005
Petrovich> reward
Petrovich></pre>
<p></p></div></div>
<p></p>
<ul>
<li>язык <a href="http://www.dangermouse.net/esoteric/haifu.html">Haifu</a>, где программы выглядят как хокку
<li>язык <a href="http://www.dangermouse.net/esoteric/piet.html">Piet</a>, исходники выглядят как абстракционистские произведения живописи:</li></ul>
<p align="center"><a href="http://ajaxie.com/images/363d14be414c_12BFF/fibbig2.gif" atomicselection="true"><img height="121" src="http://ajaxie.com/images/363d14be414c_12BFF/fibbig_thumb.gif" width="110"></a> </p>
<p>Это собственно программа на Piet, печатающая первые сто чисел Фибоначчи.</p>
<p>Про эзотерические языки, кстати, была отличная <a href="http://rsdn.ru/article/philosophy/languages.xml">статья</a> на рсдн (если кто не видел), многие интересные языки из списка там тоже упоминаются.</p>lrrrhttp://www.blogger.com/profile/12742106367384624657noreply@blogger.com3tag:blogger.com,1999:blog-32757902.post-90942752745071863242007-09-24T00:16:00.000+04:002007-09-24T01:10:09.528+04:00Ссылки: Erlang for .NET, Python 3000 и все все все<p>Вернувшись из отпуска, продолжаю разгребать залежи непрочитанных RSS.
Разобраться со всем подробно некогда, поэтому получился небольшой дайджест:</p>
<ul>
<li><p>Некий товарищ <a href="http://erlangdotnet.net/">тут вот</a> собирается писать erlang для .NET, при этом подробно комментируя процесс в блоге. Не знаю надолго ли его хватит (блогу всего неделя), но начало интригующее. Например <a href="http://erlangdotnet.net/2007/09/inside-beam-erlang-virtual-machine.html">пост</a> про внутренности виртуальной машины эрланга — BEAM. У эрланга вообще всплеск популярности, вон даже у O'Reilly в <a href="http://www.onlamp.com/">ONLamp</a> появилось небольшое <a href="http://www.onlamp.com/pub/a/onlamp/2007/09/13/introduction-to-erlang.html">введение в Erlang</a>. И еще вот неплохое <a href="http://www.builderau.com.au/program/soa/Interview-The-importance-of-being-Erlang/0,339024614,339282123,00.htm">интервью</a> про практическое применение Erlang некими австралийцами.</p></li>
<li><p>Гвидо ван Россум и Брюс Эккель в своих блогах интересно спорят о Python 3.0, многопоточности в питоне и возможности/невозможности убрать из питона Global Interpreter Lock, вот ссылки на последние посты <a href="http://www.artima.com/weblogs/viewpost.jsp?thread=214480">про питон 3.0</a> и <a href="http://www.artima.com/weblogs/viewpost.jsp?thread=214627">про GIL</a> (на первые посты ссылки давать бессмысленно, поскольку они там в форме "мой ответ на этот ответ Гвидо на мой пост...")</p></li>
<li><p>Двигаясь в сторону теоретических основ — отличный <a href="http://debasishg.blogspot.com/2007/09/got-closures-have-oo.html">пост</a> про связь между замыканиями (в смысле closures) и ООП, с иллюстрациями на Scheme.</p></li>
<li><p>Плюс, на youtube добрые люди начали делать <a href="http://www.youtube.com/user/TheCatsters">видеолекции</a> по всяким интересным темам из области теории категорий. В частности, серия лекций <a href="http://www.youtube.com/view_play_list?p=0E91279846EC843E">про монады</a> и <a href="http://www.youtube.com/view_play_list?p=54B49729E5102248">про сопряженные функторы</a>.</p></li>
<li><p>Ну и в заключение опять немножко суровых практических вещей: интересная библиотека для генерации парсеров бинарных протоколов, "binpac: A yacc for Writing Application Protocol Parsers": <a href="http://www.bro-ids.org/wiki/index.php/BinPAC_Userguide">Юзер гайд</a>, <a href="http://www.icsi.berkeley.edu/pubs/networking/binpacIMC06.pdf">whitepaper</a>[PDF].</p></li>
</ul>lrrrhttp://www.blogger.com/profile/12742106367384624657noreply@blogger.com0tag:blogger.com,1999:blog-32757902.post-14390670951715179122007-09-08T00:16:00.001+04:002007-10-09T08:55:49.269+04:00Seaside: веб-фреймворк на основе continuations<p><strong>[Довольно длинное введение]</strong></p> <p>Веб-приложения — это та область, где выбор инструмента разработки ограничен меньше всего: наплевать, сколько мегабайт библиотек тянуть за собой, не очень-то нужна даже кроссплатформенность — приложение работать будет на ограниченном количестве машин и под присмотром специально обученных админов. Поэтому новые интересные технологии в веб-программировании появляются в большом количестве. Ну и пхп всех порядком достал ;)</p> <p>Написание сложных (и не очень) веб-приложений обычно наталкивается на кучу проблем, и основная — это то, что протокол HTTP не подразумевает никакого <em>состояния — </em>и поэтому это состояние приходится за собой таскать в виде cookies, скрытых полей в формах и букета параметров методов GET/POST. Плюс к этому, линейные переходы между страницами — по сути, аналог оператора goto — приводят к тому что дизайн многих веб приложений представляет из себя мешанину из процедурного и как-бы-объектно-ориентированного кода, сумбурных обращений к базе данных, разбавленных HTML разметкой. </p> <span class="fullpost"> <p>Проблемы эти стараются решить современные фреймворки для веб-разработки, прежде всего <a href="http://www.djangoproject.com/">Django</a>, <a href="http://www.cakephp.org/">CakePHP</a> и <a href="http://www.rubyonrails.org/">Ruby on Rails</a>, в которых авторы постарались максимально отделить представление от логики, упростить работу с базой данных засчет всяких <a href="http://www.rubyonrails.org/">ORM</a> подсистем и вообще структурировать приложение (в той или иной степени) заставляя его следовать классическому, но подзабытому в 90-е паттерну Model-View-Controller. В Ruby on Rails, скажем, под моделью понимаются данные, хранящиеся в БД, view — это система шаблонов, на основе которых генерируются страницы и контроллер — это собственно бизнес-логика.</p> <p>Однако же проблема таскать за собой "состояние" сессии остается, хотя и для ее решения фреймворки предлагают много всяких вспомогательных средств. </p> <p><strong>[Па-пам]</strong></p> <p><a href="http://www.ajaxie.com/images/Seaside_13741/ByteCover2.jpg" atomicselection="true"><img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="240" src="http://www.ajaxie.com/images/Seaside_13741/ByteCover_thumb.jpg" width="173" align="left" border="0"></a> Старики помнят, что термин "объектно-ориентированный" был изобретен для того чтобы назвать так язык Smalltalk. В дискуссиях о том, насколько тот или иной язык ОО обычно гуру ссылаются именно на него, как на эталон тру ОО языка. </p> <p>Более того, паттерн MVC у тех же стариков ассоциируется прежде всего с GUI библиотеками Smalltalk, именно там этот паттерн родился и получил широкое применение (потом эта вся идеология перекочевала в ОС NextStep, а из нее в Mac OS(X), если кто не в курсе).</p> <p>Возвращаясь к веб-разработке, многие наверное читали эссе Пола Грэма <a href="http://www.paulgraham.com/avg.html">Beating the Averages</a>, как Пол с товарищами написали на лиспе систему для создания веб-магазинов и потом продали ее за много миллионов баксов Yahoo!. Там они, кроме всего прочего, использовали continuations как механизм передачи управления между страницами. Continuation'ы хранились на сервере в словаре, а ссылки на страницах содержали как параметр id того continuation, который надо выполнить для генерации страницы.</p> <p>Если сложить вместе концепцию continuations, MVC в качестве основного паттерна для архитектуры всего приложения и smalltalk в качестве языка разработки — получим Seaside, фреймворк для разработки сложных веб-приложений, не думая о большинстве вышеописанных проблем.</p> <p><strong>[Немножко подробнее про continuations в вебе]</strong></p> <p>С логикой и control flow в вебе проблем несколько — во первых, вышеупомянутое состояние сессии: таскать его между страницами через параметры POST/GET довольно неудобно да и иногда просто нереально, а наличие у юзера кнопок "назад" и "открыть в новом окне" создает проблемы, если мы храним состояние в куках или сразу сохраняем в базе данных введенные в формы данные.</p> <p>Но отличное решение этой проблемы уже давно существует и реализовано во многих динамических языках, начиная с лиспа. Называется continuation — <a href="http://brainslugs.blogspot.com/2006/10/callcc.html">тут</a> я описывал подробнее, что это, но если в двух словах — мы можем поставить выполнение программы в каком-то месте "на паузу", и потом с объектом "поставленная на паузу программа" обращаться как с любым другим — продолжить выполнение с того места (сколько угодно раз, заново), сохранить, передать, удалить за ненадобностью.</p> <p>Например, представим себе такой пример: пользователь заполняет форму, нажимает ОК, но одно поле заполнено неверно, и мы хотим показать ему страничку с предупреждением и кнопкой ОК, и вернуться обратно к той (уже частично заполненной им) форме.</p> <p>В стандартном случае мы передаем скрипту, выводящему страницу с предупреждением значения заполненных полей, а он потом передает их обратно. Как-то так:</p><pre>/show_form.php
-> validate_form.php?userName=John&phone=02
-> show_warning.php?userName=John&phone=02
-> show_form.php?userName=John&phone=02
</pre>
<p>В фреймворках, основанных на continuations метод showForm() просто вызывает validateForm(), которая вызывает showWarning(), и на время, когда юзеру надо показать отрендеренную страницу все состояние сохраняется в continuation. Потом, когда юзер жмет OK — все возобновляется с того места где приложение остановилось.</p>
<p>По сравнению с традиционным подходом тут целых несколько преимуществ: во-первых, мы не заботимся о том, как таскать состояние через страницы; во-вторых, структура программы становится понятнее, это своего рода переход от GOTO к процедурам; в-третьих, поскольку состояние теперь не наша забота, куски кода становятся более модульными, функции showWarning() уже не надо знать ничего ни о каких формах.</p>
<p>Последнее особенно хорошо иллюстрируется <a href="http://seaside.st/about/examples/multicounter?12&_k=AVpDXZlm&_n&_s=EHvWJpEebCcEIOkC">примером</a> из дистрибутива Seaside: пять компонентов (счетчиков) на одной странице, состояние обо всех некоторым образом передается между страницами, но каждый счетчик ничего не знает о других — вся логика и представление сосредоточено внутри класса, отвечающего за компонент, а не размазана по скрипту сгенерить_страницу_с_пятью_счетчиками.php. Это именно благодаря тому, что состояние сохраняется и передается автоматически между вызовами. И кнопка back в браузере отлично работает без всяких усилий со стороны разработчика.</p>
<p><strong>[Seaside]</strong></p>
<p>Собственно, про сам Seaside добавить можно теперь немного — используется в точности подход, описанный выше. </p>
<p>Немаловажный момент — Seaside принципиально не использует никакой системы шаблонов, подобно Ruby on Rails и Django — XHTML код генерится с помощью набора специальных классов, благодаря чему генерацию XHTML можно разносить по методам, применять к ним инструменты для рефакторинга Smalltalk-овского кода (а среда тут предоставляет их очень богатый набор). Конечно, дизайнерам править XHTML будет немного сложнее, но, по-хорошему, им и не надо: XHTML призван отвечать за "семантику" страницы, а для представления ее существует CSS.</p>
<p>Вообще среда разработки в Smalltalk (точнее <a href="http://www.squeak.org/">Squeak</a>, основная но не единственная реализация Smalltalk, в которой работает Seaside) заслуживает отдельного большого поста — настолько это инопланетное создание. Чего стоит только тот факт что там нету понятия исходных файлов — есть только один большой рантайм, все классы и методы правятся "на лету", не останавливая работы приложения. Система контроля версий тоже своя, и diff работающий не на уровне текста, а на уровне классов и методов. Поначалу больше всего расстраивает то, что в Squeak нельзя воспользоваться своим любимым редактором, но мало какой редактор предоставляет столько инструментов для рефакторинга и автоматической генерации кода, как System Browser в Squeak. </p>
<p><a href="http://www.ajaxie.com/images/Seaside_13741/squeak1.png" atomicselection="true"><img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="189" src="http://www.ajaxie.com/images/Seaside_13741/squeak.png" width="240" border="0"></a> </p>
<p>Кроме всего этого, к Squeak/Seaside прилагаются очень неплохие инструменты для отладки, тестирования и настройки производительности. В отладочном режиме вообще много приятностей — когда в приложении происходит какой-то эксепшен, можно нажать кнопку Debug и начать отлаживать с этого места в Squeak. Для десктопных средств разработки в этом ничего выдающегося нету, но для веб — это большой шаг вперед.</p>
<p>Или, скажем, моя любимая фича — можно на лету, исключительно в браузере править любые классы и методы для выбранного прямо со страницы компонента.</p>
<p>Лучше, конечно один раз увидеть: скринкаст <a href="http://onsmalltalk.com/programming/smalltalk/smalltalk-in-action/">здесь</a> — рефакторинг приложения (не веб-) в squeak, не останавливая его работы; и <a href="http://onsmalltalk.com/programming/smalltalk/screencast-how-to-build-a-blog-in-15-minutes-with-seaside/">тут</a> — создание блога за 15 минут в Seaside. Заметьте, как товарищ ловко фиксит там баг на лету, опять же без остановки приложения.</p>
<p><strong>[Кто-то же должен за это платить?]</strong></p>
<p>Естественно, все это оборачивается несколько более высокими аппаратными требованиями. Seaside изначально ставит стоимость времени программиста много выше стоимости железок. Squeak кушает изрядно памяти и процессорного времени (хотя по скорости выполнения, говорят, как минимум не медленнее питона и руби). По стабильности рантайма проблем нету, если кого-то беспокоит что это все может быть несколько "сыровато" — виртуальная машина squeak разрабатывается уже лет 10 как, причем довольно серьезными и профессиональными дядьками, начиная с того же Алана Кея.</p>
<p><strong>[Ну и..]</strong></p>
<p>В общем, крайне рекомендую поиграться, особенно тем кто занимается веб-разработкой профессионально. Получите, как минимум, массу удовольствия.</p>
<p><strong>[Ссылки. Много ссылок]</strong></p>
<ul>
<li>Блог "<a href="http://onsmalltalk.com">On Smalltalk</a>" много про squeak, smalltalk и seaside
<li>Блог "<a href="http://www.avibryant.com/">HREF Considered Harmful</a>" про про seaside и внутренности squeak
<li>Подробно о continuations в вебе Статья "<a href="http://www.iam.unibe.ch/~scg/Archive/Papers/Duca04eSeaside.pdf">Seaside - a Multiple Control Flow Web Application Framework</a>" [PDF]
<li>Сравнение <a href="http://onsmalltalk.com/programming/smalltalk/rails-vs-seaside/">Rails Vs Seaside</a> (+ в комментах интересная битва между любителями Rails и автором)
<li>Другое интересное <a href="http://blog.circleshare.com/?/archives/7-Rails-and-Seaside-Two-new,-great-web-frameworks.html">сравнение Rails и Seaside</a> от опытного программиста на java Дэвида Поллака. Судя по всему, Дэвида все-таки не устроило ни то, ни другое, поэтому сейчас он активно разрабатывает фреймворк на базе <a href="http://www.scala-lang.org">Scala</a>, это отдельная интересная тема :)
<li><a href="http://seaside.st">Сайт Seaside</a>
<li><a href="http://www.squeak.org">Сайт Squeak</a>
<li><a href="http://seasidehosting.st">Бесплатный хостинг</a> для некоммерческих Seaside приложений
<li>Туториалы к Seaside: <a href="http://www.shaffer-consulting.com/david/Seaside/">вот</a> и <a href="http://daitanmarks.sourceforge.net/or/squeak/squeak_tutorial.html">вот</a>, и еще несколько в гугле можно найти. К сожалению, кое-какие из них местами устарели.</li></ul><pre></pre></span>lrrrhttp://www.blogger.com/profile/12742106367384624657noreply@blogger.com10tag:blogger.com,1999:blog-32757902.post-59604849792252236282007-08-31T01:18:00.000+04:002007-08-31T01:29:11.704+04:00Блог: монстры геймдева<p>Группа широко известных в узких кругах отечественных разработчиков компьютерных игрушек (и не только) с недавних пор ведет коллективный блог по адресу <a href="http://blog.gamedeff.com">http://blog.gamedeff.com</a></p>
<p>Получается довольно интересно, даже для тех кто с игроделательной промышленностью не связан (вроде меня). Вообще, маловато нынче блогов посвященным всяким нетривиальным практическим программистским вещам, а этот — приятное исключение.</p>
<p>Всячески рекомендую, в общем.</p>lrrrhttp://www.blogger.com/profile/12742106367384624657noreply@blogger.com2tag:blogger.com,1999:blog-32757902.post-7763656113897383342007-08-29T11:38:00.001+04:002007-08-29T11:56:00.788+04:00Самый популярный функциональный язык<p>... чей рантайм установлен практически на каждом компьютере — это XSLT, язык для трансформации XML документов. </p> <p>Если кто не в курсе, в списке возможностей — абсолютное отсутствие побочных эффектов, то есть язык чисто функциональный, и поддержка функций высшего порядка. </p> <p>Все это в изобилии можно наблюдать в замечательной XSLT-библиотеке FXSL, разработанной Димитром Новачевым. Реализации большинства функциональных идиом, таких как композиция функций, операций со списками по мотивам хаскелевской стандартной библиотеки — map/filter/foldl/zipWith и т.п. Более того, в cvs-версии библиотеки можно найти даже <a href="http://fxsl.cvs.sourceforge.net/fxsl/fxsl-xslt2/Tests/TestFunc-lrParse.xsl?view=markup">реализацию небольшого LR-парсера</a> на чистом XSLT 2.0</p> <p>Конечно, выглядит не очень прозрачно, вот например использование foldl для вычисления произведения элементов списка:</p> <div style="border-right: #666 1px solid; padding-right: 8px; border-top: #666 1px solid; padding-left: 8px; padding-bottom: 8px; overflow: auto; border-left: #666 1px solid; padding-top: 8px; border-bottom: #666 1px solid; height: 280px"><pre><span style="color: #a65700"><</span><span style="font-weight: bold; color: #800000">xsl</span><span style="color: #800080">:</span><span style="font-weight: bold; color: #800000">stylesheet</span> <span style="color: #074726">version</span><span style="color: #808030">=</span><span style="color: #0000e6">"</span><span style="color: #008c00">2.0</span><span style="color: #0000e6">"</span>
<span style="color: #666616">xmlns</span><span style="color: #800080">:</span><span style="color: #074726">xsl</span><span style="color: #808030">=</span><span style="color: #0000e6">"</span><span style="color: #666616">http</span><span style="color: #800080">:</span><span style="font-weight: bold; color: #800000">//</span><span style="color: #5555dd">www.w3.org</span><span style="color: #40015a">/1999/XSL/Transform</span><span style="color: #0000e6">"</span>
<span style="color: #666616">xmlns</span><span style="color: #800080">:</span><span style="color: #074726">foldl-func</span><span style="color: #808030">=</span><span style="color: #0000e6">"</span><span style="color: #40015a">foldl-func</span><span style="color: #0000e6">"</span>
<span style="color: #666616">xmlns</span><span style="color: #800080">:</span><span style="color: #074726">f</span><span style="color: #808030">=</span><span style="color: #0000e6">"</span><span style="color: #666616">http</span><span style="color: #800080">:</span><span style="font-weight: bold; color: #800000">//</span><span style="color: #5555dd">fxsl.sf.net</span><span style="color: #40015a">/</span><span style="color: #0000e6">"</span>
<span style="color: #074726">exclude-result-prefixes</span><span style="color: #808030">=</span><span style="color: #0000e6">"</span><span style="color: #0000e6">f foldl-func</span><span style="color: #0000e6">"</span>
<span style="color: #a65700">></span>
<span style="color: #a65700"><</span><span style="font-weight: bold; color: #800000">xsl</span><span style="color: #800080">:</span><span style="font-weight: bold; color: #800000">import</span> <span style="color: #074726">href</span><span style="color: #808030">=</span><span style="color: #0000e6">"</span><span style="color: #40015a">../f/func-foldl.xsl</span><span style="color: #0000e6">"</span><span style="color: #a65700">/></span>
<span style="color: #696969"><!--</span><span style="color: #696969"></span>
<span style="color: #696969"> This transformation must be applied to: </span>
<span style="color: #696969"> ../data/numList.xml </span>
<span style="color: #696969"> </span>
<span style="color: #696969"> Expected result: 3628800 or 3.6288E6 </span>
<span style="color: #696969">--></span>
<span style="color: #a65700"><</span><span style="color: #666616">foldl-func</span><span style="color: #800080">:</span><span style="color: #5f5035">foldl-func</span><span style="color: #a65700">/></span>
<span style="color: #a65700"><</span><span style="font-weight: bold; color: #800000">xsl</span><span style="color: #800080">:</span><span style="font-weight: bold; color: #800000">variable</span> <span style="color: #074726">name</span><span style="color: #808030">=</span><span style="color: #0000e6">"</span><span style="color: #0000e6">vFoldlFun</span><span style="color: #0000e6">"</span> <span style="color: #074726">select</span><span style="color: #808030">=</span><span style="color: #0000e6">"</span><span style="color: #400000">document</span><span style="color: #808030">(</span><span style="color: #800000">'</span><span style="color: #800000">'</span><span style="color: #808030">)</span><span style="font-weight: bold; color: #800000">/</span><span style="color: #0000e6">*</span><span style="font-weight: bold; color: #800000">/</span><span style="color: #666616">foldl-func</span><span style="color: #800080">:</span><span style="font-weight: bold; color: #800000">*</span><span style="color: #808030">[</span><span style="color: #008c00">1</span><span style="color: #808030">]</span><span style="color: #0000e6">"</span><span style="color: #a65700">/></span>
<span style="color: #a65700"><</span><span style="font-weight: bold; color: #800000">xsl</span><span style="color: #800080">:</span><span style="font-weight: bold; color: #800000">output</span> <span style="color: #074726">encoding</span><span style="color: #808030">=</span><span style="color: #0000e6">"</span><span style="color: #0000e6">UTF-8</span><span style="color: #0000e6">"</span> <span style="color: #074726">omit-xml-declaration</span><span style="color: #808030">=</span><span style="color: #0000e6">"</span><span style="color: #7d0045">yes</span><span style="color: #0000e6">"</span><span style="color: #a65700">/></span>
<span style="color: #a65700"><</span><span style="font-weight: bold; color: #800000">xsl</span><span style="color: #800080">:</span><span style="font-weight: bold; color: #800000">template</span> <span style="color: #074726">match</span><span style="color: #808030">=</span><span style="color: #0000e6">"</span><span style="font-weight: bold; color: #800000">/</span><span style="color: #0000e6">"</span><span style="color: #a65700">></span>
<span style="color: #a65700"><</span><span style="font-weight: bold; color: #800000">xsl</span><span style="color: #800080">:</span><span style="font-weight: bold; color: #800000">value-of</span> <span style="color: #074726">select</span><span style="color: #808030">=</span><span style="color: #0000e6">"</span><span style="color: #666616">f</span><span style="color: #800080">:</span><span style="color: #0000e6">foldl</span><span style="color: #808030">(</span><span style="color: #797997">$vFoldlFun</span><span style="color: #44aadd">,</span><span style="color: #0000e6"> </span><span style="color: #008c00">1</span><span style="color: #44aadd">,</span><span style="color: #0000e6"> </span><span style="color: #008c00">1</span><span style="color: #0000e6"> </span><span style="font-weight: bold; color: #800000">to</span><span style="color: #0000e6"> </span><span style="color: #008c00">10</span><span style="color: #0000e6"> </span><span style="color: #808030">)</span><span style="color: #0000e6">"</span><span style="color: #a65700">/></span>
<span style="color: #a65700"></</span><span style="font-weight: bold; color: #800000">xsl</span><span style="color: #800080">:</span><span style="font-weight: bold; color: #800000">template</span><span style="color: #a65700">></span>
<span style="color: #a65700"><</span><span style="font-weight: bold; color: #800000">xsl</span><span style="color: #800080">:</span><span style="font-weight: bold; color: #800000">template</span> <span style="color: #074726">match</span><span style="color: #808030">=</span><span style="color: #0000e6">"</span><span style="font-weight: bold; color: #800000">*</span><span style="color: #808030">[</span><span style="color: #400000">namespace-uri</span><span style="color: #808030">(</span><span style="color: #808030">)</span><span style="color: #0000e6"> = </span><span style="color: #800000">'</span><span style="color: #0000e6">foldl-func</span><span style="color: #800000">'</span><span style="color: #808030">]</span><span style="color: #0000e6">"</span>
<span style="color: #074726">mode</span><span style="color: #808030">=</span><span style="color: #0000e6">"</span><span style="color: #666616">f</span><span style="color: #800080">:</span><span style="color: #0000e6">FXSL</span><span style="color: #0000e6">"</span><span style="color: #a65700">></span>
<span style="color: #a65700"><</span><span style="font-weight: bold; color: #800000">xsl</span><span style="color: #800080">:</span><span style="font-weight: bold; color: #800000">param</span> <span style="color: #074726">name</span><span style="color: #808030">=</span><span style="color: #0000e6">"</span><span style="color: #0000e6">arg1</span><span style="color: #0000e6">"</span> <span style="color: #074726">select</span><span style="color: #808030">=</span><span style="color: #0000e6">"</span><span style="color: #008c00">0</span><span style="color: #0000e6">"</span><span style="color: #a65700">/></span>
<span style="color: #a65700"><</span><span style="font-weight: bold; color: #800000">xsl</span><span style="color: #800080">:</span><span style="font-weight: bold; color: #800000">param</span> <span style="color: #074726">name</span><span style="color: #808030">=</span><span style="color: #0000e6">"</span><span style="color: #0000e6">arg2</span><span style="color: #0000e6">"</span> <span style="color: #074726">select</span><span style="color: #808030">=</span><span style="color: #0000e6">"</span><span style="color: #008c00">0</span><span style="color: #0000e6">"</span><span style="color: #a65700">/></span>
<span style="color: #a65700"><</span><span style="font-weight: bold; color: #800000">xsl</span><span style="color: #800080">:</span><span style="font-weight: bold; color: #800000">value-of</span> <span style="color: #074726">select</span><span style="color: #808030">=</span><span style="color: #0000e6">"</span><span style="color: #797997">$arg1</span><span style="color: #0000e6"> * </span><span style="color: #797997">$arg2</span><span style="color: #0000e6">"</span><span style="color: #a65700">/></span>
<span style="color: #a65700"></</span><span style="font-weight: bold; color: #800000">xsl</span><span style="color: #800080">:</span><span style="font-weight: bold; color: #800000">template</span><span style="color: #a65700">></span>
<span style="color: #a65700"></</span><span style="font-weight: bold; color: #800000">xsl</span><span style="color: #800080">:</span><span style="font-weight: bold; color: #800000">stylesheet</span><span style="color: #a65700">></span>
<small>Created with colorer-take5 library. Type 'xslt2'</small>
</pre></div>
<p></p>
<p>В качестве примеров более серьезных программ на XSLT — <a href="http://andrewjwelch.com/code/xslt/sudoku/sudoku-solver.html">решалка</a> головоломки Sudoku и <a href="http://andrewjwelch.com/code/xslt/csv/csv-to-xml_v2.html">CSV2XML конвертер</a>,написанные товарищем по имени Andrew Welch, у которого есть еще очень интересный <a href="http://ajwelch.blogspot.com">блог</a> по XSLT.</p>
<p>Если захочется поиграться, берите <a href="http://saxon.sourceforge.net/">saxon</a> в качестве XSLT процессора — поддержка XSLT 2.0 в MSXML только планируется (а в Orcas ее <a href="http://blogs.msdn.com/xmlteam/archive/2007/01/29/xslt-2-0.aspx">точно еще не будет</a>)</p>
<p>Ссылки:</p>
<ul>
<li><a href="http://dnovatchev.spaces.live.com/blog/">Блог Димитра Новачева</a>
<li><a href="http://ajwelch.blogspot.com">Блог "Thoughts on XSLT"</a>
<li><a href="http://fxsl.sourceforge.net/">FXSL</a> на SourceForge.</li></ul>lrrrhttp://www.blogger.com/profile/12742106367384624657noreply@blogger.com6tag:blogger.com,1999:blog-32757902.post-63777881509837473652007-08-24T13:02:00.001+04:002007-08-31T12:54:52.085+04:00Код Adobe<p>Когда в 2001 году компания Adobe начала строить в Сан-Хосе третью башню своего головного офиса, было решено украсить здание каким-нибудь образцом крайне современного исскуства.</p> <p>Провели конкурс, и выиграл проект художника Бена Рубина: на последнем этаже здания с помощью мощных светодиодов (количеством >23000 шт) выводится четыре ярких световых пятна, поворачивающихся на разные углы каждые 7.2 секунды. Одновременно с этим вблизи здания на волне 1680 кГц можно услышать саундтрек, состоящий из не менее странного набора звуков. Все это еще реагирует на пролетающие самолеты (рядом аэропорт).</p> <p>Называется это "Семафор Сан-Хосе", на <a href="http://www.earstudio.com/sanjosesemaphore/">сайте</a> можно найти и видео того, как вся композиция выглядит:</p> <p><embed id="VideoPlayback" style="width: 400px; height: 326px" src="http://video.google.com/googleplayer.swf?docId=-3984938972895306527&hl=en" type="application/x-shockwave-flash" flashvars=""> </embed></p> <p>Плюс к этому, автор зашифровал в последовательности этих вращений и звуков некий набор осмысленных данных, и объявил в августе 2006 года вместе с Adobe конкурс на расшифровку этого сообщения.</p> <p>Уже через месяц код был расшифрован двумя местными учеными, однако по по правилам конкурса результаты были объявлены только через год — 14 августа 2007.</p> <p>Вот <a href="http://www.earstudio.com/sanjosesemaphore/decoding.pdf">тут</a> можно почитать довольно увлекательный отчет о том как они пытались сломать этот код, а <a href="http://www.earstudio.com/sanjosesemaphore/report.pdf">тут</a> — описание собственно алгоритма.</p> <p><small>Ничего сверхъестественного внутри не оказалось — каждому символу ASCII соответствовало определенное сочетание положений дисков / звуков, а данные состояли из заголовка и зашифрованного (вариантом <a href="http://en.wikipedia.org/wiki/Vigenère_cipher">шифра Вижинера</a>) текста. </small></p> <p><small></small> </p> <p style="font-size: 1px">27723148.0f886b0078628df55b2305efb1cb3729.1188550416.ad19e9ea28e0c0f82d80c4e264544d86</p>lrrrhttp://www.blogger.com/profile/12742106367384624657noreply@blogger.com0tag:blogger.com,1999:blog-32757902.post-69318411344018744052007-08-21T19:11:00.001+04:002007-08-21T19:13:09.059+04:00Типы: ссылки<p>Пожалуй, первая серия постов про типы на этом заканчивается. Продолжение будет. </p> <p>В этом посте я собрал немножко разных ссылок по теме, часть из них я уже приводил — пускай будут в одном месте:</p> <p>Вообще:</p> <ul> <li>Отличные <a href="http://www.dcs.gla.ac.uk/~simon/teaching/tpl/">слайды к лекциям</a> по курсу "Types and programming languages" университета Глазго (это там, где появился <a href="http://www.haskell.org/ghc/">GHC</a>).</li> <li>"<a href="http://www.cis.upenn.edu/~bcpierce/papers/tng-lics2003-slides.pdf">Types and Programming Languages The Next Generation</a>" — лекция Бенджамина Пирса о том что вообще в теории типов сейчас происходит.</li> <li>Лука Карделли тоже много разных интересных научно-популярных вещей написал, например <a href="http://lucacardelli.name/Papers/TypeSystems.pdf">вот</a>("Type Systems") и <a href="http://lucacardelli.name/Papers/OnUnderstanding.A4.pdf">вот</a>("On Understanding Types, Data Abstraction, and Polymorphism").</li></ul> <p>Про подтипы:</p> <ul> <li><a href="https://guinness.cs.stevens-tech.edu/~naumann/cs510/DomSubtypingRev.pdf">Лекция про subtyping с примерами из java</a> <li>Туториал по Scala: "<a href="http://www.scala-lang.org/docu/files/ScalaByExample.pdf">Scala By Example</a>". <li>Книжка "<a href="http://www.amazon.com/Foundations-Object-Oriented-Languages-Types-Semantics/dp/026202523X">Foundations of Object-Oriented Programming Languages: Types and Semantics</a>" by Kim B. Bruce — частично <a href="http://www.cs.pomona.edu/~kim/FOOLbook.html">доступна онлайн</a>. </li></ul> <p>Про наследование:</p> <ul> <li>"<a href="http://www.cs.cmu.edu/~wing/publications/LiskovWing94.pdf">A behavioral notion of subtyping</a>" — Liskov Substitution Principle; <li>"<a href="http://okmij.org/ftp/Computation/Subtyping/">Subtyping, Subclassing, and Trouble with OOP</a>" — Олег Киселев о проблемах в ООП, связанных с наследованием; <li>"<a href="http://www.cs.cmu.edu/~fp/courses/03-312/handouts/22-inheritance.pdf">Supplementary Notes on Inheritance and Subtyping</a>" — про проблему открытой рекурсии.</li></ul> <p>На русском языке, из интересного, рекомендую <a href="http://lktalks.blogspot.com/2007/08/blog-post_19.html">почитать</a> в блоге Льва Курца откуда типы вообще возникли — с "более математической" точки зрения.</p> <p>Еще есть <a href="http://www.softcraft.ru/paradigm/dp/dp07.shtml">глава про типы</a> в книжке И. Дехтяренко "Декларативное программирование" — сам я, правда, ее подробно еще не смотрел.</p>lrrrhttp://www.blogger.com/profile/12742106367384624657noreply@blogger.com3tag:blogger.com,1999:blog-32757902.post-14371978227316225982007-08-20T13:29:00.001+04:002007-08-20T17:07:24.925+04:00Типы: Top и Bottom<p></p> <p>Для полноты картины нужно упомянуть еще два специальных крайних случая — типы Top и Bottom. <p>Тип Top (записывается как <img style="display: inline; vertical-align: middle; border-top-style: none; border-right-style: none; border-left-style: none; border-bottom-style: none" src="http://www.ajaxie.com/top.png">) — это специальный тип, являющийся супертипом для всех остальных. Если быть ближе к математике — для любого t: t <: T. </p> <p><br>В Java и C#, например, ему соответствует тип Object (правда, он не является супертипом для простых unboxed типов вроде int). Вообще в большинстве ОО языков (кроме C++) такой тип присутствует. </p> <p>Другой полезный элемент системы типов — это тип Bottom <img style="display: inline; vertical-align: middle; border-top-style: none; border-right-style: none; border-left-style: none; border-bottom-style: none" src="http://www.ajaxie.com/bottom.png">, который является подтипом для любого типа. Как правило, нет ни одного значения этого типа — в противном случае, это значение допустимо было бы использовать и в контексте когда нужен тип функции (a → b), и, скажем, когда требуется тип сложной структуры данных. <p>Несмотря на это, тип bottom весьма полезен в некоторых случаях — он может обозначать тип функции, которая никогда не возвращает значений, например, входит в бесконечный цикл или кидать exception: <pre><b>function</b> div(a : float, b : float) : float =
<b>if</b> (a != 0)
a / b
<b>else</b>
error
</pre>
<p>Выражение error имеет тип bottom, технически оно выкидывает эксепшен. Благодаря этому выражение if в целом отлично проходит проверку типов<sup>1</sup> (имеет тип float).<br>Однако, введение в систему типов такого специального случая ее неслабо усложняет — кроме <del>Haskell</del> <a href="http://www.scala-lang.org/docu/files/api/scala/Nothing.html">Scala</a> такого типа нет, вроде бы, нигде из более-менее мейнстримных языков. </p>
<p><small><sup>1</sup> Тут имеется ввиду выражение if, а не statement (как в C++/C#/Java). В C++/C#/Java этому соответствует тернарный оператор ?:</small></p>lrrrhttp://www.blogger.com/profile/12742106367384624657noreply@blogger.com14