В свободное время я продолжаю (см один , два и три ) писать небольшие поделки на Erlang. Это занятие видится мне прекрасным способом изучения языка. Почти наверняка в этой заметке будет изрядное количество ляпов, ну да я надеюсь, что более опытные коллеги меня поправят.
Для установки сторонних библиотек в Perl используется утилита cpan, в Python — pip, в Haskell — cabal. В мире Erlang есть нечто подобное под названием Agner, но обычно все же используется rebar. В нем применяется другой подход, не такой, как в cpan или cabal. Идея заключается в том, чтобы указать ссылки на git-репозитории требуемых библиотек (кстати, не обязательно git) и перед сборкой приложения подтянуть исходники этих библиотек в каталог с кодом приложения.
Соответственно, поиск библиотек осуществляется с помощью поиска GitHub’а или какого-то другого хостинга проектов. Большинство, если не абсолютно все, Erlang-библиотеки хостятся именно на GitHub’е. По моему опыту Google ищет по GitHub’у лучше самого GitHub’а. Таким образом, библиотеки можно искать прямо в гугле по запросу site:github.com erlang ключевые слова
.
В общем, все это напоминает использование Maven из мира Java или, например, связку perlbrew, cpanm и Makefile.PL из мира Perl. Для меня этот подход не очень привычен, но отчего бы ему не иметь права на жизнь? Как минимум, Erlang-библиотеки хранятся как бы очень распределенно, а распределенность — это круто! Вон у программистов на C/C++ даже такого инструмента, кажется, нет, и ничего, живут ведь как-то. Может, менеджеры пакетов самой ОС используют?
Чтобы получить rebar, нужно собрать его из исходников:
cd rebar
make
Полученный исполняемый файл rebar можно положить в ~/bin, прописав этот путь в $PATH. Часто rebar кладут прямо в репозиторий с кодом проекта и создают Makefile-обертку вокруг него, чтобы проект можно было собрать и установить традиционным make && make install
.
Попробуем воспользоваться rebar на практике. Создадим новый Git-репозиторий.
Создадим новое приложение:
Затем добавим в репозиторий файл rebar.config следующего содержания:
{ require_otp_vsn , «R14|R15» } .
% куда складывать зависимости
{ lib_dirs , [ «deps» ] } .
% список зависимостей
{ deps , [
{ ibrowse , «.*» ,
{ git , «git://github.com/cmullaparthi/ibrowse.git» ,
{ tag , «v4.0.1» } } }
] } .
На самом деле rebar способен не только тянуть зависимости. Он также умеет прогонять модульные тесты, поддерживает хуки, плагины, и многое другое, так что rebar.config может быть намного сложнее. См например rebar.config.sample в репозитории rebar’а, а также список команд, поддерживаемых rebar’ом: rebar -c
.
Теперь создадим файл src/gsearch.erl:
— export ( [ main / 0 , main / 1 ] ) .
— include ( «deps/ibrowse/include/ibrowse.hrl» ) .
main ( List ) ->
Query = lists : foldl (
fun ( X , Sum ) ->
Sum ++ » » ++ atom_to_list ( X )
end , «» , List ) ,
EncodedQuery = http_ur i : encode ( Query ) ,
SearchUrl = «http://www.google.com/search?q=» ++ EncodedQuery ,
io : format ( «Fetching ~s …~n» , [ SearchUrl ] ) ,
ibrowse: start ( ) ,
case ibrowse: send_req ( SearchUrl , [ ] , get ) of
{ ok , «200» , _Headers , Data } ->
parse_serp ( Data ) ;
Rslt ->
io : format ( «Request failed: ~p~n» , [ Rslt ] )
end .
main ( ) ->
io : format ( «Usage: gsearch query~n» ) .
parse_serp ( Data ) ->
Regex = «<a href= » /url \ ?q=(.*?)&sa=U»»
case re : run ( Data Regex [ global