tag:blogger.com,1999:blog-21453655037757845802024-03-19T19:20:37.097+01:00Alex Ott's Russian blog about IT-related thingsThis blog dedicated to IT, Software development and information security. Main language - Russian.Alex Otthttp://www.blogger.com/profile/13001951608173211050noreply@blogger.comBlogger82125tag:blogger.com,1999:blog-2145365503775784580.post-9892168021437509942012-12-03T20:21:00.000+01:002012-12-07T08:19:10.408+01:00Переводы книжек на тему ФП...Я регулярно общаюсь с издательством ДМК-Пресс, которое в последнее время занимается изданием переводов книг по функциональному программированию и языкам ФП.
В данный момент они занимаются переводом "Scala for Impatient" и им нужны люди которые бы могли сделать техническую вычитку. Если кому интересно, то напишите Дмитрию Мовчану на dm at dmk-press.ru - я сам не знаю как это дело будет организовано...</br>
Они также заинтересованы в издании перевода Practical Common Lisp, который находится в подвешенном состоянии уже давно (надо доперевести 1.5 главы и пройтись по тексту, вычитывая). Издательство приобрело права на издание книги в России, и обещает напечатать книгу по себестоимости. Если кто может принять участие в этом проекте, напишите мне, я выдам .git-репозиторий с текстом в формате LaTeX (или залить это дело на github?). У меня честно говоря совсем нет свободного времени довести PCL до ума.
<br/></br>
Update: PCL <a href="https://github.com/pcl-ru/pcl-ru">залит на github</a>, кто хочет поучавствовать - присылайте свои login names, я добавлю к проекту. Координация и обсуждения происходят в <a href="https://groups.google.com/forum/?hl=ru&fromgroups#!forum/pcl-ru">списке рассылки</a>Alex Otthttp://www.blogger.com/profile/13001951608173211050noreply@blogger.com17tag:blogger.com,1999:blog-2145365503775784580.post-90388433914900534362012-09-25T16:24:00.000+01:002012-09-26T16:13:59.801+01:00Выступление про Clojure на ITSea 2012На прошлой неделе я рассказывал про Clojure на небольшой конференции ITSea (совмещенной с купанием в море и т.п. :-), и затем еще давал небольшой мастер-класс на тему практического использования Clojure. Слайды <a href="http://www.slideshare.net/alexott/clojure-lisp-for-the-modern-world">доступны на slideshare</a> (а вот записи выступления к сожалению не было):<br />
<iframe src="http://www.slideshare.net/alexott/slideshelf" width="490px" height="470px" frameborder="0" marginwidth="0" marginheight="0" scrolling="no" style="border:none;" allowfullscreen></iframe>
Данный постинг является дополнением к этим слайдам, и содержит ссылки на разные ресурсы, упоминавшиеся в рассказе:<br />
<ul>
<li><a href="http://clojure.org/">Сайт языка</a></li>
<li><a href="http://alexott.net/ru/fp/books/">Список доступных книг про Clojure</a> (разделы про конкретные языки в обзоре литературы по ФП)</li>
<li><a href="http://alexott.net/ru/clojure/clojure-intro/index.html">Введение в Clojure на русском языке </a></li>
<li><a href="http://alexott.net/ru/clojure/video.html">Список видео-лекций и презентаций про Clojure</a></li>
<li><a href="http://planet.clojure.in/">Planet Clojure</a> - аггрегатор блогов</li>
<li><a href="http://dev.clojure.org/display/doc/Getting+Started">Getting started with Clojure</a> - описание первых шагов, включая установку и настройку средств разработки </li>
<li>Интерактивные ресурсы/учебники: <a href="http://www.4clojure.com/problems">4Clojure</a>, <a href="http://tryclj.com/">TryClojure</a>, <a href="http://himera.herokuapp.com/index.html">Himera</a>, <a href="https://github.com/relevance/labrepl">labrepl</a></li>
<li>Списки рассылки: <a href="https://groups.google.com/forum/?hl=ru&fromgroups#!forum/clojure">clojure</a>, <a href="https://groups.google.com/forum/?hl=ru&fromgroups#!forum/clojure-russian">clojure-russian</a> </li>
<li>IDE/редактора (остальные редактора/IDE описаны в подразделах Getting Started): <a href="http://dev.clojure.org/display/doc/Getting+Started+with+Eclipse+and+Counterclockwise">Eclipse</a>, <a href="http://dev.clojure.org/display/doc/Getting+Started+with+La+Clojure+and+IntelliJ+IDEA">IntelliJ IDEA</a></li>
<li>Средства сборки: <a href="http://alexott.net/ru/clojure/ClojureMaven.html">поддержка Clojure в Maven</a>, <a href="https://github.com/technomancy/leiningen">Leiningen </a></li>
<li>Библиотеки/фреймворки:
<ul>
<li>Web: <a href="https://github.com/ring-clojure/ring">Ring</a>, <a href="https://github.com/weavejester/compojure">Compojure</a>, <a href="http://www.webnoir.org/">Noir, </a><a href="https://github.com/weavejester/hiccup">Hiccup</a>, <a href="https://github.com/weavejester/lein-ring">lein-ring</a>, <a href="https://github.com/clojure/clojurescript">ClojureScript</a>, <a href="http://clojurescriptone.com/">ClojureScript One</a>, l<a href="https://github.com/emezeske/lein-cljsbuild">ein-cljsbuild</a></li>
<li>SQL: <a href="http://sqlkorma.com/">Korma</a>, <a href="https://github.com/clojure/java.jdbc">clojure.java.jdbc</a></li>
<li>NoSQL: <a href="http://clojuremongodb.info/">Monger</a> (MongoDB), <a href="https://github.com/clojure-clutch/clutch">Clutch</a> (CouchDB), <a href="https://github.com/compasslabs/clojure-hbase-schemas">clojure-hbase-schemas</a> (HBase)</li>
<li>GUI: <a href="https://github.com/daveray/seesaw">Seesaw</a> </li>
<li><a href="https://github.com/clojure/core.logic">core.logic</a></li>
<li><a href="http://dev.clojure.org/display/doc/Clojure+Contrib">Contrib libraries</a></li>
</ul>
</li>
<li>Внутреннее устройство persistent коллекций: <a href="http://blog.higher-order.net/2009/02/01/understanding-clojures-persistentvector-implementation/">вектора</a>, <a href="http://blog.higher-order.net/2009/09/08/understanding-clojures-persistenthashmap-deftwice/">отображения</a> (maps)</li>
</ul>
Alex Otthttp://www.blogger.com/profile/13001951608173211050noreply@blogger.com3tag:blogger.com,1999:blog-2145365503775784580.post-28463006177284370762012-04-15T18:46:00.000+01:002012-04-15T18:46:33.292+01:00Clojure 1.4!А между тем, незаметно подкрался релиз новой версии языка Clojure - 1.4.<br />
Rich Hickey называет этот релиз в основном maintenance, хотя есть и достаточно крупные изменения:<br />
<ul><li>Расширяемая процедура чтения (reader) - разработчик может указать функцию чтения для своих типов данных. Разработчик должен указать метку для своего типа данных, и соответствующую функцию чтения, и данная функция будет вызвана после того, как следующая (после метки) форма будет считана стандартным reader. Например, можно будет писать вот так:<code> <span style="font-family: "Courier New",Courier,monospace;">#foo/bar [1 2 3]</span> </code>- в этом случае, после чтения метки, процедура чтения сначала считает форму <code style="font-family: "Courier New",Courier,monospace;">[1 2 3]</code>, а затем вызовет процедуру связанную с данной меткой (если она определена) и передаст ей прочитанные данные. В состав новой версии вошла поддержка чтения двух новых типов - <span style="font-family: "Courier New",Courier,monospace;">#inst</span> - для времени и даты, и <span style="font-family: "Courier New",Courier,monospace;">#uuid</span> - для UUID.<code><br />
</code></li>
<li> Новый синтаксис для доступа к полям записей (унифицировано с ClojureScript) - теперь можно писать <span style="font-family: "Courier New",Courier,monospace;">(.-field_name record-instance)</span>.</li>
<li>Возможность контролировать поведение компилятора Clojure с помощью опций, указанных через переменную <span style="font-family: "Courier New",Courier,monospace;">*compiler-options*</span>.</li>
</ul>Остальные изменения включают в себя добавление новых функций в базовую библиотеку, достаточно много исправлений ошибки, оптимизации производительности. <br />
Полный список изменений можно <a href="https://github.com/clojure/clojure/blob/master/changes.md">найти в репозитории</a>. Кроме того, может быть интересным <a href="http://www.infoq.com/interviews/hickey-clojure-reader">интервью Rich Hickey</a> в котором он рассказывает про некоторые изменения в новой версии.Alex Otthttp://www.blogger.com/profile/13001951608173211050noreply@blogger.com0tag:blogger.com,1999:blog-2145365503775784580.post-85956994598229020772011-11-27T16:09:00.001+01:002011-11-28T10:20:59.153+01:00Перевод TaPL в продажеДля заинтересованных - перевод TaPL можно уже купить. findbook показывает что можно заказать через <a href="http://www.goodreads.ru/books/2460883/default.aspx">goodreads.ru</a>, books.ru имеет книгу в каталоге, но она помечена как "нет в продаже"...<br />
<div>Судя по <a href="http://juick.com/qrilka/1628376#7">информаци из juick</a>, в Москве можно купить в обычных книжных магазинах: "В москве продаётся как минимум в МДК (на арбате и в техкниге), в Москве (на тверской), и в библиоглобусе. Дешевле всего (за 1100р) можно купить в МЦНМО (<a href="http://www.mccme.ru/head/address.html">mccme.ru</a>). туда лучше заранее позвонить, ибо много книг хранить они не могут"...</div><div><div><div>P.S. а озон почему-то выставил безумную цену в 2 с лишним тысячи, поэтому они идут лесом :-)<br />
<br />
Update: Алексей Махоткин <a href="http://ru-lambda.livejournal.com/133077.html">написал пост</a>, где собрал список всех известных магазинов и других способов покупки книги...</div></div></div>Alex Otthttp://www.blogger.com/profile/13001951608173211050noreply@blogger.com0tag:blogger.com,1999:blog-2145365503775784580.post-37745526926036523422011-10-21T11:59:00.000+01:002011-10-21T11:59:09.132+01:00Книга "Типы в языках программирования"Из <a href="http://newstar.rinet.ru/pipermail/tapl/2011-October/000445.html">достоверных источников</a> стало известно, что книга "<a href="http://newstar.rinet.ru/%7Egoga/tapl/">Типы в языках программирования</a>" (перевод известной "Types and Programming Languages") вышла в бумажном виде, и <a href="http://dl.dropbox.com/u/132983/IMG_1009.jpg">это не миф</a> :-) Пока правда неизвестно где ее можно купить, но вы можете <a href="http://newstar.rinet.ru/pipermail/tapl/2011-October/000446.html">связаться с Алексеем Махоткиным</a> (aka squadette) и узнать об этом. Я тоже напишу когда она будет доступна в магазинах.<br />
Также доступна полная <a href="http://dl.dropbox.com/u/132983/tapl.pdf">электронная версия книги</a>, она совпадает с печатной версией. Меньшего формата не будет (пока?), поскольку там есть проблемы с таблицами и листингами, но вы можете попытаться переверстать, благо исходные тексты также доступны.<br />
Эта книга труд многих людей - Юра Бронников сделал львинную часть перевода, Алексей Махоткин сделал огромную работу по вычитке и редактированию, а Вадим Родионов так красиво и правильно все сверстал. Кроме того, много людей читало промежуточные версии перевода и присылало замечания и пожелания - всем спасибо!Alex Otthttp://www.blogger.com/profile/13001951608173211050noreply@blogger.com5tag:blogger.com,1999:blog-2145365503775784580.post-46110719608348853182011-09-24T16:14:00.000+01:002011-09-24T16:14:07.297+01:00Что нового в Clojure 1.3?<p>Сегодня ночью была выпущена новая версия <a href="http://clojure.org/">языка Clojure</a> — 1.3. Что нового в этой версии? Давайте рассмотрим основные изменения сделанные в этой версии (детальный список изменений можно найти <a href="https://github.com/clojure/clojure/blob/1.3.x/changes.txt">в соответствующей ветке репозитория</a>).</p><h3>Расширенная поддержка примитивных типов</h3><p class="first">В предыдущих версиях, примитивные типы (long, double, etc.) поддерживались только для локальных арифметических операций и при объявлении полей <code>deftype</code>/<code>defrecord</code>, но не для аргументов функций и не для возвращаемых значений. Boxing выполнялся всегда, что часто приводило к ощутимым накладным расходам.</p><p>В новой версии примитивные типы поддерживаются в полной мере, что приводит к значительному увеличению производительности кода (в соответствующих тестах, в среднем в 3-5 раз). Соответственно изменилась работа с арифметическими выражениями — для примитивных типов будут использоваться стандартные операторы Java. Но при этом не будет происходит автоматического превращения в "Big*" типы при переполнении, как это происходило раньше — вместо этого будет брошено исключение. Если вам все-таки нужно автоматическая конвертация, то вы можете использовать операторы <code>+'</code>, <code>*'</code>, и т.д., хотя они и более медленные. Битовые операции теперь только поддерживаются для примитивных типов, и вся их поддержка для "Big*" была убрана из языка.</p><p>Для использования примитивных типов вам необходимо добавить соответствующие type hints, например:</p><pre class="src">(<span style="color: #7f007f;">defn</span> <span style="color: #0000ff;">fib</span> <span style="color: #218a21;">^long</span> [<span style="color: #218a21;">^long</span> n]
(<span style="color: #473c8a;">if</span> (<span style="color: #9f522c;"><=</span> n 1)
1
(<span style="color: #9f522c;">+</span> (fib (<span style="color: #9f522c;">dec</span> n)) (fib (<span style="color: #9f522c;">-</span> n 2)))))
</pre><p>Более подробно обо всем этом <a href="http://dev.clojure.org/display/doc/Documentation+for+1.3+Numerics">на соответствующей странице JIRA</a>.</p><h3>Улучшения <code>defrecord</code> и <code>deftype</code></h3><p class="first">В версии 1.3 были сделаны различные улучшения для работы с <code>defrecord</code> и <code>deftype</code>:</p><ul><li>новый синтаксис для чтения и записи — либо с метками (<code>#myns.MyRecord{:a 1, :b 2}</code> — только для записей), либо позиционный (<code>#myns.MyRecord[1 2]</code> — для записей и типов);</li>
<li>автоматическая генерация функций для создания типов и записей: <code>myns/map->MyRecord</code> (только для записей) и <code>myns/->MyRecord</code> (для записей и типов).</li></ul><p>Подробнее можно прочитать вот <a href="http://dev.clojure.org/display/design/defrecord+improvements">тут</a>.</p><h3>Reflection API</h3><p class="first">Введено новое пространство имен <code>clojure.reflect</code>, функции которого должны обеспечить более удобную и быструю работу с классами, методами и т.д. Подробнее об этом <a href="http://dev.clojure.org/display/design/Reflection+API">тут</a>.</p><h3>Модульный <code>clojure-contrib</code></h3><p class="first">Начиная с версии 1.3, больше не существует монолитного набора библиотек известного как <code>clojure-contrib</code> — вместо этого, были созданы отдельные проекты для каждой из библиотек, что позволяет им развиваться и выпускаться независимо друг от друга. Полный список всех старых библиотек, и соответствующих им новых, можно найти на <a href="http://dev.clojure.org/display/design/Where+Did+Clojure.Contrib+Go">отдельной странице</a>.</p><h3>Множественные улучшения производительности</h3><p class="first">Кроме улучшений в части производительности, описанных выше, в новом релизе сделано множество изменений чтобы обеспечить более высокую скорость работы программ на Clojure:</p><ul><li>Более быстрый доступ к переменным;</li>
<li>Ускорение загрузки</li>
<li>Promises не используют блокировок (locks);</li>
<li>Инлайнинг <code>nil?</code>, битовых функций, математических операций, функций <code>min</code> & <code>max</code> с разным числом аргументов;</li>
<li>и многое другое...</li></ul><h3>Прочее</h3><p class="first">Помимо новой функциональности описанной выше, а также различных исправлений ошибок, в новой версии реализованы новые вещи (перечислены не все):</p><ul><li>Некоторые вспомогательные пространства имен (<code>clojure.set</code>, <code>clojure.xml</code>, <code>clojure.zip</code>) не загружаются при запуске;</li>
<li>Объявления сделанные с помощью <code>def</code> более не являются "динамическими" по умолчанию — вы должны использовать <code>^:dynamic</code> если хотите иметь возможность использования ее в <code>binding</code>;</li>
<li>Улучшенные сообщения об ошибках и исключениях;</li>
<li>Можно вызвать <code>deref</code> с указанием таймаута;</li>
<li>Функция <code>comp</code> возвращает <code>identity</code> если вызвана без параметров;</li>
<li>Возможность указания разных возвращаемых типов в объявлениях одной функции с разными количествами аргументов;</li>
<li>Некоторые функции перемещены в другие пространства имен;</li></ul>Alex Otthttp://www.blogger.com/profile/13001951608173211050noreply@blogger.com5tag:blogger.com,1999:blog-2145365503775784580.post-1650023000473946532011-09-18T10:59:00.001+01:002011-09-19T10:12:57.397+01:00Перевод " Learn You a Haskell for Great Good!"BTW, планируется выпуск русского перевода "Learn You a Haskell for Great Good!" в виде бумажной книги. Переводом занимается <a href="http://arsanukaev.blogspot.com/">Yasir Arsanukaev</a>, и работа над переводом ведется на <a href="https://bitbucket.org/yasir/lyah">bitbucket</a> - кто может, присоединяйтесь к вычитке перевода! :-)<br />
<br />
P.S. Из достоверных источников стало известно, что книжка уже на этапе верстки, так что недолго ждать осталось :-)Alex Otthttp://www.blogger.com/profile/13001951608173211050noreply@blogger.com2tag:blogger.com,1999:blog-2145365503775784580.post-1144260307488348402011-07-01T12:05:00.000+01:002011-07-01T12:05:50.477+01:00Опрос: название для русской версии Practical Common LispВ процессе причесывания русского перевода <a href="http://pcl.catap.ru/">Practical Common Lisp</a>, выползла проблема того, как книжка должна называться на русском языке. Пока вариантов немного, и некоторые звучат не особо :-( Поэтому хочу попросить помощи у сообщества - какой из переводов вам больше нравится (или можете предложить свой) - пишите номера или сови предложения в комментариях:<br />
<ol><li>Practical Common Lisp - оставить оригинальное название (будет плохо искаться в поиске, имхо)</li>
<li>(ru '(Practical Common Lisp)) - вариант <a href="http://catap.ru/blog/">catap</a>'а</li>
<li>Практика Common Lisp</li>
<li>Common Lisp на практике</li>
<li>Практический Common Lisp </li>
<li>Практический Lisp</li>
</ol>Alex Otthttp://www.blogger.com/profile/13001951608173211050noreply@blogger.com52tag:blogger.com,1999:blog-2145365503775784580.post-53314770061891598562011-05-14T12:26:00.002+01:002011-05-15T10:45:11.049+01:00Небольшой книжный обзорДавно не писал в блог, даже собирался как-то продолжить свою серию обзоров книг, прочитанных за последние два месяца, но со временем полный завал - релизы на работе, плюс дополнительные проекты, поэтому писать про книги буду реже... Так что рецензии на уже прочитанные книги, и то, что я буду дальше читать, можно найти <a href="http://www.goodreads.com/user/show/635213-alex-ott">на Goodreads</a>.<br />
<h3>Вкратце о разных книгах</h3>За мартовский отпуск дочитал давно лежащую в очереди "The art of meta-object protocol" - книжка дает понимание как проектировался CLOS, как были выбраны те или иные решения, и т.д.<br />
В апреле в достаточно быстром темпе (они предложили сделать ревью) прочитал две книги издательства Manning: <a href="http://www.manning.com/mattmann/">Tika in Action</a> и <a href="http://www.manning.com/wright/">ManifoldCF in Action</a>. Первая была не особо интересной для меня, поскольку я в этой области работаю уже давно, да и tika знаю достаточно хорошо, но я думаю, что книжка все равно будет интересна для людей, которым нужно выделять текст и мета-информацию из файлов разных форматов. А вот вторая книга была более интересной - я ее купил когда она еще только была анонсирована, но руки не доходили ее прочитать. Книга описывает ManifoldCF - расширяемый фреймворк для работы с разными content repositories, откуда можно извлекать информацию для индексирования и прочей обработки. Фреймворк очень интересный, и я надеюсь его запользовать в одном из своих проектов.<br />
<h3>Функциональное программирование на F#</h3>Также в апреле мне попала на руки книга Дмитрия Сошникова <a href="http://www.ozon.ru/context/detail/id/6151130/?partner=alexott">Функциональное программирование на F#</a> (спасибо издательству ДМК-Пресс за предоставленный файл), и я ее неспешно прочитал...<br />
Книга чисто практическая, начинается с примеров, и все остальное вводится по мере повествования. Это же является и ее недостатком - нет подробностей о лямбда-исчислении и синтаксисе языка - для этого требуется обратиться к другим источникам, типа <a href="https://code.google.com/p/funprog-ru/">перевода курса лекций Джона Хариссона</a>, и <a href="http://www.ozon.ru/context/detail/id/6252314/?partner=alexott">переводу орейлевской книги про F#</a>, которая вышла в издательстве "Символ-Плюс" (я ее правда не читал в переводе).<br />
<br />
Описываются все основные приемы программирования - функциональный, императивный и объектно-ориентированный. Достаточно хорошо описаны расширения языка типа активных паттернов, async, etc. <br />
<br />
Ну и стоит отдельно упоминуть 7-ю главу, которая содержит примеры решения задач в различных областях - "научное" программирование, графика, программирование для Windows Phone 7, веб-программирование, включая использование F# с ASP.Net, работу с веб-сервисами и т.п.<br />
Я думаю, что книга может быть полезна студентам и начинающим программистам для использования в качестве сборника примеров решения задач. А затем, если язык заинтересует, то можно переходить и к <a href="http://alexott.net/ru/fp/books/">другим книгам</a>...Alex Otthttp://www.blogger.com/profile/13001951608173211050noreply@blogger.com4tag:blogger.com,1999:blog-2145365503775784580.post-85326036962741465542011-04-13T13:23:00.000+01:002011-04-13T13:23:31.500+01:00Новый номер журнала «Практика функционального программирования»<p>Вышел <a href="http://fprog.ru/2011/issue7/">свежий (7-й) номер журнала «Практика функционального программирования»</a>. В новом номере вы можете прочитать следующие статьи:<p><ul><li> <b>Язык РЕФАЛ — взгляд со стороны.</b> Бойко Банчев расскажет о сущности, истории и современном состоянии языка РЕФАЛ.<li> <b>Circumflex — веб-фреймворк на Scala <i>comme il faut</i></b>. Александр Темерев даст урок использования этого «обезжиренного» и гибкого веб-фреймворка, написанного на Scala.<li> <b>Разработка алгоритма обнаружения движения в среде программирования Mathematica</b>. Вадим Залива расскажет об опыте прототипирования такого алгоритма при разработке iPhone-приложения <a href="http://itunes.apple.com/us/app/isentry/id396777365?mt=8">iSentry</a>.<li> <b>Как написать LDAP-сервер на Erlang</b> и <b>Как написать LDAP-сервер на Си</b>. Максим Сохацкий и Олег Смирнов обменяются любезностями со Львом Валкиным: Максим и Олег похвалят Erlang за то, что на нем можно за 20 минут написать LDAP-сервер, а Лев докажет, что дело тут вовсе не в Erlang.<li> <b>Продолжения в практике</b>. Алексей Вознюк расскажет об использовании продолжений для упрятывания асинхронности кода за обыкновенным «последовательным» синтаксисом.<li> <b>Суперкомпиляция: идеи и методы</b>. Илья Ключников, расскажет о суперкомпиляции, построив поразительно компактный и понятный суперкомпилятор простого языка, и покажет, что она применима не только для удивительно мощной оптимизации многих классов программ, но имеет и другие неожиданные применения.</ul><p>Кроме электронной версии, этот номер доступен и в <a href="http://samizdal.ru/fprog">печатном виде</a>!</p><p>Обсудить статьи вы можете в <a href="http://fprog.ru/2011/issue7/discuss/">fprog@ЖЖ</a>.</p>Alex Otthttp://www.blogger.com/profile/13001951608173211050noreply@blogger.com0tag:blogger.com,1999:blog-2145365503775784580.post-7666019326026226882011-04-07T09:40:00.000+01:002011-04-07T09:40:33.551+01:00Monad tutorial для кложуры<a href="http://www.vimeo.com/user5897815/videos">Серия слайдкастов</a> про монады на примере Clojure сделанный <a href="http://www.exampler.com/blog/">Brian Marick.</a> <br />
Первая лекция начинается со следующей фразы "Существует предсказание, что когда-то, каждый человек на земле сделает monad tutorial, и высшая цель вселенной будет достигнута, и все человечество попадет в рай..." :-)Alex Otthttp://www.blogger.com/profile/13001951608173211050noreply@blogger.com0tag:blogger.com,1999:blog-2145365503775784580.post-73358389296141424972011-02-09T19:08:00.000+01:002011-02-09T19:08:02.980+01:00Дайджест прочитанных книг. Январь 2011<p>Как вы наверное уже заметили, в прошлом месяце не было обзора литературы — было слишком много дел, поэтому никакой книги я читать не закончил. Но зато рождественские и новогодние праздники позволили прочитать больше книг.</p><div class="contents"><dl><dt><a href="#sec1">DSLs in Action</a></dt>
<dt><a href="#sec2">Camel in Action</a></dt>
<dt><a href="#sec3">Test-driven development: By Example</a></dt></dl></div><h2><a name="sec1" id="sec1"></a>DSLs in Action</h2><p class="first">Давно собирался почитать что-то про domain specific languages (DSL) чтобы найти новые идеи, сравнить с тем что я сам делаю (у меня есть несколько DSL, которые я применяю в рабочих проектах), может быть улучшить свои решения. Мой выбор пал на <a href="http://www.amazon.com/gp/product/1935182455?ie=UTF8&tag=aleottshompag-20&linkCode=as2&camp=1789&creative=390957&creativeASIN=1935182455">DSLs in Action</a>, написанную Debasish Ghosh, который является достаточно известным разработчиком в Scala сообществе, хотя использует и другие языки, например, Haskell, Groovy, Clojure. Когда я выбирал что почитать, я также смотрел в сторону книги <a href="http://www.amazon.com/gp/product/0321712943?ie=UTF8&tag=aleottshompag-20&linkCode=as2&camp=1789&creative=390957&creativeASIN=0321712943">Domain-Specific Languages</a>, написанную Martin Fowler, но Manning прислал очередную партию скидок, и я купил книгу у них (и не пожалел).</p><p>Книга написана очень простым языком, но при этом дается материал очень высокого качества. Автор показывает различные приемы разработки DSL используя разные языки — Ruby, Groovy, Scala, Clojure (в книге используются только языки, работающие только на JVM, и многие вещи применимы только к этой платформе). Это позволяет показать разные подходы к проектированию и реализации DSL (есть также <a href="http://debasishg.blogspot.com/2011/02/why-i-made-dsls-in-action-polyglotic.html">статья в блоге автора</a> о том, почему использовались разные языки).</p><p>Первая часть книги посвящена основам DSL — автор начинает рассказ с описания что такое DSL, из чего они состоят, какие бывают виды DSL, как они выполняются, преимущества и недостатки использования DSL в ваших проектах. Отдельно описывается то, как моделируются предметные области, и как они влияют на структуру DSL.</p><p>Вторая глава демонстрирует простой DSL, который реализован с помощью стандартной Java, и анализируются недостатки конкретного подхода. Затем, аналогичный DSL создается с помощью Groovy, и рассматриваются его преимущества по сравнению с первой реализаций. В остальной части главы рассматриваются паттерны реализации DSL, с учетом предыдущей информации.</p><p>Третья глава посвящена вопросам интеграции DSL в основной проект. В ней обсуждаются java scripting engine, интеграция на базе Spring, и т.д. Для каждого из возможных подходов, рассматриваются преимущества и недостатки данного подхода, то, как он может повлиять на реализацию DSL, и т.д.</p><p>Вторая часть (главы 4-8) посвящены реализации DSL на конкретных языках программирования. 4-я глава описывает основные приемы реализации внедряемых (internal) DSL — мета-программирование, типизированные абстракции, генерацию кода во время компиляции и т.д. И следующие две главы (5 и 6), подробно показывают как эти абстракции применяются при реализации DSL на Ruby, Groovy, Clojure и Scala.</p><p>Седьмая глава продолжает тему реализации DSL, но уже с точки зрения использования внешних (external) DSL. Рассматриваются разные виды парсеров, с помощью которых можно разбирать код использующий DSL, показывается небольшой пример использования ANTLR для генерации парсеров, и приводится небольшое описание Xtext — фреймворка для Eclipse, который упрощает разработку внешних DSL.</p><p>В восьмой главе продолжается тематика использования внешних DSL и в ней показывается применение комбинаторов парсеров для разбора исходного кода DSL. Глава начинается с небольшого описания того, что такое комбинаторы парсеров, а затем показывается пример использования комбинаторов парсеров в Scala для работы с внешними DSL.</p><p>И в заключительной части книги рассматриваются текущие тенденции в части разработки и использования DSL, утилит для упрощения разработки, и сопутствующие темы.</p><p>Кроме основного материала, в книге имеется несколько приложений, в которых собраны краткие описания используемых языков, что позволяет ознакомиться с примерами даже тем людям, которые не программируют на конкретных языках. Отдельно стоит упомянуть "философское" приложение A, которое посвящено обсуждению роли абстракций в моделировании предметной области, влиянию чистоты, отсутствия побочных эффектов на разработку, и сопутствующим проблемам. Кроме этого, может быть интересным приложение B, где обсуждается роль мета-программирования в разработке DSL.</p><p><em>Заключение:</em> если вы используете и/или разрабатываете DSL, или вам просто интересна эта тема, то книгу обязательно стоит прочитать — в ней много практической информации, которая будет полезна при разработке DSL.</p><h2><a name="sec2" id="sec2"></a>Camel in Action</h2><p class="first">Для очередного из "домашних" проектов понадобилось слепить систему обработки данных из разных источников, поэтому погуглив, я нашел <a href="http://camel.apache.org/">Apache Camel</a>, который показался мне интересным и достаточно зрелым проектом, а на очередной маннинговской распродаже я прикупил книжку <a href="http://www.amazon.com/gp/product/1935182366?ie=UTF8&tag=aleottshompag-20&linkCode=as2&camp=1789&creative=390957&creativeASIN=1935182366">Camel in Action</a> авторства Claus Ibsen и Jonathan Anstey.</p><p>Книга начинается (глава 1) с объяснения что такое Apache Camel, какие задачи он решает и из чего он состоит. Во второй главе более подробно рассматриваются маршруты (routes) и показывается как можно их создавать используя код на Java или Spring.</p><p>Вторая часть книги полностью посвящена базовым вопросам разработки с использованием Camel, показывается как преобразовывать данные, обрабатывать ошибки, тестировать код, и использовать дополнительные компоненты, такие как JMS, базы данных и т.д.</p><p>А третья часть посвящена таким вопросам как использование транзакций, организация конкурентной обработки данных, а также вопросам мониторинга и деплоймента проектов.</p><p>Отдельная глава (11-я) описывает организацию процесса разработки с использованием Camel, включая разработку новых компонентов и адаптеров. Кроме этого, на примере DSL для Scala, показывается как использовать Camel с другими языками (хотя на мой взгляд проект <a href="https://github.com/krasserm/scalaz-camel">scalaz-camel</a> выглядит более интересным).</p><p><em>Заключение:</em> если вы заинтересованы в применении Apache Camel, то книжку стоит прочитать — она может служить как хорошим введением в данную систему, так и достаточно подробным руководством по основным компонентам.</p><p>P.S. Для Clojure также начата работа по созданию библиотеки для интеграции с Apache Camel. Проект называется <a href="https://github.com/dysinger/hackamore">Hackamore</a> и находится в начальной стадии разработки. Если вам это интересно, то вы можете присоединиться к обсуждению в специально созданном <a href="https://groups.google.com/group/hackamore">списке рассылки</a>.</p><h2><a name="sec3" id="sec3"></a>Test-driven development: By Example</h2><p class="first">Недавно я готовил презентацию для внутреннего семинара о test driven development (TDD), и решил прочитать что-то от основоположников этого движения. Серию Extreme Programming я читал много лет назад, сразу после ее выхода, поэтому взгляд остановился на книге <a href="http://www.amazon.com/gp/product/0321146530?ie=UTF8&tag=aleottshompag-20&linkCode=as2&camp=1789&creative=390957&creativeASIN=0321146530">Test Driven Development: By Example</a> Кента Бека.</p><p>Книжка небольшая — чуть больше 200 страниц, но и этот объем является слишком большим для данной темы — автор взял одну проблему, и подробно разбирает процесс ее реализации, который управляется тестами, которые создаются по мере добавления новых требований. На протяжении первой части книги, с помощью данного примера иллюстрируются основы TDD и Unit testing.</p><p>Во второй части, применение TDD иллюстрируются описанием процесса реализации xUnit-подобного фреймворка для тестирования кода на Python, начиная с определения основной функциональности фреймворка, и затем, последовательной реализацией кода.</p><p>В третьей части рассматриваются основные приемы и паттерны использования TDD, проектирования кода для тестирования, разработки тестов и т.д.</p><p><em>Заключение:</em> хорошее введение в TDD, но стоит прочитать только для людей кто никогда с ним не сталкивался — слишком уж начального уровня. Хотя иногда попадаются полезные советы по организации кода, неплохое описание рабочего процесса и т.п. Если вы уже хоть как-то применяли тесты в своей работе, то можно найти более короткий источник нужной информации.</p>Alex Otthttp://www.blogger.com/profile/13001951608173211050noreply@blogger.com5tag:blogger.com,1999:blog-2145365503775784580.post-21756267462637857202011-02-04T15:19:00.005+01:002011-02-04T15:30:27.471+01:00Типы и протоколы в ClojureЭта заметка также опубликована как часть <a href="http://alexott.net/ru/clojure/clojure-intro/">статьи "Введение в Clojure"</a>...<br />
<hr><p>Одно из самых больших изменений в Clojure версии 1.2 — введение в язык новых артефактов: протоколов (protocols) и типов данных (datatypes). Данные изменения позволяют улучшить производительность программ по сравнению с мультиметодами, что в будущем даст возможность написать Clojure на Clojure (в данный момент протоколы и типы данных уже активно используются при реализации Clojure).</p><div class="contents"><dl><dt><a href="#sec1">Что это такое и зачем нужно?</a></dt><dt><a href="#sec2">Определение протоколов</a></dt><dt><a href="#sec3">Реализация протоколов</a></dt><dt><a href="#sec4">Определение типов данных</a></dt><dd><dl><dt><a href="#sec5">deftype & defrecord</a></dt><dt><a href="#sec6">reify</a></dt></dl></dd><dt><a href="#sec7">Дополнительные функции и макросы</a></dt><dt><a href="#sec8">Дополнительная информация</a></dt></dl></div><h2><a name="sec1" id="sec1"></a>Что это такое и зачем нужно?</h2><p class="first">Протоколы и типы данных — два связанных друг с другом понятия. Протоколы используются для определения полиморфных функций, которые затем могут быть реализованы для конкретных типов данных (в том числе и из других библиотек).</p><p>Существует несколько причин введения протоколов и типов данных в новую версию языка:</p><ul><li>Увеличить скорость работы полиморфных функций, при этом поддерживая большую часть функциональности мультиметодов, поскольку для протоколов диспатчеризация выполняется только по типу данных;</li>
<li>Использовать лучшие стороны интерфейсов (только спецификация функций, без реализации, реализация нескольких интерфейсов одним типом), в тоже время избегая недостатков (список реализуемых интерфейсов задан во время реализации типа данных, создание иерархии типов вида <code>isa/instanceof</code>);</li>
<li>Избежать <a href="http://en.wikipedia.org/wiki/Expression_Problem">Expression problem</a> и дать возможность расширять набор операций над типами данных без изменениях определения типов данных (в том числе и чужих) и перекомпиляции исходного кода<sup><a class="footref" name="fnr.1" href="#fn.1">1</a></sup>;</li>
<li>Использовать высокоуровневые абстракции для типов данных и операций над ними<sup><a class="footref" name="fnr.2" href="#fn.2">2</a></sup>, что упрощает проектирование программ.</li>
</ul><p>Также как и интерфейсы, протоколы позволяют объединить объявление нескольких полиморфных функций (или одной функции) в один объект<sup><a class="footref" name="fnr.3" href="#fn.3">3</a></sup>. Отличием от интерфейсов является то, что вы не можете унаследовать новый протокол от существующего протокола.</p><p>В отличии от имеющегося в Clojure <code>gen-interface</code> (и соответствующих <code>proxy/gen-class</code>) определение протоколов и типов не требует AOT (ahead-of-time) компиляции исходного кода, что упрощает распространение программ на Clojure. Однако при определении протокола, Clojure автоматически создает соответствующий интерфейс, который будет доступен для кода, написанного на Java.</p><p>Типы данных, определенные с помощью <code>deftype</code> или <code>defrecord</code> позволяют программисту на Clojure определять свои структуры данных, вместо использования обычных отображений и структур, но об этом <a href="#datatypes">ниже</a>.</p><p><em>Важно помнить, что протоколы и типы данных с одним и тем же именем могут быть определены в разных пространствах имен, так что стоит быть осторожным и не наделать ошибок при импорте определений и последующей реализации протоколов!</em></p><h2><a name="sec2" id="sec2"></a>Определение протоколов</h2><p class="first">Протоколом называется именованный набор функций с определенными сигнатурами. Для определения используется макрос, применение которого выглядит следующим образом:</p><pre class="src">(<span style="color: #a020f0;">defprotocol</span> <span style="color: #0000ff;">название</span> <span style="color: #666666;">"описание"</span> & сигнатуры)
</pre><p><code>название</code> — единственный обязательный параметр, хотя определение протокола без функций не имеет особого смысла. В описании вы можете описать ваш протокол, и это описание будет показываться при вызове функции <code>doc</code> для вашего протокола. Для протокола вы можете указать одну или несколько сигнатур функций, где каждая сигнатура выглядит следующим образом:</p><pre class="src">(имя [аргументы+]+ <span style="color: #008b00;">"описание"</span>)
</pre><p>Вы можете определять одну функцию, которая будет принимать различное количество параметров, но первым аргументом функции всегда является объект, на основании которого будет выполняться диспатчеризация, и к которому эта функция будет применяться. Вы можете рассматривать его как <code>this</code> в Java и C++. В дополнение к сигнатурам, вы можете описать вашу функцию, но это необязательно.</p><p>Давайте посмотрим на стандартный пример:</p><pre class="src">(<span style="color: #a020f0;">defprotocol</span> <span style="color: #0000ff;">AProtocol</span>
<span style="color: #666666;">"A doc string for AProtocol abstraction"</span>
(bar [a b] <span style="color: #008b00;">"bar docs"</span>)
(baz [a] [a b] [a b c] <span style="color: #008b00;">"baz docs"</span>))
</pre><p>Данный протокол определяет две функции: <code>bar</code> — с двумя параметрами, и <code>baz</code> — с одним, двумя или тремя параметрами.</p><p><code>defprotocol</code> также создаст соответствующий интерфейс, с тем же самым именем что и протокол. Данный интерфейс будет иметь те же самые функции, что и протокол.</p><h2><a name="sec3" id="sec3"></a>Реализация протоколов</h2><p class="first">Протокол сам по себе ни на что не влияет — чтобы использовать его, мы должны добавить его специализации для типов данных или классов JVM. Для этого может использоваться функция <code>extend</code>, использование которой выглядит следующим образом:</p><pre class="src">(<span style="color: #006400;">extend</span> тип-или-класс
протокол-1
{<span style="color: #006400;">:метод-1</span> уже-определенная-функция
<span style="color: #006400;">:метод-2</span> (<span style="color: #006400;">fn</span> [a b] ...)
<span style="color: #006400;">:метод-3</span> (<span style="color: #006400;">fn</span> ([a]...) ([a b] ...)...)}
протокол-2
{...}
...)
</pre><p>Для этой функции вы указываете имя типа данных или класса (или <code>nil</code>), и передаете список состоящий из названий протоколов (<code>протокол-1</code> и т.д.) и отображений, которые связывают функции протокола (<code>метод-1</code> и т.д.) с их реализациями — анонимными или именованными функциями.</p><p>Стоит отметить, что функция <code>extend</code> является низкоуровневым инструментом реализации протоколов. Кроме этого, в состав языка введены макросы <code>extend-protocol</code> & <code>extend-type</code>, которые немного упрощают реализацию протоколов<sup><a class="footref" name="fnr.4" href="#fn.4">4</a></sup>. Протокол также может быть реализован непосредственно при <a href="#datatypes">объявлении типа данных</a>.</p><p>Использование <code>extend-type</code> выглядит практически также как и использование <code>extend</code>, но пользователь записывает реализации в более удобном виде (<code>extend-type</code> раскрывается в соответствующий вызов <code>extend</code>):</p><pre class="src">(<span style="color: #006400;">extend-type</span> тип-или-класс
протокол-1
(метод-2 [a b] ...)
(метод-3 ([a]...)
([a b] ...)...)
протокол-2
(....)
...)
</pre><p>Макрос <code>extend-protocol</code> использоваться в тех случаях, если вы хотите реализовать один протокол для нескольких типов данных или классов. В общем виде использование <code>extend-protocol</code> выглядит следующим образом:</p><pre class="src">(<span style="color: #006400;">extend-protocol</span> название-протокола
Тип-или-Класс-1
(метод-1 ...)
(метод-2 ...)
Тип-или-Класс-2
(метод-1 ...)
(метод-2 ...)
...)
</pre><p>При использовании, <code>extend-protocol</code> раскрывается в серию вызовов <code>extend-type</code> для каждого из используемых типов.</p><p>Давайте рассмотрим небольшой пример. Пусть мы объявим следующий простой протокол:</p><pre class="src">(<span style="color: #a020f0;">defprotocol</span> <span style="color: #0000ff;">Hello</span> <span style="color: #666666;">"Test of protocol"</span>
(hello [this] <span style="color: #008b00;">"hello function"</span>))
</pre><p>Мы можем использовать <code>extend</code>, <code>extend-protocol</code>, или <code>extend-type</code> для его специализации для класса <code>String</code>:</p><pre class="src">(<span style="color: #006400;">extend</span> <span style="color: #006400;">String</span>
<span style="color: #006400;">Hello</span>
{<span style="color: #006400;">:hello</span> (<span style="color: #006400;">fn</span> [this] (<span style="color: #006400;">str</span> <span style="color: #008b00;">"Hello "</span> this <span style="color: #008b00;">"!"</span>))})
(<span style="color: #006400;">extend-protocol</span> <span style="color: #006400;">Hello</span> <span style="color: #006400;">String</span>
(hello [this] (<span style="color: #006400;">str</span> <span style="color: #008b00;">"Hello "</span> this <span style="color: #008b00;">"!"</span>)))
(<span style="color: #006400;">extend-type</span> <span style="color: #006400;">String</span> <span style="color: #006400;">Hello</span>
(hello [this] (<span style="color: #006400;">str</span> <span style="color: #008b00;">"Hello "</span> this <span style="color: #008b00;">"!"</span>)))
</pre><p>При использовании любой из этих реализаций для объекта класса <code>String</code> мы получим один и тот же ответ:</p><pre class="src">user> (hello <span style="color: #008b00;">"world"</span>)
<span style="color: #008b00;">"Hello world!"</span>
</pre><p>Стоит отметить, что если вы не реализовали протокол для определенного типа данных, то при вызове функции будет сгенерировано исключение. В том случае, если вам необходима "реализация по умолчанию", то вы можете специализировать протокол для класса <code>Object</code>.</p><h2><a name="sec4" id="sec4"></a><a name="datatypes" id="datatypes"></a>Определение типов данных</h2><p class="first">В Clojure 1.2 введены два метода определения новых именованных типов данных (<code>deftype</code> и <code>defrecord</code>), которые реализуют абстракции, определенные протоколами и/или интерфейсами (к типам данных относится также <code>reify</code>, который описан ниже).</p><p><code>deftype</code> и <code>defrecord</code> динамически создают именованный класс, который имеет набор заданных полей и (необязательно) методов для одного или нескольких протоколов и/или интерфейсов. Поскольку они не требуют явной компиляции, то это дает возможность их использования в интерактивной разработке. С точки зрения разработчика <code>deftype</code> и <code>defrecord</code> похожи на <code>defstruct</code>, но во многом они отличаются:</p><ul><li>они создают уникальный класс с соответствующими полями;</li>
<li>созданный класс имеет конкретный тип;</li>
<li>имеется конструктор;</li>
<li>для полей можно указывать типы (это будет использоваться для оптимизации и ограничения типов в конструкторе).</li>
</ul><p><code>deftype</code> является "базовым" инструментом для определения типов данных — созданный тип имеет только конструктор, и ничего больше — все остальное должен реализовывать разработчик. Но при этом, <code>deftype</code> может иметь изменяемые поля, чего не имеет <code>defrecord</code>.</p><p>В отличии от <code>deftype</code>, <code>defrecord</code> более прост в использовании, поскольку создаваемый тип данных имеет большую функциональность (по большей части за счет реализации интерфейсов <code>IKeywordLookup</code>, <code>IPersistentMap</code>, <code>Serializable</code> и т.д.):</p><ul><li>автоматически генерируемые функции <code>hashCode</code> и <code>equals</code>;</li>
<li>возможность указания мета-информации;</li>
<li>доступ к полям с помощью ключевых символов;</li>
<li>вы можете добавлять поля, не указанные в определении.</li>
</ul><p><code>deftype</code> и <code>defrecord</code> обычно имеют разные области применения: <code>deftype</code> в основном используется для "системных" вещей — коллекций, и т.п., тогда как <code>defrecord</code> в основном используется для хранения информации из "проблемной области" — данных о заказчиках, записях в БД и т.п. — то, для чего использовались отображения в версиях 1.0 и 1.1.</p><p>Давайте рассмотрим как использовать конкретные средства для создания типов данных.</p><h3><a name="sec5" id="sec5"></a>deftype & defrecord</h3><p class="first">В общей форме использование макросов <code>deftype</code> и <code>defrecord</code> выглядит следующим образом:</p><pre class="src">(deftype имя [& поля] & спецификации)
(defrecord имя [& поля] & спецификации)
</pre><p>Для обоих макросов обязательным параметром является лишь имя, которое становится именем класса. Поля, которые станут членами класса, перечисляются в векторе, следующем за именем, и могут содержать объявления типов. После этого вектора, можно указать список реализуемых интерфейсов и протоколов, вместе с реализацией (это не обязательно, поскольку для этого вы позже можете использовать <code>extend-protocol</code> & <code>extend-type</code>).</p><p>Спецификации протоколов/интерфейсов выглядят следующим образом:</p><pre class="src">протокол/интерфейс
(название-метода [аргументы*] реализация)*
</pre><p>Вы можете указать любое количество протоколов/интерфейсов, которые будут реализованы данным типом данных. Давайте посмотрим на простейший тип данных, который реализует протокол <code>Hello</code>:</p><pre class="src">(<span style="color: #a020f0;">deftype</span> <span style="color: #0000ff;">A</span> []
<span style="color: #006400;">Hello</span>
(hello [this] (<span style="color: #006400;">str</span> <span style="color: #008b00;">"Hello A!"</span>)))
</pre><p>Мы можем вызвать функцию <code>hello</code> для нашего объекта, и получим следующий вывод:</p><pre class="src">user> (hello (<span style="color: #006400;">A.</span>))
<span style="color: #008b00;">"Hello A!"</span>
</pre><p>Мы можем также создать тип с помощью <code>defrecord</code>:</p><pre class="src">(<span style="color: #a020f0;">defrecord</span> <span style="color: #0000ff;">B</span> [name]
<span style="color: #006400;">Hello</span>
(hello [this] (<span style="color: #006400;">str</span> <span style="color: #008b00;">"Hello "</span> name <span style="color: #008b00;">"!"</span>)))
</pre><p>и вызвать метод <code>hello</code> для этого типа:</p><pre class="src">user> (hello (<span style="color: #006400;">B.</span> <span style="color: #008b00;">"world"</span>))
<span style="color: #008b00;">"Hello world!"</span>
</pre><p>Как уже отмечалось выше, создаваемые поля по умолчанию являются неизменяемыми, но если вы создаете тип с помощью <code>deftype</code>, то вы можете пометить некоторые поля как изменяемые, используя метаданные (с помощью ключевого символа <code>:volatile-mutable</code> или <code>:unsynchronized-mutable</code>). Для таких полей вы сможете использовать оператор <code>(set! afield aval)</code> для изменения данных. Давайте посмотрим как это делается на примере — если мы создадим следующий протокол и тип данных:</p><pre class="src">(<span style="color: #a020f0;">defprotocol</span> <span style="color: #0000ff;">Setter</span>
(set-name [this new-name]))
(<span style="color: #a020f0;">deftype</span> <span style="color: #0000ff;">AM</span> [^{<span style="color: #006400;">:volatile-mutable</span> true} mfield]
<span style="color: #006400;">Hello</span>
(hello [this] (<span style="color: #006400;">str</span> <span style="color: #008b00;">"Hello "</span> mfield <span style="color: #008b00;">"!"</span>))
<span style="color: #006400;">Setter</span>
(set-name [this new-name]
(set! mfield new-name)))
</pre>то мы сможем изменять значение поля:<br />
<pre class="src">user> (def am (AM. <span style="color: #008b00;">"world"</span>))
#'user/am
user> (hello am)
<span style="color: #008b00;">"Hello world!"</span>
user> (set-name am <span style="color: #008b00;">"peace"</span>)
<span style="color: #008b00;">"peace"</span>
user> (hello am)
<span style="color: #008b00;">"Hello peace!"</span>
</pre><h3><a name="sec6" id="sec6"></a>reify</h3><p><code>reify</code> используется тогда, когда вам нужно реализовать протокол или интерфейс только в одном месте — когда вы используете <code>reify</code> вы одновременно объявляете тип, и сразу создаете объект этого типа. Функция <code>reify</code> по своему использованию очень похожа на <code>proxy</code>, но с некоторыми исключениями:</p><ul><li>можно использовать только для интерфейсов и протоколов;</li>
<li>реализуемые методы являются методами результирующего класса, и они вызываются напрямую,<br />
без поиска в отображении, но при этом не поддерживается подмена методов в отображении.</li>
</ul><p>Эти отличия позволяют получить более высокую производительность по сравнению с <code>proxy</code>, и при создании и при выполнении.</p><p>Вот небольшой пример реализации протокола <code>Hello</code> для конкретного объекта:</p><pre class="src">(<span style="color: #a020f0;">def</span> <span style="color: #0000ff;">int-reify</span> (<span style="color: #006400;">reify</span> <span style="color: #006400;">Hello</span>
(hello [this] <span style="color: #008b00;">"Hello integer!"</span>)))
</pre><p>И при вызове <code>hello</code> для этого объекта, мы получим соответствующий результат:</p><pre class="src">user> (hello int-reify)
<span style="color: #008b00;">"Hello integer!"</span>
</pre><h2><a name="sec7" id="sec7"></a>Дополнительные функции и макросы</h2><p class="first">Для работы с протоколами и типами данных определено некоторое количество вспомогательных функций, которые могут вам понадобиться:</p><dl><dt><strong><code>extends?</code></strong></dt>
<dd>возвращает <code>true</code> если данный тип данных (2-й аргумент) реализует интерфейс, заданный первым аргументом;</dd>
<dt><strong><code>extenders</code></strong></dt>
<dd>возвращает коллекцию типов, реализующих заданный протокол;</dd>
<dt><strong><code>satisfies?</code></strong></dt>
<dd>возвращает <code>true</code> если данный протокол (1-й аргумент) применим к данному объекту (2-й аргумент);</dd> </dl><h2><a name="sec8" id="sec8"></a>Дополнительная информация</h2><p class="first">Как всегда, основной источник информации — сайт языка: ознакомьтесь с разделами <a href="http://clojure.org/protocols">protocols</a> и <a href="http://clojure.org/datatypes">datatypes</a>. Хорошее описание протоколов и типов данных можно найти в 13-й главе недавно вышедшей книги <a href="http://www.amazon.com/gp/product/1430272317?ie=UTF8&tag=aleottshompag-20&linkCode=as2&camp=1789&creative=390957&creativeASIN=1430272317">Practical Clojure. The Definitive Guide</a>, а также в <a href="http://www.amazon.com/gp/product/1935182595?ie=UTF8&tag=aleottshompag-20&linkCode=as2&camp=1789&creative=390957&creativeASIN=1935182595">Clojure in Action</a> и <a href="http://www.amazon.com/gp/product/1935182641?ie=UTF8&tag=aleottshompag-20&linkCode=as2&camp=1789&creative=390957&creativeASIN=1935182641">The Joy of Clojure. Thinking the Clojure Way</a>, которые будут выпущены в ближайшее время.</p><p>Stuart Halloway создал очень <a href="http://vimeo.com/11236603">интересный скринкаст</a> в котором он рассказывает о том, зачем были созданы протоколы и data types, и демонстрирует их применение на небольших примерах.</p><p>Введение новых возможностей в язык не обходится без статей в блогах. Вот ссылки на некоторые интересные статьи на эту тему:</p><ul><li><a href="http://www.ibm.com/developerworks/java/library/j-clojure-protocols/index.html">Статья Stuart Sierra</a> на IBM developerWorks;</li>
<li><a href="http://www.infoq.com/presentations/Clojure-Expression-Problem">Clojure's Solutions to the Expression Problem</a> — выступление Chris Houser на конференции Strange Loop 2010;</li>
<li>Серия из 3-х статей (<a href="http://www.objectcommando.com/blog/2010/03/26/clojure-protocols-part-1/">1</a>, <a href="http://www.objectcommando.com/blog/2010/03/29/clojure-protocols-part-2/">2</a>, <a href="http://www.objectcommando.com/blog/2010/04/12/clojure-protocols-part-3/">3</a>) о протоколах в блоге Object Commando;</li>
<li><a href="http://freegeek.in/blog/2010/05/clojure-protocols-datatypes-a-sneak-peek/">Краткое введение</a> в протоколы, написанное Baishampayan Ghose;</li>
<li><a href="http://formpluslogic.blogspot.com/2010/08/clojure-protocols-and-expression.html">Clojure Protocols and Expression Problem</a>;</li>
<li>Два постинга от Sean Devlin — <a href="http://fulldisclojure.blogspot.com/2010/08/thoughts-on-protocols.html">Protocol Implementation Awesomeness</a> и <a href="http://fulldisclojure.blogspot.com/2010/08/partially-implemented-protocols.html">Partially Implemented Protocols</a>;</li>
<li><a href="http://blog.higher-order.net/2010/05/05/circuitbreaker-clojure-1-2/">Пример реализации паттерна "Circuit Breaker"</a> с помощью протоколов;</li>
<li><a href="http://kotka.de/blog/2010/03/memoize_done_right.html#protocols">Пример использования протоколов</a> для мемоизации;</li>
<li><a href="http://bestinclass.dk/index.clj/2010/04/prototurtle-the-tale-of-the-bleeding-turtle.html">Еще пример</a> использования протоколов для реализации turtle graphics;</li>
<li><a href="http://kirindave.tumblr.com/post/658770511/monkey-patching-gorilla-engineering-protocols-in">Небольшое сравнение</a> Monkey Patching в Ruby с протоколами в Clojure;</li>
<li>Пример реализации стека с помощью протоколов (<a href="http://www.viksit.com/content/stack-implementation-clojure-using-protocols-and-records">1</a>, <a href="http://www.viksit.com/content/stack-implementation-clojure-ii-functional-approach">2</a>), написанный Viksit Gaur;</li>
</ul><br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<hr><p class="footnote"><a class="footnum" name="fn.1" href="#fnr.1">1.</a> Стоит однако отметить, что протоколы не реализуют monkey patching и внедрение методов<br />
(injection) в существующие типы данных.</p><br />
<p class="footnote"><a class="footnum" name="fn.2" href="#fnr.2">2.</a> Возможность реализации абстракций на Clojure и высокая скорость работы протоколов<br />
позволит в будущем написать Clojure на самой Clojure, без использования исходного кода<br />
на Java.</p><br />
<p class="footnote"><a class="footnum" name="fn.3" href="#fnr.3">3.</a> Люди знакомые с Haskell могут рассматривать протоколы как некоторое подобие типов<br />
классов (typeclasses) в этом языке, правда при этом нельзя определять реализации по<br />
умолчанию для методов.</p><br />
<p class="footnote"><a class="footnum" name="fn.4" href="#fnr.4">4.</a> Но <code>extend</code> может использоваться в тех случаях, когда вы хотите использовать одни и те<br />
же реализации для разных типов данных — в этом случае, вы можете создать отображение<br />
с нужными функциями, и использовать его для разных типов, например, как описано в<br />
<a href="http://fulldisclojure.blogspot.com/2010/08/thoughts-on-protocols.html">следующем блог-постинге</a>.</p>Alex Otthttp://www.blogger.com/profile/13001951608173211050noreply@blogger.com1tag:blogger.com,1999:blog-2145365503775784580.post-7161380850361061772011-02-01T21:40:00.001+01:002011-02-02T08:44:12.706+01:00Добавления в haskell-modeНа новогодних каникулах сделал давно запланированное добавление к haskell-mode - добавил поддержку для <a href="http://community.haskell.org/%7Endm/hlint/">hlint</a> (команда <b style="font-family: "Courier New",Courier,monospace;">hs-lint</b>) и <a href="http://projects.haskell.org/style-scanner/">haskell style scanner</a> (команда <b><span style="font-family: "Courier New",Courier,monospace;">hs-scan</span></b>). Как и в предыдущей реализации, hs-lint поддерживает замену кода на предлагаемый вариант.<br />
Патчи отправлены мейнтейнеру, но пока они не закоммиченны в основной репозиторий, эти изменения доступны в <a href="https://patch-tag.com/r/alexott/haskell-mode/home">моем форке</a>. Замечания и пожелания приветствуются...Alex Otthttp://www.blogger.com/profile/13001951608173211050noreply@blogger.com0tag:blogger.com,1999:blog-2145365503775784580.post-75486922556587487822010-12-30T17:52:00.003+01:002010-12-31T13:42:41.771+01:00Итоги года...Год получился интересным, было много интересных проектов, как на работе, так и вне ее.<br />
Продолжал "развлекаться" с Clojure, что в итоге вылилось в написание <a href="http://alexott.net/ru/clojure/clojure-intro/index.html">большой статьи</a> для журнала "Практика функционального программирования", докладах на <a href="http://www.slideshare.net/alexott/clojure-margincon-2010">MarginCon 2010</a> и на встрече Munster Java User Group, а также в подкасте у golodnyj (<a href="http://taop.rpod.ru/168440.html">1</a>, <a href="http://taop.rpod.ru/172639.html">2</a>). Ну и конечно, не обошлось без писания кода для разных проектов (Incanter, leiningen, swank-clojure, clojure-hadoop, и еще паре своих). Правда немного подзабросил Common Lisp и Scheme, но с первым я поработаю во время чтения недавно купленной "<a href="http://www.amazon.com/gp/product/1558601910?ie=UTF8&tag=aleottshompag-20&linkCode=as2&camp=1789&creative=390957&creativeASIN=1558601910">Paradigms of Artificial Intelligence Programming: Case Studies in Common Lisp</a>".<br />
Очень много <a href="http://alexott-ru.blogspot.com/search/label/book">читал</a> (соответствующая <a href="http://www.shelfari.com/alexott/lists/IsRead">полка на shelfari</a>, правда список на прочитать <a href="http://www.shelfari.com/alexott/lists/Reading">еще больше</a>), не в последнюю очередь благодаря покупке iPad, и приобретению электронных книг (много у Manning).<br />
Первый раз был в США (по работе) - была очень полезная поездка. Теперь в планах поездки уже не по работе, хочется вживую познакомиться с френдами на обоих побережьях США...<br />
На следующий год очень много планов:<br />
<ul><li>хочу немного увеличить количество Haskell и Erlang в своих проектах, и может быть посмотреть на Scala, если останется время;</li>
<li>продолжить заниматься machine learning, кроме того, есть несколько задумок в части natural language processing; </li>
<li>продолжу занятия с hadoop, и т.п. вещами, связанными с обработкой больших объемов данных;</li>
<li>обновить существующие статьи по программированию и Emacs, и может быть написать что-то новое для ПФП;</li>
<li>продолжить хакать Emacs, особенно в части CEDET для функциональных языков.</li>
</ul> И пользуясь случаем, хочу поздравить всех своих читателей с наступающим новым годом, и пусть у вас будет много интересных вещей в новом году, и вообще все хорошо в жизни :-)<br />
<br />
<i>Update</i>: Забыл написать, что в следующем году (марте скорее всего) будет официально издан перевод отличной книжки - Types and Programming Languages. Перевод закончен полностью, и сейчас только ведется работа над версткойAlex Otthttp://www.blogger.com/profile/13001951608173211050noreply@blogger.com5tag:blogger.com,1999:blog-2145365503775784580.post-86163359710424582852010-12-08T14:59:00.000+01:002010-12-08T14:59:48.201+01:00Следующие номера ПФПРедакция журнала "Практика функционального программирования" ищет авторов статей для следующих выпусков журнала.<br />
Если вы хотите написать о применении ФП в своей работе, о новом языке программирования, о конкретном алгоритме, сделать перевод хорошей статьи, или написать еще о чем-то относящемся к ФП, то пришлите письмо на адрес <a href="mailto:ie@fprog.ru">ie@fprog.ru</a> с небольшим описанием того, о чем вы хотите написатьAlex Otthttp://www.blogger.com/profile/13001951608173211050noreply@blogger.com0tag:blogger.com,1999:blog-2145365503775784580.post-54422863715468573692010-11-30T13:52:00.000+01:002010-11-30T13:52:42.847+01:006-й номер журнала "Практика функционального программирования"После долгого перерыва вышел новый номер журнала "Практика функционального программирования". В новом номере опубликованы интервью с Саймоном Пейтон Джонсом и Джо Армстронгом, а также несколько интересных статей.<br />
Кроме того, выпущена бумажная версия журнала. Подробнее об этом, в <a href="http://community.livejournal.com/fprog/17124.html">официальном анонсе</a>!Alex Otthttp://www.blogger.com/profile/13001951608173211050noreply@blogger.com0tag:blogger.com,1999:blog-2145365503775784580.post-82752990122982542512010-10-07T14:52:00.000+01:002010-10-07T14:52:51.140+01:00Дайджест прочитанных книг. Сентябрь 2010<p>Мне пришла в голову идея, что было бы полезно делиться достаточно подробными впечатлениями о прочитанных книгах. Хотя я и пользуюсь <a href="http://www.goodreads.com/user/show/635213">GoodReads</a> и <a href="http://www.shelfari.com/alexott">Shelfari</a>, но обзоры там делаю на английском и достаточно краткие. В качестве периода между обзорами выбран месяц, что дает мне возможность прочитать 2-4 книги, про которые стоило бы рассказать :-)</p><hr><h4>The Joy of Clojure: Thinking the Clojure Way</h4><p class="first">Я купил <a href="http://www.amazon.com/gp/product/1935182641?ie=UTF8&tag=aleottshompag-20&linkCode=as2&camp=1789&creative=390957&creativeASIN=1935182641">The Joy of Clojure: Thinking the Clojure Way</a> (авторы Michael Fogus и Chris Houser) почти сразу после того, как она появилась на сайте Manning, и регулярно получал обновления для него. Но примерно месяц назад пришла полная версия книги (но без окончательной вычитки редактором и красивой верстки), и я сел за ее чтение в полном объеме. У этой книги имеется <a href="http://joyofclojure.com/">отдельный сайт</a> на котором можно найти дополнительную информацию о книге, включая информацию о существующих скидках на предварительную версию (MEAP).</p><p>Хочется сразу отметить, что это не учебник по языку Clojure, и хотя в книге имеется отдельная глава с кратким (около 30 страниц) описанием основ языка, но все равно, для начала стоит прочитать одну из существующих книг: <a href="http://www.amazon.com/gp/product/1430272317?ie=UTF8&tag=aleottshompag-20&linkCode=as2&camp=1789&creative=390957&creativeASIN=1430272317">Practical Clojure</a> или<br />
<a href="http://www.amazon.com/gp/product/1934356336?ie=UTF8&tag=aleottshompag-20&linkCode=as2&camp=1789&creative=390957&creativeASIN=1934356336">Programming Clojure</a>, или еще не выпущенную, но уже доступную через MEAP,<br />
<a href="http://www.manning.com/rathore/">Clojure in Action</a>.</p><p>Книга пытается рассказать о том, как "более правильно" программировать на Clojure с точки зрения стиля языка и функционального программирования, как лучше организовывать программы на Clojure. Сюда относятся использование "ленивых" структур данных, когда нужно и можно использовать макросы, как организовывать рекурсивное выполнение, как организованы различные структуры данных, когда их нужно и можно использовать, и т.п.</p><p>Также достаточно много места уделено вопросам производительности программ на Clojure — какие структуры данных лучше использовать в различных ситуациях, как можно улучшить производительность с помощью type hinting, использования "переходных" структур данных, "блочных" последовательностей и мемоизации.</p><p>Не обойден стороной и вопрос конкуррентного программирования на Clojure, и использование изменяемых данных в программах. Обсуждению этих вопросов посвящена 11-я глава книги, в которой обсуждается устройство изменяемых структур (refs/atoms/agents), когда их можно и нужно использовать, а также рассказывается про параллельное программирование на Clojure (futures, promises, локи и т.п.).</p><p>Кроме того, книга касается вопросов использования мультиметодов, протоколов и типов данных, введенных в Clojure 1.2, а также вопросов интеграции с JVM и Java. Но эти темы рассматриваются не настолько подробно, как остальные.</p><p><em>Вердикт</em>: эту книжку рекомендуется прочитать всем, кто уже познакомился с языком, но хочет изучить некоторые темы более подробно и/или хочет научиться "более правильно" программировать на этом языке. Я лично нашел достаточно много интересного материала, который начал применять в своих проектах.</p><h4>Lucene in Action, 2-е издание</h4><p class="first">Я давно собирался посмотреть на <a href="http://lucene.apache.org/">Lucene</a> для своих проектов, слышал про книгу Lucene in Action, но было много жалоб на то, что эта книга уже устарела и неприменима для свежих версий Lucene. Недавно вышедшее второе издание <a href="http://www.amazon.com/gp/product/1933988177?ie=UTF8&tag=aleottshompag-20&linkCode=as2&camp=1789&creative=390957&creativeASIN=1933988177">Lucene in Action</a> исправляет эту проблему.</p><p>Начинается книга (глава 1) с небольшого обзора Lucene и из чего она состоит, описываются основные этапы в жизненном цикле поиска — сбор документов, выделение информации, индексация, и сам поиск. Кроме того, в 1-й главе приведены небольшие, но законченные примеры того, как можно выполнять индексацию документов и затем использовать полученный индекс для поиска.</p><p>Первая часть книги (главы 2-6) посвящены подробному описанию того, как Lucene устроена, и как можно использовать ее возможности в приложениях. Глава 2 полностью посвящена вопросам индексации с описанием того, какие есть опции индексации, как они влияют на работу Lucene, включая производительность, как можно производить индексацию численных и временных (temporal) данных, как можно оптимизовывать и отлаживать процесс индексации.</p><p>Глава 3 описывает использование основных поисковых возможностей Lucene. Глава начинается с простого приложения, которое используется в качестве основы для остальных примеров. Сначала рассматривается использование <code>IndexSearch</code>, который используется для выполнения поиска, а затем уже рассматриваются основные виды запросов, реализованных в Lucene, и <code>QueryParser</code>.</p><p>Главы с 4-й по 6-ю посвящены "расширенным" темам, их можно пропустить при первом прочтении, если вам нужны только стандартные возможности Lucene. В 4-й главе описываются различные анализаторы текста, реализованные в Lucene и Nutch, а также показывается как можно реализовать новые анализаторы и/или расширять существующие. 5-я глава посвящена дополнительным возможностям поиска — запросам по нескольким полям и/или индексам, использовании векторов терминов (term vectors), сортировке результатов и т.п. А в 6-й главе рассказывается о том, как можно расширить возможности поиска путем реализации собственных методов сортировки, фильтров и "сборщиков" (collectors) документов.</p><p>Вторая часть книги (главы 7-11) рассказывает о том, как можно выделять текст с помощью библиотеки <a href="http://tika.apache.org/">Tika</a> (глава 7), какие существуют расширения для Lucene (главы 8-9), как можно использовать Lucene с языками, отличными от Java (глава 10), а 11-я глава рассматривает вопросы администрирования Lucene, и настройки производительности.</p><p>Третья часть книги полностью посвящена рассмотрению того, как Lucene применяется в реальных проектах (Kruge, SIREn, LinkedIn) и рассказывается про то, какие возможности Lucene они используют, как организован процесс индексации и поиска, какие расширения были добавлены для работы, и т.д.</p><p><em>Вердикт</em>: Большое количество примеров и подробное описание как делают эту книгу очень привлекательной для людей, которые начинают использовать Lucene. После ее прочтения, можно возвращаться к ней для получения ответов на вопросы, которые не описываются в официальной документации.</p><h4>Introduction to Algorithms</h4><p class="first">Эту книгу я уже читал много лет назад, в русском переводе (на русском она называется <a href="http://www.ozon.ru/context/detail/id/2429691/?partner=alexott">Алгоритмы. Построение и анализ</a>), но некоторое время назад мне захотелось обновить теоретические основы, и поэтому я решил перечитать эту книгу. В руки мне попало 2-е издание, а спустя буквально месяц вышло уже третье издание <a href="http://www.amazon.com/gp/product/0262033844?ie=UTF8&tag=aleottshompag-20&linkCode=as2&camp=1789&creative=390957&creativeASIN=0262033844">Introduction to Algorithms</a>, и я немного жалею, что не дождался его, поскольку там есть некоторые полезные темы.</p><p>Я не могу много написать об этой книге, иначе это будет ее пересказ :-) Лучше всего о ней говорит <a href="http://mitpress.mit.edu/catalog/item/default.asp?ttype=2&tid=11866&mode=toc">оглавление этой книги</a>.</p><p>Это классический учебник по алгоритмам и подходам к их анализу. Книга начинается с основ анализа алгоритмов, и затем переходит к рассмотрению различных алгоритмов и структур данных (списки, деревья, хеш-таблицы, кучи и т.д.). Для каждой из рассматриваемых тем приводится анализ сложности алгоритма, рассматриваются возможные варианты реализации структур данных и т.п. Достаточно много места посвящено алгоритмам над графами. Кроме базовых структур данных и алгоритмов, в книге рассматриваются некоторые "сложные" темы — биноминальные кучи, b-trees и т.п. Почти сотню страниц книги занимают приложения, в которых описывается весь математический аппарат, необходимый для чтения этой книги —<br />
теория множеств, основы теории вероятностей, и т.п.</p><p>Стоит также отметить, что на английском языке доступны <a href="http://videolectures.net/mit6046jf05_introduction_algorithms/">видео-записи лекций</a> по данному курсу которые читались в MIT (они также доступны через iTunesU).</p><p><em>Вердикт</em>: всем программистам читать обязательно, можно использовать как справочник, но первые главы нужно прочитать обязательно.</p>Alex Otthttp://www.blogger.com/profile/13001951608173211050noreply@blogger.com2tag:blogger.com,1999:blog-2145365503775784580.post-52180676891202128902010-09-16T12:25:00.001+01:002010-09-16T12:26:05.835+01:00Еще работа для функциональщиковНашел очередную <a href="http://altadata.ee/index.php?page=senior-quantitative-developers-team-leader&hl=ENG">вакансию для функциональных программистов</a>: ищут программистов на статически-типизированных функциональных языках - Haskell/OCaml/F#. И как всегда для такого набора языков - это около-финансовая компания - производные продукты и т.п.<br />
У них также есть <a href="http://altadata.ee/index.php?page=junior-quantitative-developers&hl=ENG">вакансия для начинающих программистов</a>.<br />
Компания находится в Таллине, Эстония. Если кого это заинтересовало, пишите им напрямуюAlex Otthttp://www.blogger.com/profile/13001951608173211050noreply@blogger.com3tag:blogger.com,1999:blog-2145365503775784580.post-57764172276350278102010-09-15T08:09:00.000+01:002010-09-15T08:09:22.820+01:00Вторая часть марлезонского балетаПочти через месяц после первой части, Антон (ака golodnyj) <a href="http://taop.rpod.ru/172639.html">выложил вторую часть подкаста</a> со мной, в которой рассказывается про язык Clojure.Alex Otthttp://www.blogger.com/profile/13001951608173211050noreply@blogger.com3tag:blogger.com,1999:blog-2145365503775784580.post-46614645942987416072010-08-19T16:52:00.003+01:002010-08-20T09:17:48.885+01:00Вышла Clojure 1.2После 8 месяцев напряженной работы, вышла новая версия языка Clojure - 1.2.<br />
В этой версии очень много изменений, из которых особо стоит отметить следующие:<br />
<ul><li>добавлены протоколы (<a href="http://clojure.org/protocols">protocols</a>) и типы данных (<a href="http://clojure.org/datatypes">datatypes</a>), позволяющие создавать новые абстракции и полиморфные функции. При этом производительность гораздо выше чем при использовании мультиметодов;</li>
<li>расширена деструктуризация структур данных, о которой я <a href="http://alexott-ru.blogspot.com/2010/08/clojure.html">уже писал</a>;</li>
<li>в составе языка введено несколько новых пространств имен, функции которых были перенесены из clojure-contrib. Сюда относятся функции для работы со строками, repl, pretty printer, ввод/вывод Java, и т.д.;</li>
<li>расширен набор функций для работы с последовательностями; </li>
<li>добавлена поддержка аннотаций Java, что позволяет использовать соответствующий функционал различных фреймворков;</li>
<li>много изменений, связанных с улучшением производительности кода;</li>
<li>для указания метаданных теперь вместо <span style="font-family: "Courier New",Courier,monospace;">#^</span> используется просто <span style="font-family: "Courier New",Courier,monospace;">^</span>. </li>
</ul>Полный список изменений <a href="http://github.com/clojure/clojure/blob/1.2.x/changes.txt">можно найти в репозитории языка</a>. Также полезной может быть <a href="http://fogus.me/static/preso/clj1.2+/">презентация Michael Fogus</a> о новых возможностях.<br />
<br />
P.S. я успел только частично обновить <a href="http://alexott.net/ru/clojure/clojure-intro/">Введение в Clojure</a> (это обновленная версия статьи из 4-го номера <a href="http://fprog.ru/">ПФП</a>) описанием функциональности из версии 1.2. Сейчас не хватает описания протоколов и типов данных. Я надеюсь, что допишу этот кусок за выходные, о чем сделаю отдельный анонсAlex Otthttp://www.blogger.com/profile/13001951608173211050noreply@blogger.com0tag:blogger.com,1999:blog-2145365503775784580.post-7939920680021458432010-08-17T12:35:00.000+01:002010-08-17T12:35:27.490+01:00ПодкастовоеДебютировал в <a href="http://taop.rpod.ru/168440.html">подкасте у golodnyj</a>. Это первая часть в которой мы общаемся на тему функционального программирования и лиспа. Вторая часть (через несколько дней) будет про язык Clojure...Alex Otthttp://www.blogger.com/profile/13001951608173211050noreply@blogger.com3tag:blogger.com,1999:blog-2145365503775784580.post-26674959119499086662010-08-11T15:28:00.003+01:002010-08-11T16:38:32.901+01:00Русская планета ClojureЯ сделал (пока с помощью Yahoo! Pipes) <a href="http://feeds.feedburner.com/RussianClojurePlanet">агрегатор русскоязычных блогов, посвященных Clojure</a>. Все заведено через feedburner, так что будущие изменения в хостинге не будут влиять на подписчиков. <br />
Если кто пишет про Clojure на русском - пишите мне, с ссылками на блог - я сразу добавлю.<br />
Update 1: Что-то Yahoo! Pipes выставляет неправильные ссылки на оригинальные посты - разбираюсь с ним<br />
Update 2: ПочинилAlex Otthttp://www.blogger.com/profile/13001951608173211050noreply@blogger.com8tag:blogger.com,1999:blog-2145365503775784580.post-58376992224274272702010-08-06T15:14:00.001+01:002010-08-06T16:42:47.329+01:00Деструктуризация параметров в Clojure<div class="first"><i>Это небольшое дополнение к статье про Clojure, которое я решил опубликовать отдельно. Эта часть будет добавлена в оригинальную статью, которая сейчас обновляется в предверии выхода Clojure версии 1.2.</i></div><hr /><div class="first">Если вы передаете сложные структуры данных в функции (<code>defn</code> или <code>fn</code>), или связываете значения с символами в <code>let</code>, то вы можете использовать встроенную в Clojure <a href="http://clojure.org/special_forms#Special%20Forms--%28let%20%5bbindings*%20%5d%20exprs*%29">деструктуризацию параметров</a>, что позволяет связывать части структур данных с символами. Это значительно упрощает (и сокращает) код, поскольку вам не нужно писать явный код для получения значения значений из массивов или отображений.</div>Существует две формы деструктуризации параметров — деструктуризация отображений, и деструктуризация векторов, строк и массивов. Деструктуризация векторов/массивов/строк имеет простую форму — вы помещаете список символов внутри вектора, и значения, стоящие на соответствующих местах в деструктурируемом объекте, будут связаны с этими символами. В том случае, если вы укажете меньше аргументов, чем указано символов, то отсутствующие значения будут рассматриваться как имеющие значение <code>nil</code>, если укажете больше, то они будут отброшены. Вы можете собрать "лишние" значения в отдельный список, используя запись <code>& символ</code>, и все "лишние" значения будут помещены в список, связанный с указанным символом. Вот примеры использования деструктуризации векторов и строк:<br />
<pre class="src">user> (<span style="color: #a020f0;">let</span> [ [a b] [1 2]]
(<span style="color: darkgreen;">list</span> a b))
(1 2)
user> (<span style="color: #a020f0;">let</span> [ [a b] [1]]
(<span style="color: darkgreen;">list</span> a b))
(1 nil)
user> (<span style="color: #a020f0;">let</span> [ [a b] [1 2 3 4]]
(<span style="color: darkgreen;">list</span> a b))
(1 2)
user> (<span style="color: #a020f0;">let</span> [ [a b & c] [1 2 3 4]]
(<span style="color: darkgreen;">list</span> a b c))
(1 2 (3 4))
user> (<span style="color: #a020f0;">let</span> [ [a b & c] <span style="color: #008b00;">"abcde"</span>]
(<span style="color: darkgreen;">list</span> a b c))
(\a \b (\c \d \e))
user> ((<span style="color: darkgreen;">fn</span> [ [a b] ] (<span style="color: darkgreen;">list</span> a b)) [1 2])
(1 2)
user> (<span style="color: #a020f0;">defn</span> <span style="color: blue;">dfunc1</span> [ [a b] ]
(<span style="color: darkgreen;">list</span> a b))
user> (dfunc1 [1 2])
(1 2)</pre>Деструктуризация отображений выглядит следующим образом — вы записываете отображение, в котором ключом является символ, с которым будет связано значение, а значением — является ключ в деструктурируемом отображении. Например,<br />
<pre class="src">user> (<span style="color: #a020f0;">let</span> [{a <span style="color: darkgreen;">:k1</span> b <span style="color: darkgreen;">:k2</span> c <span style="color: darkgreen;">:k3</span>} {<span style="color: darkgreen;">:k1</span> 1 <span style="color: darkgreen;">:k2</span> 2 <span style="color: darkgreen;">:k3</span> 3}]
(<span style="color: darkgreen;">list</span> a b c))
(1 2 3)
user> (<span style="color: #a020f0;">let</span> [{a <span style="color: darkgreen;">:k1</span> b <span style="color: darkgreen;">:k2</span> c <span style="color: darkgreen;">:k3</span>} {<span style="color: darkgreen;">:k1</span> 1 <span style="color: darkgreen;">:k3</span> 3}]
(<span style="color: darkgreen;">list</span> a b c))
(1 nil 3)</pre>Также как и в случае с деструктуризацией векторов, если конкретный ключ не был указан, то символ получает значение <code>nil</code>, как это видно во втором примере.<br />
Деструктуризация отображений может иметь более сложную форму, поскольку можно указывать еще и значения по умолчанию, которые будут присвоены соответствующим символам вместо <code>nil</code>, если нужный ключ не был указан в отображении. Это осуществляется путем указания ключевого символа <code>:or</code> и отображения, в котором перечисляются значения по умолчанию:<br />
<pre class="src">user> (<span style="color: #a020f0;">let</span> [{a <span style="color: darkgreen;">:a</span> b <span style="color: darkgreen;">:b</span> c <span style="color: darkgreen;">:c</span> <span style="color: darkgreen;">:or</span> {a 1 b 2 c 3}} {<span style="color: darkgreen;">:a</span> 4}]
(<span style="color: darkgreen;">list</span> a b c))
(4 2 3)</pre>Для того, чтобы не писать пары символ/ключ, имеется упрощенная форма записи, когда вы указываете ключевой символ <code>:keys</code> и вектор, содержащий список символов, которые будут превращены в ключевые слова с теми же самыми именами, и которые будут использоваться для поиска ключей в деструктурируемом отображении. Например, предыдущие примеры можно переписать в более компактной форме:<br />
<pre class="src">user> (<span style="color: #a020f0;">let</span> [{<span style="color: darkgreen;">:keys</span> [a b c]} {<span style="color: darkgreen;">:a</span> 1 <span style="color: darkgreen;">:b</span> 2 <span style="color: darkgreen;">:c</span> 3}]
(<span style="color: darkgreen;">list</span> a b c))
(1 2 3)
user> (<span style="color: #a020f0;">let</span> [{<span style="color: darkgreen;">:keys</span> [a b c]} {<span style="color: darkgreen;">:a</span> 1 <span style="color: darkgreen;">:c</span> 3}]
(<span style="color: darkgreen;">list</span> a b c))
(1 nil 3)</pre>Кроме ключевых символов, в качестве ключей отображений вы можете использовать строки и символы. Для этого нужно использовать ключевое слово <code>:strs</code> — для строк и <code>:syms</code> — для символов, как это показано в следующих примерах:<br />
<pre class="src">user> (<span style="color: #a020f0;">let</span> [{<span style="color: darkgreen;">:strs</span> [a b c] <span style="color: darkgreen;">:as</span> m <span style="color: darkgreen;">:or</span> {a 2 b 3}} {<span style="color: #008b00;">"a"</span> 5 <span style="color: #008b00;">"c"</span> 6}]
(<span style="color: darkgreen;">list</span> a b c m))
(5 3 6 {<span style="color: #008b00;">"a"</span> 5, <span style="color: #008b00;">"c"</span> 6})
user> (<span style="color: #a020f0;">let</span> [{<span style="color: darkgreen;">:syms</span> [a b c] <span style="color: darkgreen;">:as</span> m <span style="color: darkgreen;">:or</span> {a 2 b 3}} {'a 5 'b 6}]
(<span style="color: darkgreen;">list</span> a b c m))
(5 3 6 {<span style="color: #008b00;">"a"</span> 5, <span style="color: #008b00;">"c"</span> 6})</pre>Особенно полезна деструктуризация отображений для тех случаев, когда вы хотите иметь необязательные (и именованные) параметры в функциях. В этом случае, объявление функции будет иметь вид<br />
<pre class="src">(<span style="color: #7f007f;">defn</span> <span style="color: blue;">имя-функции</span> [обязательные параметры
& {<span style="color: #79378a;">:keys</span> [необязательные параметры]
<span style="color: #79378a;">:or</span> {значения по умолчанию}}]
тело функции)</pre>например,<br />
<pre class="src">user> (<span style="color: #7f007f;">defn</span> <span style="color: blue;">dfunc2</span> [a b & {<span style="color: #79378a;">:keys</span> [c d] <span style="color: #79378a;">:or</span> {c <span style="color: #8a2152;">"c"</span> d <span style="color: #8a2152;">"d"</span>}}]
(<span style="color: #79378a;">list</span> a b c d))
user> (dfunc2 1 2 <span style="color: #79378a;">:c</span> 3)
(1 2 3 <span style="color: #8a2152;">"d"</span>)</pre>Здесь мы определяем функцию, принимающую два обязательных параметра, и два необязательных, значения которых можно указывать после соответствующих ключевых символов. <br />
Деструктуризация — это полезный инструмент, но иногда необходимо получить все переданные параметры в неизменном виде. Для этого можно использовать ключевой символ <code>:as символ</code>, которая связывает указанный символ с оригинальными параметрами. Например:<br />
<pre class="src">user> (<span style="color: #a020f0;">let</span> [[a b <span style="color: darkgreen;">:as</span> c] [1 2 3]]
(<span style="color: darkgreen;">list</span> a b c))
(1 2 [1 2 3])
user> (<span style="color: #a020f0;">let</span> [{a <span style="color: darkgreen;">:a</span> b <span style="color: darkgreen;">:b</span> <span style="color: darkgreen;">:as</span> c} {<span style="color: darkgreen;">:a</span> 1 <span style="color: darkgreen;">:b</span> 2 <span style="color: darkgreen;">:c</span> 3}]
(<span style="color: darkgreen;">list</span> a b c))
(1 2 {<span style="color: darkgreen;">:a</span> 1, <span style="color: darkgreen;">:b</span> 2, <span style="color: darkgreen;">:c</span> 3})</pre>Также хочется отметить, деструктуризация может применяться и к вложенным структурам, например, если у вас есть вектор векторов, или вложенные отображения. Например,<br />
<pre class="src">user> (<span style="color: #a020f0;">let</span> [ [a [b c]] [1 [2 3]]]
(<span style="color: darkgreen;">list</span> a b c))
(1 2 3)
user> (<span style="color: #a020f0;">let</span> [ [a [b c]] [1 2]]
(<span style="color: darkgreen;">list</span> a b c))
Error....
user> (<span style="color: #a020f0;">let</span> [{a <span style="color: darkgreen;">:a</span> {c <span style="color: darkgreen;">:c</span> d <span style="color: darkgreen;">:d</span>} <span style="color: darkgreen;">:b</span>} {<span style="color: darkgreen;">:a</span> 1 <span style="color: darkgreen;">:b</span> {<span style="color: darkgreen;">:c</span> 3 <span style="color: darkgreen;">:d</span> 4}}]
(<span style="color: darkgreen;">list</span> a c d))
(1 3 4)</pre>Но тут стоит быть осторожным, поскольку если вместо вектора вы передадите объект несовместимого типа, то вы получите ошибку, как во втором примере.<br />
Дополнительные примеры вы можете найти <a href="http://paste.lisp.org/display/97057">на данной странице</a>. Также хорошее описание деструктуризации параметров можно найти в книге "Clojure in Action".Alex Otthttp://www.blogger.com/profile/13001951608173211050noreply@blogger.com0tag:blogger.com,1999:blog-2145365503775784580.post-59105351556814133622010-07-23T09:58:00.000+01:002010-07-23T09:58:53.161+01:00Статья про Clojure & HadoopНаконец-то закончил давно начатую и откладываемую с<a href="http://alexott.net/ru/clojure/ClojureHadoop.html">татью про использование Clojure для программирования Hadoop</a>. В статье описывается пакет <a href="http://groups.google.ru/group/clojure-russian?hl=ru">clojure-hadoop</a>, который позволяет сильно упростить программирование заданий для Hadoop. <br />
<br />
P.S. English version will follow after short time, that I need to make translation ;-)Alex Otthttp://www.blogger.com/profile/13001951608173211050noreply@blogger.com0