tag:blogger.com,1999:blog-21453655037757845802024-03-10T18:49:05.665+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.comBlogger352125tag:blogger.com,1999:blog-2145365503775784580.post-4448577433432294922016-06-01T20:47:00.001+01:002016-06-02T19:28:14.340+01:00Заметки о практическом машинном обученииДанный пост описывает мои личные наблюдения собранные во время работы над практической реализации задач решаемых при помощи машинного обучения (machine learning, ML). Данный топик всегда интересовал меня, наряду с другими областями, такими как обработка естественного языка (natural language processing, NLP), data mining, и имеющих к ним некоторое отношение технологий big data. Хотя я имею некоторый теоретический бэкграунд, достаточный для понимания применимости того или иного алгоритма, но все эти области интересуют меня в первую очередь с практической точки зрения.<br />
<br />
Первый опыт практического применения машинного обучения я получил 2002-2003 годах, после выхода статьи Paul Graham <a href="http://www.paulgraham.com/spam.html">Plan for Spam</a>, которая описывала простой алгоритм для классификации спамерских почтовых сообщений. Простота алгоритма сподвигнула нашу группу, работающую над продуктом для фильтрации почтового трафика "<a href="http://www.jet.msk.su/services_and_solutions/information_security/products_vendor/dozor_dzhet/">Дозор-Джет</a>, на написание соответствующего модуля для нашей системы. При реализации этого модуля мы первый раз наткнулись на тот факт, что основная сложность и трудоемкость системы не в алгоритме, а в сопутствующих вещах - собирании и очистке данных для тренировки моделей, анализе результатов, исправлении фальшивых срабатываний и т.п.<br />
<br />
Позже, когда я стал работать в McAfee/Intel Security, я продолжал эксперементировать с различными алгоритмами и библиотеками, плюс получил большие теоретические знания благодаря онлайн курсам: <a href="http://ml-class.org/">ML Class</a> (Andrew Ng) & <a href="http://ai-class.org/">AI Class</a> (Peter Norwig & Sebastian Thrun), плюс последующие классы на Coursera. 2 года назад я перешел в новую группу, которая работает над применением технологий машинного обучения для задач информационной безопасности, что позволило мне получить больше практического опыта в этой области. На основании этого опыта, я и решил написать этот пост.<br />
<h3 id="orgc3ace22">
Как получить хорошие результаты при использовании машинного обучения</h3>
Результат применения методов машинного обучения к различным задачам зависит от многих факторов, включая:<br />
<ul class="org-ul">
<li><b>Понимание того, какую проблему мы хотим решить</b>. Это достаточно важный пункт - зная о том, какую задачу мы хотим решить, мы имеем информацию об ограничениях накладываемых на конкретные алгоритмы (потребление ресурсов, скорость работы, и т.п.), понимаем насколько критичны ошибки при применении алгоритма, как решение задачи влияет на наш бизнес, и т.д. Часто, "достаточно хорошее", но дешевое решение может быть предпочтительней "наилучшего", но очень дорогого с точки зрения разработки, ресурсов и т.п. (хороший пример этого - история Netflix prize, когда <a href="https://www.techdirt.com/blog/innovation/articles/20120409/03412518422/why-netflix-never-implemented-algorithm-that-won-netflix-1-million-challenge.shtml">выигравший алгоритм так и не был реализован, а компания остановился на чуть-чуть худшем решении которое было дешевле в реализации</a>);</li>
<li><b>Хорошее знание предметной области</b>. На мой взгляд - это важнейший фактор успеха проекта. Без знания предметной области очень трудно (если вообще возможно) построить хорошую модель. Хорошее знание предметной области позволяет сконцентрироваться на ключевых факторах (или их комбинациях) на базе которых будет построена модель, игнорировать ненужные данные, использование которых не даст выигрыша в качестве (или вообще приведет к деградации качества), выбрать правильные методы сбора, извлечения и кодирования данных, оценить применимость того или иного алгоритма, и т.п.;</li>
<li><b>Наличие хорошей таксономии для задач классификации</b>. В таких задачах необходимо отнести входные данные (текст, или что-то другое) к одному (или нескольким) предопределенным классам. В некоторых случаях, таксономии уже определены, и в задачу проекта может входить построение решения которое будет использовать эту таксономию. И иногда, существующие таксономии не совсем удобно применять с алгоритмами машинного обучения. Например, если имеется несколько "близких" друг к другу классификаций - в этом случае, алгоритмы классификации делают ошибки относя входные данные к "родственным" классам, хотя это не всегда правильно. Например, если вы имеете класс "Спорт" и класс "Азартные игры", может быть достаточно тяжело различить сайты которые обсуждают результаты футбольных матчей от сайтов которые дают советы по ставкам на футбольные матчи;</li>
<li><b>Понимание применимости того или иного алгоритма к классу задач</b>. Сейчас не нужно быть кандидатом наук для применения машинного обучения в практиеческих задачх. Но необходимо иметь понимание того, какие классы алгоритмов существуют, к каким задачам они могут применяться, требования к ресурсам, чувствительность к качеству тренировочных данных, и т.д. (В настоящее время существует огромное количество информации на эту тему - онлайн курсы, книги, документация к библиотекам и т.д., так что это только вопрос времени на ознакомление). Очень часто, наилучший результат приносят не индивидуальные алгоритмы, а алгоритмы основанные на ансамблях из разных моделей, каждая из которых сама по себе дает "средний" результат, например, Random Forest, различные реализации Boosted Trees, и т.д.;</li>
<li><b>Применяемые методы сбора, извлечения и кодирования данных</b>. <b>Чистота и баланс данных</b>. Для разных задач существуют различные методы сбора данных, но основная цель - получить качественный набор тренировочных данных, по возможности не содержащих некоректные данные (хотя это очень дорогое удовольствие для больших объемов данных). В некоторых случаях, при сборе данных необходимо также соблюдать баланс, чтобы объем данных одного класса не превосходил объем данных других классов (хотя существуют некоторые методы решения этой проблемы при построении моделей);</li>
<li><b>Выделение ключевых факторов на базе которых будет построена модель</b>. Также крайне важный фактор влияющий на качество модели - включение лишних факторов в модель может ухудшить ее качество или увеличить потребление ресурсов при построении модели. Также важную роль часто играет применение не индивидуальных факторов, а комбинаций разных независимых факторов;</li>
<li><b>Отсутствие разделения на "разработчиков" и "ученых"</b>. Это больше организационный фактор, но он также важен. Иногда бывает, когда "ученые" и "разрабочики" относятся к совершенно разным группам, имеющим очень слабую связь. В таких случаях, при реализации проекта иногда возникает ситуация, когда "ученые" решают в пользу того или иного алгоритма, которые показывает очень хорошие результаты в лабораторых условиях, но который очень тяжело применять в реальной обстановке. Например, он очень требователен к ресурсам, тяжел в реализации, очень медленный и т.д. Лучше избегать такого разделения и позволить всем группам вместе работать над проектом с самого начала.</li>
</ul>
<h3 id="orgdcc8ede">
Машинное обучение: теория и практика…</h3>
Многие люди, не знакомые близко с машинным обучением, когда слышат этот термин, представляют себе листы бумаги исписанные формулами, какой-нибудь заумный код, и т.п. В реальности же, основная трудоемкость таких проектов часто приходится не на реализацию алгоритмов (существует огромное количество готовых библиотек), а на аналитические и инженерные задачи:<br />
<ul class="org-ul">
<li><b>сбор и проверка данных</b>. Это одна из самых трудоемких частей. Для этих задач существуют готовые библиотеки и утилиты, но все равно, иногда возникает необходимость в написании чего-то специального. После сбора данных, необходимо убедиться в том что мы действительно собрали правильные данные. Например, если вы занимаетесь классификацией веб страниц, то может возникнуть ситуация, когда содержимое сайта не соотвествует той классификации которая была ему когда-то присвоена - ПО сайта может возвращать сообщение об ошибке, сайт может сменить владельца, он может быть хакнут и помимо нормального содержимого он будет содержать какой-то другой текст (например, рекламу виагры, или порно-сайтов). Для проверки данных часто возникает необходимость в написании специализированных утилит, кросс-проверке данных и т.п.;</li>
<li><b>анализ и выбор факторов (features) которые войдут в модель</b>. Это одна из самых важных частей работы - необходимо понять, какие из факторов являются основными для получения качественных моделей. Для этого необходимо хорошо понимать предметную область, поскольку зачастую качество моделей зависит не от единичных факторов, а, например, от их комбинаций. Для некоторых областей, таких как классификация текстов, часто необходимо выполнить и выбор факторов (feature selection) (для классификации текстов - это слова в тексте), иначе модель будет слишком большая, что приведет к увеличенному потреблению ресурсов и замедлениям при тренировке моделей;</li>
<li><b>извлечение данных</b> - как мы выделяем нужные нам факторы. Например, при работе с текстовыми данными, нам может быть необходимо привести все входные данные к одной и той же кодировке, или необходимо выделить только определенную часть данных. Например, при анализе почтового трафика в поисках спама, мы можем игнорировать некоторые заголовки;</li>
<li><b>анализ полученных результатов</b> - еще одна трудоемкая часть. Существуют разные методы оценки качества моделей, зависящие от типа: классификация, кластеризация и т.п., но основная работа приходится на то чтобы понять откуда возникают фальшивые срабатывания и т.п. По результатам анализа может понадобиться настройка параметров моделей, изменение набора тренинговых данных, анализ влияния различных факторов и т.п.;</li>
<li><b>настройка параметров модели</b>. Многие алгоритмы имеют набор параметров которые могут влиять на качество моделей. Нет универсального набора параметров который бы подходил ко всем задачам, поэтому обычно производят построение моделей для диапазонов значений, и выбирают параметры приведшие к построению наилучшей модели. Остальные модели тоже могут принести пользу - например, все построенные модели могут использоваться для построения мета-модели, которая позволит получить лучшее качество чем одна модель;</li>
<li><b>деплоймент моделей в эксплуатацию</b>. Сюда входит: обеспечение беспрерывной работы системы, проверку результатов на реальных данных и т.п.</li>
</ul>
На практике, лишь в небольшом количестве проектов возникает необходимость в новых алгоритмах или реализации существующих алгоритмов с нуля. В большинстве своем, практически всегда используются уже готовые библиотеки и фреймворки, такие как <a href="http://scikit-learn.org/">Scikit-Learn</a> для Python, <a href="https://mahout.apache.org/">Apache Mahout</a>, <a href="http://spark.apache.org/docs/latest/mllib-guide.html">Apache Spark ML</a>, <a href="http://www.h2o.ai/">H2O</a>, <a href="https://github.com/dmlc/xgboost">XGBoost</a>, библиотеки для R, и многие другие - эти библиотеки разрабатываются большими коллективами, протестированны для разных задач, и большая часть ошибок уже исправлена. Имея на руках готовые данные, и понимая применимость того или иногда алгоритма, с помощью этих библиотек можно быстро построить модели, оценить их применимость к вашей задаче, и принять решение о реализации.<br />
<br />
Мои впечатления на эту тему совпадают с фразой и иллюстрацией из интересной статьи <a href="https://papers.nips.cc/paper/5656-hidden-technical-debt-in-machine-learning-systems">Hidden Technical Debt in Machine Learning Systems</a> опубликованной сотрудниками Google: "It may be surprising to the academic community to know that only a tiny fraction of the code in many ML systems is actually devoted to learning or prediction (Для научных сотрудников может быть удивительным, что только мала часть кода во многих системах построенных на алгоритмах машинного обучения, в действительности относится к обучению или предсказанию)".<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEil6ZWMBWdiUqtJTPTJvXZuGok-ZEdTtVZcc1ZvBb3mSD5Xgh_BUFV_jtpMX7O9zVwZ6ah4VilDfJa7g9KQdqEeZJSOhwapz6Iq3OgfQy_6nPTrxFCIZ-oJxXs7gI9lBoXspMV8_l2Q2F4/s1600/ml-system.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="209" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEil6ZWMBWdiUqtJTPTJvXZuGok-ZEdTtVZcc1ZvBb3mSD5Xgh_BUFV_jtpMX7O9zVwZ6ah4VilDfJa7g9KQdqEeZJSOhwapz6Iq3OgfQy_6nPTrxFCIZ-oJxXs7gI9lBoXspMV8_l2Q2F4/s640/ml-system.png" width="640" /></a></div>
<br />
<h3 id="org6143bde" style="text-align: center;">
* * *</h3>
В данном посте я пытался сформулировать свой опыт полученный при реализации конкретных проектов. В следующих постах я попытаюсь раскрыть те или иные пункты более подробно (насколько это не противоречит моему рабочему контракту :-). Я буду очень благодарен комментариям от моих читателей - может быть что-то описано не совсем ясно, тогда я постараюсь дополнить этот пост.Alex Otthttp://www.blogger.com/profile/13001951608173211050noreply@blogger.com9tag:blogger.com,1999:blog-2145365503775784580.post-5659937939186820802013-01-11T09:40:00.001+01:002013-01-11T10:40:17.995+01:00Готовится перевод "Clojure Programming"Издательство "ДМК-Пресс" продолжает серию переводов книг про новые языки программирования, и следующая вещь в списке - "Clojure Programming". Перевод уже начался, и они ищут людей которые помогут с технической вычиткой перевода. Если кому-то интересно, то пишите на dm at dmk-press.ru.Alex Otthttp://www.blogger.com/profile/13001951608173211050noreply@blogger.com2tag: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-4958515514685650492012-10-30T19:11:00.001+01:002012-10-30T19:39:42.455+01:00Новая версия статьи про CEDETТолько что залил на сайт новую версию своей <a href="http://alexott.net/ru/writings/emacs-devenv/EmacsCedet.html">статьи про настройку CEDET</a>. Я также оставил доступной <a href="http://alexott.net/ru/writings/emacs-devenv/EmacsCedetOld.html">старую версию статьи</a>, но в виде отдельной страницы.<br />
Новая версия описывает новую схему расположения исходного кода, а также новый способ активации под-режимов, так что статья теперь применима и к версии из bzr, и к версии идущей в составе GNU Emacs (после того как выпустят новую его версию).<br />
Кроме того, я добавил небольшое описание того, как настроить связку CEDET + Java, а также небольшое описание настройки дополнений через auto-complete.<br />
<br />
Вместо моего конфига, который очень уж сильно замусорен, теперь лучше воспользоваться <a href="https://gist.github.com/3930120">отдельным конфигом</a>.<br />
<br />
P.S. кстати, в последних снапшотах, CEDET умеет находить проекты Maven, и получать информацию о classpath прямо из них, так что теперь работает и дополнение имен для классов из сторонних библиотек. Например, вот так (Это дополнение при работе с кодом Apache Tika):<br />
<table style="width:auto;"><tr><td><a href="https://picasaweb.google.com/lh/photo/tFFmyk0aLM8ApIUjHRoBptMTjNZETYmyPJy0liipFm0?feat=embedwebsite"><img src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhpJbsS1J3d45Rr65w8ZEXd9RFpWCGWvIdDUXHJ6srpfH0hkXfnZDkNSICebxVDwRJ_OAZpdHAcdet-VlBFV8cZUm6p2PvwKeDWosNukussvvi5S-TljA2dxWIDHu5GTUiv5G9gcuVqusM/s400/OutlookExtractor.java_002.png" height="268" width="400" /></a></td></tr></table>
<br /><br />
P.P.S. If you found error, or typo - please write comment on page, or fork <a href="https://github.com/alexott/alexott.github.com">source code on github</a> (it's enough to fix only .muse file), and create pull request :-)Alex Otthttp://www.blogger.com/profile/13001951608173211050noreply@blogger.com26tag: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-54694247863516252822012-06-10T13:56:00.003+01:002012-06-10T17:05:57.242+01:00Вышел GNU Emacs 24.1!После длительной разработки, была выпущена новая версия GNU Emacs - 24.1. Среди основных изменений в данной версии можно отметить следующие:<br />
<ul>
<li>система пакетов, которая позволяет скачивать и устанавливать пакеты из внешних источников - как официальных, так и сторонних</li>
<li>поддержка отображения и редактирования текстов на языках, где текст пишется справа-налево</li>
<li> поддержка lexical scoping в Emacs Lisp</li>
<li>улучшения в системе дополнений (completion) - большинство пакетов теперь используют одинаковый метод показа дополнений</li>
<li>встроенная поддержка тем оформления </li>
<li>улучшения в интеграции с внешними библиотеками - GTK+3, ImageMagic, GNU TLS, etc.</li>
</ul>
Более подробную информацию можно найти в поставке GNU Emacs (файл <a href="http://www.gnu.org/software/emacs/NEWS.24.1">etc/NEWS</a>) и в статьях, перечисленных на <a href="http://wikemacs.org/wiki/GNU_Emacs_24">странице wikemacs</a>.Alex Otthttp://www.blogger.com/profile/13001951608173211050noreply@blogger.com4tag:blogger.com,1999:blog-2145365503775784580.post-80430594564229703562012-06-03T17:17:00.004+01:002012-06-03T17:22:47.425+01:00Впечатления о курсе "Natural Language Processing"Продолжая традицию постоянного обучения, я не смог не пройти мимо еще одного из курсов предлагаемых <a href="https://www.coursera.org/">Coursera</a>. После курсов прошедших прошлой осенью, у меня осталось очень хорошее впечатление о них. Среди большого набора новых курсов я выбрал курс <a href="https://www.coursera.org/course/nlp">Natural Language Processing</a> (NLP) - та тема, которая меня давно интересовала. А на этой неделе я наконец-то получил сертификат об окончании этого курса, и решил написать по свежим следам...<br />
Курс длится 8 недель и преподается двумя известными специлистами в этой области - Dan Jurafsky & Christopher Manning (оба из университета Stanford). В качестве основы для курса взяты две книги: <a href="http://www.amazon.com/gp/product/0131873210/ref=as_li_ss_tl?ie=UTF8&tag=aleottshompag-20&linkCode=as2&camp=1789&creative=390957&creativeASIN=0131873210">Speech & Language Processing, 2ed</a> и <a href="http://www.amazon.com/gp/product/0521865719/ref=as_li_ss_tl?ie=UTF8&tag=aleottshompag-20&linkCode=as2&camp=1789&creative=390957&creativeASIN=0521865719">Introduction to Information Retrieval</a> (можно найти и онлайн-версии обоих книг - в виде последних снапшотов перед отравкой в издательство). Так получилось, что обе книги у меня уже были достаточно давно, но все не доходили руки сесть за их чтение. Хочется отметить, что читать книги все-таки требовалось, чтобы лучше понять то, что объяснялось в лекциях.<br />
Каждую неделю необходимо было прослушать примерно 2 часа лекций, ответить на набор вопросов, и выполнить домашнее задание (в виде программы). В качестве языка программирования можно было использовать Java или Python - каждую неделю публиковалось новое задание, которое содержало заготовку кода, куда надо было вписать свое решение. Одним из отличий от осенних курсов было то, что на выполнение заданий отводилось больше времени - две недели (эти сроки иногда увеличивались - в зависимости от сложности задания и технических проблем).<br />
Первые три недели были достаточно простыми - разбирали использование регулярных выражений для NLP, моделирование языков, spell correction и классификацию текстов с помощью Naive Bayes - задания выполнялись достаточно быстро.<br />
А вот недели 4-6 были достаточно сложными - рассматривались maximum entropy модели, вычленение именованных объектов и отношений между ними, part of speech tagging, а также вероятностный парсинг текста. 5-е и 6-е задания были самыми сложными в этом курсе (стоит отметить, что много народу просто пропустило 6-ю домашнюю работу) - необходимо было уметь программировать на достаточно хорошем уровне. Но зато было очень интересно смотреть как твоя программа выдает корректную структуру даже для очень сложных предложений с правильно присвоенными частями речи.<br />
7-е задание было очень легким - надо было запрограммировать индексирование текста и вычисление tf-idf. А вот 8-е, хоть и казалось несложным, но требовало достаточно много времени для доводки регулярных выражений, которые должны были извлекать кусочки информации из входных данных. Времени к сожалению было не особо много, так что я сдал первый работающий вариант, за который получил около 70% от макс. оценки.<br />
В итоге, после прохождения всего курса, я набрал 93% от макс. кол-ва баллов. Также вспомнил/научился как программировать на питоне - языке на котором я писал очень редко, а в основном читал код. И даже применил новые знание на практике, соорудив категоризатор текста на базе HBase/Clojure/Hadoop в виде эксперементального модуля для нашего продукта.<br />
<br />
Так что если вам интересны вопросы information retrieval/natural language processing - я очень рекомендую этот курс - он дает очень хорошее представление об этих областях и формирует основу для дальнейшего изучения.<br />
<br />Alex Otthttp://www.blogger.com/profile/13001951608173211050noreply@blogger.com6tag: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-71312148596033519582011-12-31T16:27:00.000+01:002011-12-31T16:27:24.668+01:00Итоги года...Сейчас самое подвести итоги уходящего года, и посмотреть вперед - 2011-й год был достаточно насыщеным, свободного времени практически не было....<br />
<br />
<ul><li>получил повышение до Principal разработчика, что добавило задач, но проекты были интересными, и будут новые</li>
<li>достаточно много ездил - в другие страны (<a href="https://picasaweb.google.com/106643849267592516873/2011England">англия</a>, <a href="https://picasaweb.google.com/106643849267592516873/2011Keukenhof">голландия</a>, канарские острова) и в германии (<a href="https://picasaweb.google.com/106643849267592516873/2011Rhein">по рейну</a>, <a href="https://picasaweb.google.com/106643849267592516873/11112011CarnivalAtCologne">в Кельн на карнавал</a>, и т.д.)</li>
<li>накатал 2000км на велосипеде, хотя это меньше чем я планировал</li>
<li>достаточно много "книжных" проектов - работал с Manning над "Mahout in Action" & "Tika in Action", наконец-то <a href="http://alexott-ru.blogspot.com/2011/10/blog-post.html">вышел перевод TaPL</a> в его окончательном варианте</li>
<li>в части open source активность была не особо высокой - обычно в виде небольших патчей для разных проектов</li>
<li>для статей тоже не особо много времени находилось - написал только статью про <a href="http://alexott.net/en/cpp/CppTestingIntro.html">TDD & Unit testing in C++</a>, и вместе с <a href="http://my-clojure.blogspot.com/">Дмитрием Бушенко</a>, написали <a href="https://docs.google.com/open?id=0BzmL7xzGeOtOOWE1ZTc3NzAtZjkyNy00ZDU5LTg2Y2UtZDc4MmNkNTI1ZmJl">небольшое пособие про Emacs</a>, которое мы планируем в следующем году значительно расширить информацией про CEDET/Semantic для Java и т.п.</li>
<li><a href="http://www.goodreads.com/user_challenges/21521">много читал</a>, в основном техническую литературу</li>
<li><a href="http://alexott-ru.blogspot.com/2011/12/blog-post.html">учился</a> в двух стенфордских классах, что доставило очень большое удовольствие и позволило многому научиться</li>
</ul><div><br />
</div><div>В следующем году продолжу разбираться с темами, которые мне интересны - machine learning, natural language processing (в том числе возьму и <a href="http://www.nlp-class.org/">стенфордский класс на эту тему</a>), постараюсь больше писать на разные темы, и более активно учавствовать в open source проектах. И проехать 3000км на велосипеде (надо только его проапгрейдить до шоссейника)...</div><div><br />
</div><div>И хочу поздравить всех моих читателей с Новым, 2012-м годом - пусть он будет успешным и интересным для вас!</div>Alex Otthttp://www.blogger.com/profile/13001951608173211050noreply@blogger.com7tag:blogger.com,1999:blog-2145365503775784580.post-45565895366682360332011-12-23T19:52:00.003+01:002011-12-23T20:14:12.988+01:00Про Стэнфордские курсы...Я как и многие мои знакомые, учавствовал в экспериментальных учебных курсах предложенных Стэнфордским университетом. В виду <strike>патологической жадности</strike> любви к учебе, записался сразу на два курса <a href="http://www.ai-class.com/">Artificial Intelligence (AI)</a> & <a href="http://www.ml-class.org/">Machine Leaning (ML)</a>, оба на advanced track, что предполагало делание домашних заданий в дополнение к вопросам в ходе лекций. Вчера я получил свой сертификат для AI - 89%, чему я с одной стороны рад, поскольку я смог это сделать, с другой стороны - корю себя за невнимательность и несобранность - было сделано достаточно много глупых ошибок. Сертификат по ML скорее всего придет на той неделе.<br />
Я собирался написать про свои впечатления об обоих курсах, но Lev Walkin меня опередил <a href="http://lionet.livejournal.com/99296.html">отличных постом</a> в своем журнале. Мои впечатления полностью совпадают с тем, что он написал - возможность получения немедленного feedback на ML-курсе, позволила гораздо лучше запомнить материал по сравнению с тем что давали на AI. Но стоит отметить, что AI тоже не прошел даром - обзорные лекции по разным темам дали возможность на них посмотреть чуть ближе, и понять что из них будет интересно и применимо.<br />
Оба курса были также хорошей возможностью чуть лучше сконцентрироваться на определенных темах, поскольку домашние работы надо было выполнять в срок. Плюс это дало возможность наконец-то почитать давно купленные книги, например, Artificial Intelligence: A Modern Approach (у меня 2-е, русское издание), купленное много лет назад, и иногда доставаемое с полки для чтения какой-то главы :-)<br />
<br />
А в конце января, начнется новая серия курсов, я скорее всего возьму только один - <a href="http://www.nlp-class.org/">Natural Language Processing</a> (так что я достану из загашников еще пару книжек :-), хотя хочется взять половину из новых курсов, даже 2 курса одновременно - это достаточно затратно по времени, так что буду надеяться что все курсы будут оставаться в открытом доступе и в дальнейшем (по крайней мере, курс по ML будет повторен и в новом семестре).Alex Otthttp://www.blogger.com/profile/13001951608173211050noreply@blogger.com3tag: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-85614763234014953992011-10-22T14:12:00.000+01:002011-10-22T14:12:12.330+01:00Еще книжное...Осень выдается достаточно результативной на книги, к которым я имею отношение в той или иной мере... Кроме релиза про перевод Types & programming languages, про который я писал <a href="http://alexott-ru.blogspot.com/2011/10/blog-post.html">вчера</a>, сегодня я получил свой экземпляр книги <a href="http://www.manning.com/owen/">Mahout in Action</a>, в издании которой я принимал участие в качестве technical proofreader. В том же качестве я поработал и над книгой <a href="http://www.manning.com/mattmann/">Tika in Action</a>, которая должна выйти в ближайшее время. А началось все с того, что люди из Manning предложили мне сделать review для нескольких книг, часть из которых я уже купил как MEAP, а потом предложили сделать и technical proofreading - проверить примеры, формулы и т.п., что и было с удовольствием сделано - все равно я собирался читать эту книгу, а тут такая возможность :-)<br />
<br />
<br />
Mahout in Action - интересная книга, если вы интересуетесь machine learning, особенно в large scale. В книжке почти нет теории, но в ней подробно описывается как использовать <a href="http://mahout.apache.org/">Apache Mahout</a> для классификации и кластеризации данных, а также рекомендаций (для товаров и т.п.). В книге описаны только основные алгоритмы, в самом Mahout их гораздо больше, и все больше добавляется с каждым релизом.<br />
В электронной версии (в PDF) есть мультимедийные вставки, с помощью которых рассказывают или показывают про сложные места - интересно сделано. На <a href="http://www.amazon.com/gp/product/1935182684?ie=UTF8&tag=aleottshompag-20&linkCode=shr&camp=213733&creative=393185&creativeASIN=1935182684&ref_=sr_1_1&qid=1319288354&sr=8-1">амазоне, печатная книга стоит дешевле</a> чем у <a href="http://www.manning.com/owen/">Manning</a>'а, но у Manning'а вместе с печатной версией дают и электронную - это у них стандартные условия, плюс регулярно бывают 40-50% скидки - если кому интересно. Все примеры были протестированы на Mahout версии 0.5 (актуальный релиз), но я планирую в ближайшее время <a href="https://github.com/tdunning/MiA">сделать их</a> совместимыми со следующим релизом - 0.6 - там совсем небольшое изменение...<br />
<br />
P.S. будет еще несколько книг, но уже на русском, но я пока не знаю еще точных сроков выхода, но обязательно напишу :-)Alex Otthttp://www.blogger.com/profile/13001951608173211050noreply@blogger.com6tag: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-35033960433558040622011-04-05T08:50:00.001+01:002011-04-05T10:43:14.663+01:00Реклама в журнале "Практика функционального программирования"Может быть это заинтересует кого-то из моих читателей - вы можете разместить свои вакансии (или другую рекламу) в журнале "Практика функционального программирования". Преимуществом такой рекламы является достаточно большая аудитория разработчиков ПО, которые, как мне кажется, имеют хороший уровень образования. Подробности <a href="http://community.livejournal.com/fprog/20291.html">тут</a>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-90060378875302323622010-12-21T11:57:00.000+01:002010-12-21T11:57:38.102+01:00Переехал на el-getЯ достаточно долгое время таскал с собой все используемые пакеты для Емакса, вместе с конфигурационными файлами - это позволяло мне иметь везде одинаковую рабочую среду. Большая часть используемых пакетов бралась прямо из репозиториев и регулярно обновлялась с помощью набор шельных скриптов.<br />
Но некоторое время назад я наткнулся на проект <a href="https://github.com/dimitri/el-get">el-get</a>, который берет на себя вопросы скачивания и обновления пакетов, и делает это прямо из емакса. Основное удобство заключается в том, что в составе el-get имеется большое количество готовых конфигурационных файлов (рецептов) для самых разных пакетов, и вы можете сразу использовать их в своей конфигурации.<br />
Использование el-get очень просто - вы определяет список пакетов, которые вы хотите использовать, а затем вызываете функцию <span style="font-family: "Courier New",Courier,monospace;">(el-get)</span>, которая выкачивает пакет, компилирует его в соответствии с инструкциями, и загружает нужные части, так что пакет становится доступным для использования. Подробности использования можно найти в описании проекта.<br />
Неделю назад я наконец-то собрался с духом, и перевел свою <a href="https://github.com/alexott/emacs-configs">рабочую конфигурацию</a> на el-get (я пока использую <a href="https://github.com/alexott/el-get">свой форк проекта</a>, хотя многие из рецептов уже внесены в основной проект), пришлось правда добавить рецептов которых еще не было в репозитории, и немного повозиться со сборкой на Mac OS X. Но в остальном - все работает нормально.Alex Otthttp://www.blogger.com/profile/13001951608173211050noreply@blogger.com17