├── .gitignore ├── ErlangHandbook-RU.tex ├── ErlangHandbook.tex ├── Makefile ├── README-RU.md ├── README.md ├── chapters-RU ├── 01-background.tex ├── 02-structure-of-an-erlang-program.tex ├── 03-data-types.tex ├── 04-pattern-matching.tex ├── 05-functions.tex ├── 06-processes.tex ├── 07-error-handling.tex ├── 08-distributed-erlang.tex ├── 09-ports-and-port-drivers.tex ├── 10-code-loading.tex ├── 11-macros.tex └── 12-further-reading.tex ├── chapters ├── 01-background.tex ├── 02-structure-of-an-erlang-program.tex ├── 03-data-types.tex ├── 04-pattern-matching.tex ├── 05-functions.tex ├── 06-processes.tex ├── 07-error-handling.tex ├── 08-distributed-erlang.tex ├── 09-ports-and-port-drivers.tex ├── 10-code-loading.tex ├── 11-macros.tex └── 12-further-reading.tex ├── fonts ├── FiraMono-Bold.ttf ├── FiraMono-Regular.ttf ├── PTF55F.ttf ├── PTF56F.ttf ├── PTF75F.ttf └── PTF76F.ttf ├── includes ├── cc-by-sa.png └── erlang-logo.png └── output ├── ErlangHandbook-RU.pdf └── ErlangHandbook.pdf /.gitignore: -------------------------------------------------------------------------------- 1 | 2 | # latex ignores 3 | *.aux 4 | *.log 5 | *.nav 6 | *.out 7 | *.snm 8 | *.toc 9 | *.vrb 10 | *.bbl 11 | *.blg 12 | *.lof 13 | *.lot 14 | *.ilg 15 | *.ind 16 | *.nlo 17 | *.nls 18 | *.tdo 19 | *.gz 20 | *.gz(busy) 21 | *.depend 22 | *.fls 23 | *.fdb_latexmk 24 | *.dvi 25 | *.acn 26 | *.glo 27 | *.ist 28 | *.pyg 29 | *.acr 30 | *.alg 31 | *.glg 32 | *.gls 33 | *.lnk 34 | *.bak 35 | 36 | # general nonsense 37 | Thumbs.db 38 | .DS_Store 39 | *.pdf -------------------------------------------------------------------------------- /ErlangHandbook-RU.tex: -------------------------------------------------------------------------------- 1 | % !TEX encoding = UTF-8 Unicode 2 | %% NOTE: Due to using fontspec and UTF8 to avoid encoding problems and stuff, Russian 3 | %% version of this document builds using xe(la)tex and TexStudio 4 | \documentclass[russian,14pt,oneside]{book} 5 | \usepackage{extsizes} % additional font sizes for documentclass 6 | 7 | %%%%%% 8 | %% package includes 9 | \usepackage{ifxetex} 10 | \ifxetex 11 | \else 12 | \usepackage[utf8]{inputenc} 13 | \usepackage[T2A]{fontenc} 14 | \fi 15 | 16 | \usepackage[russian]{babel} 17 | \usepackage{hyperref} 18 | \usepackage{textcomp} 19 | \usepackage{array} 20 | \usepackage{color} 21 | \usepackage[hmargin=2.5cm,vmargin=2.5cm]{geometry} 22 | \usepackage{minted} 23 | \usepackage{todonotes} 24 | \usepackage{parskip} 25 | \usepackage[Bjornstrup]{fncychap} 26 | \usepackage{listings} 27 | 28 | %%%%%% 29 | %% package setup 30 | \hypersetup{ 31 | colorlinks=true, 32 | linktoc=all, 33 | linkcolor=red, 34 | } 35 | 36 | %%%%%% 37 | %% Fonts 38 | \ifxetex 39 | \usepackage{fontspec} 40 | \defaultfontfeatures{Scale=MatchLowercase,Mapping=tex-text} 41 | \setmainfont[Path=fonts/,ItalicFont=PTF56F.ttf, 42 | BoldFont=PTF75F.ttf]{PTF55F.ttf} 43 | \setmonofont[Ligatures={NoRequired,NoCommon,NoContextual}, 44 | Path=fonts/,BoldFont=FiraMono-Bold.ttf]{FiraMono-Regular.ttf} 45 | \usepackage{titlesec} 46 | \newfontfamily\erlChapterFont[Path=fonts/,BoldFont=PTF75F.ttf]{PTF55F.ttf} 47 | \ChTitleVar{\erlChapterFont\fontsize{28}{28}\bf\selectfont\hfill} 48 | \ChNameVar{\erlChapterFont\fontsize{16}{16}\bf\selectfont} 49 | \fi 50 | 51 | %%%%%% 52 | %% hacks and macros 53 | \newminted[erlang]{erlang}{xleftmargin=0cm,xrightmargin=0cm,frame=single,framerule=1pt} 54 | 55 | %% Framed code fragment coloring, for code examples where Russian variable 56 | %% names break syntax and coloring 57 | \usepackage{fancyvrb} 58 | \DefineVerbatimEnvironment{erlangru}{Verbatim}{frame=single,samepage=true} 59 | 60 | %% hack to fix the margin issue in \item s in 1.2.1 61 | \newminted[erlangim]{erlang}{xleftmargin=-1.5cm} 62 | 63 | %%% display todo notes or not? 64 | \newcommand{\todonote}[1]{\todo[inline]{\textbf{Note:} #1}} 65 | %\newcommand{\todonote}[1]{} 66 | 67 | %% typesetting for the "results in" notation used. 68 | \def\resultingin{$\quad\Rightarrow\quad$} 69 | 70 | \usepackage{wrapfig} 71 | 72 | \begin{document} 73 | 74 | %%%%%% 75 | %% Title 76 | \begin{titlepage} 77 | \centering 78 | 79 | \vspace*{70pt} 80 | \includegraphics[scale=0.3]{includes/erlang-logo.png}\\[0.8\baselineskip] 81 | {\Huge \sffamily НАСТОЛЬНАЯ КНИГА}\\ 82 | \vspace{250pt} 83 | {\LARGE Бьярн Дэкер (Bjarne D\"acker)}\par 84 | {\LARGE Роберт Вирдинг (Robert Virding)}\par 85 | 86 | \end{titlepage} 87 | 88 | 89 | %%%%%% 90 | %% Info Page 91 | \clearpage 92 | \thispagestyle{empty} 93 | {\Huge Настольная книга по Erlang}\\[0.1\baselineskip] 94 | \hspace{10pt}{\large{Бьярн Дэкер (Bjarne Däcker) и Роберт Вирдинг (Robert Virding)}} 95 | 96 | \vspace{10pt} 97 | {\Large \textbf{Версия:}\\[0.2\baselineskip] 98 | \immediate\write18{git log -n1 | grep 'Date:' | sed 's/Date: //g' > _revision.tex} 99 | \input{_revision} 100 | \immediate\write18{rm _revision.tex} 101 | } 102 | 103 | \vspace{10pt} 104 | {\large Последняя версия этой книги находится по адресу:\\ 105 | \url{http://opensource.erlang-solutions.com/erlang-handbook}} 106 | 107 | \vfill 108 | 109 | \textbf{Главный редактор}\\[0.1\baselineskip] 110 | Омер Килич (Omer Kilic) 111 | 112 | \textbf{Прочие участники}\\[0.1\baselineskip] 113 | Перевод на русский: Дмитрий Литовченко (Dmytro Lytovchenko) 114 | 115 | Список людей, которые помогли с изменениями и исправлениями находится 116 | \href{https://github.com/esl/erlang-handbook/graphs/contributors}{в репозитории 117 | проекта}. 118 | 119 | \vspace{10pt} 120 | \textbf{Соглашения}\\ 121 | Спецификации синтаксиса задаются с помощью \texttt{этого моноширинного шрифта}. 122 | В квадратные скобки ([ ]) заключаются необязательные части. Термы, начинающиеся 123 | с заглавной буквы, как например \textit{Integer} должны быть заменены на 124 | какое-нибудь подходящее значение. Термы, начинающиеся со строчной буквы, как 125 | например \texttt{end}, являются зарезервированными словами языка Erlang. 126 | Вертикальная черта (\textbar{}) разделяет альтернативные варианты, как например 127 | Integer \textbar{} Float. 128 | 129 | \vspace{10pt} 130 | \textbf{Ошибки и улучшения}\\ 131 | Это живой документ, пожалуйста присылайте исправления и рекомендации по улучшению 132 | содержимого используя систему учёта задач Github по адресу 133 | \url{https://github.com/esl/erlang-handbook}. Вы также можете создать свою ветвь 134 | репозитория (fork) и прислать нам запрос на соединение ветвей (pull request) с 135 | вашими предлагаемыми исправлениями и предложениями. Новые ревизии этого документа 136 | будут публиковаться по мере накопления больших изменений. 137 | 138 | \vspace{10pt} 139 | \begin{wrapfigure}[2]{l}{0.15\textwidth} 140 | \vspace{-12pt} 141 | \includegraphics[scale=0.7]{includes/cc-by-sa.png} 142 | \vspace{-12pt} 143 | \end{wrapfigure} 144 | Этот текст доступен согласно условиям лицензии Creative Commons 145 | Attribution-ShareAlike 3.0 License. Вы имеете право копировать, распространять и 146 | передавать эту книгу по условиям лицензии, описанным по адресу 147 | \url{http://creativecommons.org/licenses/by-sa/3.0} 148 | 149 | \newpage 150 | 151 | 152 | %%%%%% 153 | %% TOC 154 | \tableofcontents 155 | 156 | 157 | %%%%%% 158 | %% Chapters 159 | 160 | \input{chapters-RU/01-background} 161 | \input{chapters-RU/02-structure-of-an-erlang-program} 162 | \input{chapters-RU/03-data-types} 163 | \input{chapters-RU/04-pattern-matching} 164 | \input{chapters-RU/05-functions} 165 | \input{chapters-RU/06-processes} 166 | \input{chapters-RU/07-error-handling} 167 | \input{chapters-RU/08-distributed-erlang} 168 | \input{chapters-RU/09-ports-and-port-drivers} 169 | \input{chapters-RU/10-code-loading} 170 | \input{chapters-RU/11-macros} 171 | \input{chapters-RU/12-further-reading} 172 | 173 | 174 | \end{document} 175 | -------------------------------------------------------------------------------- /ErlangHandbook.tex: -------------------------------------------------------------------------------- 1 | %&pdfLaTeX 2 | % !TEX encoding = UTF-8 Unicode 3 | \documentclass[oneside]{book} 4 | 5 | %%%%%% 6 | %% package includes 7 | \usepackage[T1]{fontenc} 8 | \usepackage[utf8]{inputenc} 9 | \usepackage{hyperref} 10 | \usepackage{textcomp} 11 | \usepackage{array} 12 | \usepackage{color} 13 | \usepackage[hmargin=2.5cm,vmargin=2.5cm]{geometry} 14 | \usepackage{minted} 15 | \usepackage{todonotes} 16 | \usepackage{parskip} 17 | \usepackage[Bjornstrup]{fncychap} 18 | \usepackage{listings} 19 | 20 | %%%%%% 21 | %% package setup 22 | \hypersetup{ 23 | colorlinks=true, 24 | linktoc=all, 25 | linkcolor=red, 26 | } 27 | 28 | %%%%%% 29 | %% hacks and macros 30 | \newminted[erlang]{erlang}{xleftmargin=1cm,xrightmargin=1cm,frame=single,framerule=1pt} 31 | 32 | %% hack to fix the margin issue in \item s in 1.2.1 33 | \newminted[erlangim]{erlang}{xleftmargin=-1.5cm} 34 | 35 | %%% display todo notes or not? 36 | \newcommand{\todonote}[1]{\todo[inline]{\textbf{Note:} #1}} 37 | %\newcommand{\todonote}[1]{} 38 | 39 | %% typesetting for the "results in" notation used. 40 | \def\resultingin{$\quad\Rightarrow\quad$} 41 | 42 | \begin{document} 43 | 44 | %%%%%% 45 | %% Title 46 | \begin{titlepage} 47 | \centering 48 | 49 | \vspace*{70pt} 50 | \includegraphics[scale=0.3]{includes/erlang-logo.png}\\[0.8\baselineskip] 51 | {\Huge \sffamily HANDBOOK}\\ 52 | \vspace{250pt} 53 | {\LARGE \sffamily Bjarne D\"acker}\par 54 | {\LARGE \sffamily Robert Virding}\par 55 | 56 | \end{titlepage} 57 | 58 | 59 | %%%%%% 60 | %% Info Page 61 | \clearpage 62 | \thispagestyle{empty} 63 | {\Huge Erlang Handbook}\\[0.1\baselineskip] 64 | \hspace{10pt}{\large{by Bjarne Däcker and Robert Virding}} 65 | 66 | \vspace{20pt} 67 | {\Large \textbf{Revision:}\\[0.2\baselineskip] 68 | \immediate\write18{git log -n1 | grep 'Date:' | sed 's/Date: //g' > _revision.tex} 69 | \input{_revision} 70 | \immediate\write18{rm _revision.tex} 71 | } 72 | 73 | \vspace{20pt} 74 | {\large Latest version of this handbook can be found at:\\ 75 | \url{http://opensource.erlang-solutions.com/erlang-handbook}} 76 | 77 | ISBN: 978-1-938616-04-4 78 | 79 | \vfill 80 | 81 | \textbf{Editor}\\[0.1\baselineskip] 82 | %\begin{tabular}{@{\hspace{3ex}}p{42em}} 83 | Omer Kilic 84 | %\end{tabular} 85 | 86 | \textbf{Contributors}\\[0.1\baselineskip] 87 | %\begin{tabular}{@{\hspace{3ex}}p{42em}} 88 | The list of contributors can be found \href{https://github.com/esl/erlang-handbook/graphs/contributors}{on the project repository}. 89 | %\end{tabular} 90 | 91 | \vspace{20pt} 92 | \textbf{Conventions}\\ 93 | Syntax specifications are set using \texttt{this monotype font}. Square brackets 94 | ([ ]) enclose optional parts. Terms beginning with an uppercase letter like 95 | \textit{Integer} shall then be replaced by some suitable value. Terms beginning 96 | with a lowercase letter like \texttt{end} are reserved words in Erlang. A 97 | vertical bar (\textbar{}) separates alternatives, like Integer \textbar{} Float. 98 | 99 | \vspace{20pt} 100 | \textbf{Errata and Improvements}\\ 101 | This is a live document so please file corrections and suggestions for 102 | improvement about the content using the issue tracker at 103 | \url{https://github.com/esl/erlang-handbook}. You may also fork this repository 104 | and send a pull request with your suggested fixes and improvements. New 105 | revisions of this document will be published after major corrections. 106 | 107 | \vspace{20pt} 108 | \includegraphics[scale=0.7]{includes/cc-by-sa.png}\\ This text is made available 109 | under a Creative Commons Attribution-ShareAlike 3.0 License. You are free to 110 | copy, distribute and transmit it under the license terms defined at 111 | \url{http://creativecommons.org/licenses/by-sa/3.0} 112 | 113 | \newpage 114 | 115 | 116 | %%%%%% 117 | %% TOC 118 | \tableofcontents 119 | 120 | 121 | %%%%%% 122 | %% Chapters 123 | 124 | \input{chapters/01-background} 125 | 126 | \input{chapters/02-structure-of-an-erlang-program} 127 | 128 | \input{chapters/03-data-types} 129 | 130 | \input{chapters/04-pattern-matching} 131 | 132 | \input{chapters/05-functions} 133 | 134 | \input{chapters/06-processes} 135 | 136 | \input{chapters/07-error-handling} 137 | 138 | \input{chapters/08-distributed-erlang} 139 | 140 | \input{chapters/09-ports-and-port-drivers} 141 | 142 | \input{chapters/10-code-loading} 143 | 144 | \input{chapters/11-macros} 145 | 146 | \input{chapters/12-further-reading} 147 | 148 | 149 | \end{document} 150 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | DOC=ErlangHandbook 2 | DOC_RU=ErlangHandbook-RU 3 | REV=`git log -n1 | grep 'Date:' | sed 's/Date: //g'` 4 | 5 | .PHONY: all 6 | all: english 7 | 8 | .PHONY: english 9 | english: output/$(DOC).pdf 10 | 11 | .PHONY: russian 12 | russian: output/$(DOC_RU).pdf 13 | 14 | .PHONY: release 15 | release: clean all 16 | git add output/$(DOC).pdf output/$(DOC_RU).pdf 17 | git commit -m "release: $(REV)" 18 | git push 19 | 20 | .PHONY: clean 21 | clean: 22 | rm -f *.pdf *.dvi *.aux *.log *.nav *.out *.snm *.toc *.vrb *.bbl *.blg \ 23 | *.lof *.lot *.ilg *.ind *.nlo *.nls *.tdo *.gz *.depend 24 | 25 | .PHONY: view 26 | view: 27 | evince $(DOC).pdf & 28 | 29 | XELATEX=xelatex -synctex=1 -interaction=nonstopmode --shell-escape 30 | output/$(DOC_RU).pdf: chapters-RU/*.tex $(DOC_RU).tex 31 | $(XELATEX) $(DOC_RU).tex && \ 32 | $(XELATEX) $(DOC_RU).tex; \ 33 | mv -f $(DOC_RU).pdf output/ 34 | 35 | PDFLATEX=pdflatex -synctex=1 -interaction=nonstopmode --shell-escape 36 | output/$(DOC).pdf: chapters/*.tex $(DOC).tex 37 | $(PDFLATEX) $(DOC).tex && \ 38 | $(PDFLATEX) $(DOC).tex; \ 39 | mv -f $(DOC).pdf output/ 40 | # NOTE the ; after pdflatex call, sometimes pdflatex ends with error but still produces the document 41 | -------------------------------------------------------------------------------- /README-RU.md: -------------------------------------------------------------------------------- 1 | # Настольная книга по Erlang 2 | 3 | Изначально написанная Бьярном Дэкером (Bjarne Däcker) и позже пересмотренная 4 | Робертом Вирдингом (Robert Virding), настольная книга по Erlang является 5 | собранием возможностей языка и системы времени исполнения. Книга нацелена на людей 6 | с некоторым опытом программирования, и служит кратким введением в область знаний, 7 | касающуюся языка Erlang. 8 | 9 | 10 | ## Где скачать 11 | Текущая версия может быть скачана [здесь][release]. 12 | 13 | Настольная книга свёрстана с помощью системы LaTeX. Если вы хотите собрать книгу 14 | самостоятельно, вам поможет Makefile, попробуйте команду `make` или даже `make russian`. 15 | Вам понадобится дополнительно установить пакеты [minted] и [pygments] для того, 16 | чтобы магия раскраски исходных текстов заработала, а также `xelatex`, поскольку 17 | русская версия использует Unicode шрифты, и, в отличие от английской, не работает 18 | со стандартными шрифтами LaTeX. 19 | 20 | 21 | ## Ошибки и улучшения 22 | 23 | Это живой документ, пожалуйста присылайте исправления и рекомендации по улучшению 24 | содержимого используя [систему учёта задач][issue tracker]. Вы также можете создать 25 | свою ветвь репозитория (fork) и прислать нам запрос на соединение ветвей (pull request) 26 | с вашими предлагаемыми исправлениями и предложениями. Новые ревизии этого документа 27 | будут публиковаться по мере накопления больших изменений 28 | 29 | 30 | ## Лицензия 31 | 32 | ![cc-by-sa](http://i.creativecommons.org/l/by-sa/3.0/88x31.png) 33 | 34 | Этот текст доступен согласно Creative Commons Attribution-ShareAlike 3.0 License. 35 | Вы имеете право копировать, распространять и передавать его согласно условиям 36 | лицензии, описанным [здесь][cc-license]. 37 | 38 | 39 | 40 | [release]: https://github.com/esl/erlang-handbook/raw/master/output/ErlangHandbook-RU.pdf 41 | [pygments]: http://pygments.org/ 42 | [minted]: https://github.com/gpoore/minted 43 | [issue tracker]: https://github.com/esl/erlang-handbook/issues 44 | [cc-license]: http://creativecommons.org/licenses/by-sa/3.0 45 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Erlang Handbook 2 | 3 | Originally written by Bjarne Däcker and later revised by Robert Virding, the 4 | Erlang Handbook is a summary of the language features and the runtime system. 5 | It is aimed at people with some programming experience, serving as a quick 6 | introduction to the Erlang domain. 7 | 8 | 9 | ## Download 10 | 11 | The current English release can be obtained [here][release]. Russian translation is [here][releaseRU]. 12 | 13 | The handbook is typeset using LaTeX. If you want to build from source, the 14 | Makefile will be your friend. Run `make` or `make english`. You will need the 15 | [minted] package (and [pygments]) for the syntax highlighting magic to work. 16 | 17 | 18 | ## Errata and Improvements 19 | 20 | This is a live document so please file corrections and suggestions for 21 | improvement about the content using the [issue tracker]. You may also fork 22 | this repository and send a pull request with your suggested fixes and 23 | improvements. New revisions of this document will be published after major 24 | corrections. 25 | 26 | 27 | ## License 28 | 29 | ![cc-by-sa](http://i.creativecommons.org/l/by-sa/3.0/88x31.png) 30 | 31 | This text is made available under a Creative Commons Attribution-ShareAlike 32 | 3.0 License. You are free to copy, distribute and transmit it under the 33 | license terms defined [here][cc-license]. 34 | 35 | 36 | [release]: https://github.com/esl/erlang-handbook/raw/master/output/ErlangHandbook.pdf 37 | [releaseRU]: https://github.com/esl/erlang-handbook/raw/master/output/ErlangHandbook-RU.pdf 38 | [pygments]: http://pygments.org/ 39 | [minted]: https://github.com/gpoore/minted 40 | [issue tracker]: https://github.com/esl/erlang-handbook/issues 41 | [cc-license]: http://creativecommons.org/licenses/by-sa/3.0 42 | -------------------------------------------------------------------------------- /chapters-RU/01-background.tex: -------------------------------------------------------------------------------- 1 | \chapter[Вступление, или почему Erlang такой, как он есть]{Вступление} 2 | \section*{или почему Erlang такой, как он есть} 3 | \label{background} 4 | 5 | Erlang --- это результат проекта по улучшению программирования приложений для 6 | телекоммуникаций в Лаборатории Компьютерных Наук (CSLab или Computer Science Lab) 7 | компании Ericsson. Критически важным требованием была поддержка характеристик 8 | этих приложений, таких, как: 9 | 10 | \begin{itemize} 11 | \item Массивная параллельность 12 | \item Устойчивость к сбоям 13 | \item Изоляция 14 | \item Динамическое обновление кода во время его исполнения 15 | \item Транзакционность 16 | \end{itemize} 17 | 18 | В течение всей истории Erlang процесс его разработки был исключительно 19 | прагматичным. Характеристики и свойства видов систем, в которых была заинтересована 20 | компания Ericsson, прямым образом влияли на ход разработки Erlang. Эти свойства 21 | считались настолько фундаментальными, что было решено поддержку для них встроить 22 | прямо в язык, вместо дополнительных библиотек. По причине прагматичного процесса 23 | разработки вместо предварительного планирования, Erlang "<стал"> функциональным 24 | языком --- поскольку свойства функциональных языков очень хорошо подходили к 25 | свойствам систем, которые разрабатывались. 26 | 27 | -------------------------------------------------------------------------------- /chapters-RU/02-structure-of-an-erlang-program.tex: -------------------------------------------------------------------------------- 1 | \chapter{Структура Erlang-программы} 2 | 3 | \section{Синтаксис модулей} 4 | 5 | Программа на Erlang состоит из \textbf{модулей} где каждый модуль является 6 | текстовым файлом с расширением \textbf{.erl}. Для небольших программ все 7 | модули обычно хранятся в одной директории. Модуль состоит из атрибутов модуля 8 | и определений функций. 9 | 10 | \begin{erlang} 11 | -module(demo). 12 | -export([double/1]). 13 | 14 | double(X) -> times(X, 2). 15 | 16 | times(X, N) -> X * N. 17 | \end{erlang} 18 | 19 | Показанный модуль \texttt{demo} состоит из функции \texttt{times/2}, которая 20 | является локальной для модуля и функции \texttt{double/1}, которая 21 | экспортирована и может быть вызвана снаружи модуля. 22 | 23 | \texttt{demo:double(10)} \resultingin \texttt{20}\hfill 24 | (стрелка $\Rightarrow$ читается как "<даёт результат">) 25 | 26 | \texttt{double/1} означает, что перед нами функция " с \emph{одним} 27 | аргументом. Функция \texttt{double/2} принимает \emph{два} аргумента и считается 28 | другой, отличной от первой, функцией. Количество аргументов называется 29 | \textbf{арностью} (arity) данной функции. 30 | 31 | 32 | 33 | \section{Атрибуты модулей} 34 | 35 | \textbf{Атрибут модуля} определяет некоторое свойство модуля и состоит из 36 | \textbf{метки} и \textbf{значения} в следующем виде: 37 | 38 | \texttt{-Метка(Значение).} 39 | 40 | \texttt{Метка} должна быть атомом, в то время, как значение \texttt{Значение} 41 | должно быть термом (смотрите главу \ref{datatypes}). Можно указывать любое имя 42 | для атрибута модуля, также разрешены повторы. Атрибуты хранятся в скомпилированном 43 | коде и могут быть извлечены с помощью вызова функции 44 | \texttt{Модуль:module\_info(attributes).} 45 | 46 | \subsection{Предопределённые атрибуты модулей} 47 | Предопределённые атрибуты модулей должны быть размещены в модуле до начала первого 48 | определения функции. 49 | 50 | \begin{itemize} 51 | 52 | \item \verb|-module(Модуль).|\hfill\\ 53 | Этот атрибут обязателен и должен идти первой строкой файла. Он определяет имя 54 | модуля. Имя Module, атом (смотрите раздел \ref{datatypes:atom}), 55 | должно соответствовать имени файла без расширения \texttt{.erl}. 56 | 57 | \item \verb|-export([Функ1/Арность1, ..., ФункN/АрностьN]).|\hfill\\ 58 | Этот атрибут указывает, какие функции модуля могут быть вызваны снаружи 59 | модуля. Каждое имя функции \texttt{Функ\textsubscript{X}} --- это атом и 60 | \texttt{АрностьX} функции --- целое число. 61 | 62 | \item \verb|-import(Модуль,[Функ1/Арность1, ..., ФункN/АрностьN]).|\hfill\\ 63 | Этот атрибут указывает модуль \texttt{Модуль}, из которого импортируется список 64 | функций. Например: 65 | 66 | \begin{itemize} 67 | \item \verb|import(demo, [double/1]).|\hfill\\ 68 | Эта запись означает, что теперь можно писать \texttt{double(10)} вместо более 69 | длинной записи \texttt{demo:double(10)}, которая может быть непрактична, если 70 | функция используется часто. 71 | \end{itemize} 72 | 73 | \item \verb|-compile(Параметры).|\hfill\\ 74 | Параметры компилятора для данного модуля. 75 | 76 | \item \verb|-vsn(Vsn).|\hfill\\ 77 | Версия модуля. Если не указать этот атрибут, то по умолчанию будет использована 78 | контрольная сумма содержимого модуля. 79 | 80 | \item \verb|-behaviour(Поведение).|\hfill\\ 81 | Этот атрибут указывает поведение модуля, либо выбранное пользователем, либо 82 | одно из стандартных поведений OTP: \texttt{gen\_server}, \texttt{gen\_fsm}, 83 | \texttt{gen\_event} или \texttt{supervisor}. Принимаются как британская 84 | (behaviour), так и американская запись (behavior). 85 | \end{itemize} 86 | 87 | 88 | 89 | \subsection{Определения записей и макросов} 90 | 91 | Записи и макросы определяются так же, как и другие атрибуты модуля: 92 | 93 | \begin{erlangru} 94 | -record(Запись, Поля). 95 | -define(Макро, Замена). 96 | \end{erlangru} 97 | 98 | Записи и определения макросов также позволяются между функциями, если 99 | определение встречается раньше, чем его первое использование. (Подробнее о 100 | записях читайте секцию \ref{datatypes:record}, а о макросах главу \ref{macros}.) 101 | 102 | 103 | 104 | \subsection{Включение содержимого файлов} 105 | 106 | Включение содержимого файлов указывается аналогично другим атрибутам модуля: 107 | 108 | \begin{erlangru} 109 | -include(Файл). 110 | -include_lib(Файл). 111 | \end{erlangru} 112 | 113 | \texttt{File} --- это строка, представляющая собой имя файла. Включаемые файлы 114 | обычно используются для определений записей и макросов, которые используются 115 | в нескольких модулях сразу. По договорённости для включаемых файлов используется 116 | расширение \texttt{.hrl}. 117 | 118 | \begin{erlang} 119 | -include("my_records.hrl"). 120 | -include("incdir/my_records.hrl"). 121 | -include("/home/user/proj/my_records.hrl"). 122 | \end{erlang} 123 | 124 | Если путь к файлу \texttt{File} начинается с компонента пути \texttt{\$Var}, то 125 | значение переменной окружения \texttt{Var} (которое возвращается функцией 126 | \texttt{os:getenv(Var)}) будет подставлено вместо \texttt{\$Var}. 127 | 128 | \begin{erlang} 129 | -include("$PROJ_ROOT/my_records.hrl"). 130 | \end{erlang} 131 | %%$ texmaker parser bug 132 | 133 | Директива \texttt{include\_lib} подобна \texttt{include}, но считается, что 134 | первый компонент пути --- имя приложения. 135 | 136 | \begin{erlang} 137 | -include_lib("kernel/include/file.hrl"). 138 | \end{erlang} 139 | 140 | Сервер кода (специальный процесс, управляющий загрузкой и версиями модулей в 141 | памяти) использует функцию \texttt{code:lib\_dir(kernel)} для поиска директории 142 | текущей (свежайшей) версии модуля \texttt{kernel}, и затем в поддиректории 143 | \texttt{include} производится поиск нужного файла \texttt{file.hrl}. 144 | 145 | 146 | 147 | \section{Комментарии} 148 | 149 | Комментарии могут появляться в любом месте модуля, кроме как внутри строк и 150 | атомов, заключённых в кавычки. Комментарий начинается с символа процента 151 | (\texttt{\%}) и действителен до конца строки но не включая символ конца строки. 152 | Завершающий строку символ конца строки, с точки зрения компилятора, действует 153 | как пробел. 154 | 155 | 156 | 157 | \section{Кодировка файлов} 158 | 159 | Erlang работает с полным набором символов Latin-1 (ISO-8859-1). Таким образом, 160 | можно использовать и выводить на экран все печатные символы из набора Latin-1 161 | без цитирования с помощью обратной косой черты (\textbackslash{}). Атомы и 162 | переменные могут использовать все символы из набора Latin-1. 163 | 164 | \textbf{Примечание:} Начиная с версии R16 позволяется использовать кодировку 165 | UTF-8 для исходных файлов, но этот режим нужно включать параметром командной 166 | строки компилятора. Начиная с версии R17, исходные файлы имеют кодировку UTF-8 167 | по умолчанию. 168 | 169 | \vspace*{12pt} 170 | \begin{center} 171 | \begin{tabular}{|>{\raggedright}p{52pt}|>{\raggedright}p{53pt}|>{\raggedright}p{103pt}|>{\raggedright}p{150pt}|} 172 | \hline 173 | \multicolumn{4}{|p{350pt}|}{Классы символов в кодировке}\tabularnewline 174 | \hline 175 | Восьме\-ричное & Деся\-тичное~ & & Класс \tabularnewline 176 | \hline 177 | 40 - 57 & 32 - 47 & ! \texttt{"} \# \$ \% \& ' / & Символы пунктуации \tabularnewline 178 | \hline 179 | 60 - 71 & 48 - 57 & 0 - 9 & Десятичные цифры \tabularnewline 180 | \hline 181 | 72 - 100 & 58 - 64 & : ; \texttt{<} = \texttt{>} @ & Символы пунктуации \tabularnewline 182 | \hline 183 | 101 - 132 & 65 - 90 & A - Z & Заглавные буквы \tabularnewline 184 | \hline 185 | 133 - 140 & 91 - 96 & [ \textbackslash{} ] \textasciicircum{} \_ ` & Символы пунктуации \tabularnewline 186 | \hline 187 | 141 - 172 & 97 - 122 & a - z & Строчные буквы \tabularnewline 188 | \hline 189 | 173 - 176 & 123 - 126 & \{ \textbar{} \} \textasciitilde{} & Символы пунктуации \tabularnewline 190 | \hline 191 | 200 - 237 & 128 - 159 ~ & & Управляющие символы \tabularnewline 192 | \hline 193 | 240 - 277 & 160 - 191 & - ¿ & Символы пунктуации \tabularnewline 194 | \hline 195 | 300 - 326 & 192 - 214 & À - Ö & Заглавные буквы \tabularnewline 196 | \hline 197 | 327 & 215 & × & Символ пунктуации \tabularnewline 198 | \hline 199 | 330 - 336 & 216 - 222 & Ø - Þ & Заглавные буквы \tabularnewline 200 | \hline 201 | 337 - 366 & 223 - 246 & ß - ö & Строчные буквы \tabularnewline 202 | \hline 203 | 367 & 247 & ÷ & Символ пунктуации \tabularnewline 204 | \hline 205 | 370 - 377 & 248 - 255 & ø - ÿ & Строчные буквы \tabularnewline 206 | \hline 207 | \end{tabular} 208 | \end{center} 209 | 210 | 211 | \section{Зарезервированные слова} 212 | 213 | %\vspace{12pt} 214 | 215 | Следующие ключевые слова в Erlang зарезервированы, и не могут использоваться в 216 | качестве атомов (для использования одного из ключевых слов в качестве атома, 217 | оно должно быть заключено в одиночные кавычки): 218 | 219 | \begin{erlang} 220 | after and andalso band begin bnot bor bsl bsr bxor case 221 | catch cond div end fun if let not of or orelse receive 222 | rem try when xor 223 | \end{erlang} 224 | -------------------------------------------------------------------------------- /chapters-RU/03-data-types.tex: -------------------------------------------------------------------------------- 1 | \chapter{Типы данных (термы)} 2 | \label{datatypes} 3 | 4 | 5 | \section{Унарные (одиночные) типы данных} 6 | 7 | 8 | \subsection{Атомы} 9 | \label{datatypes:atom} 10 | \textbf{Атом} --- это символьное имя, также известное, как \emph{литерал}. 11 | Атомы начинаются со строчной латинской буквы и могут содержать буквенно-цифровые 12 | символы, подчёркивания (\texttt{\_}) и символ \emph{at} (\texttt{@}). 13 | Как вариант, атомы могут быть указаны с помощью заключения в одиночные кавычки 14 | (\texttt{'}), это необходимо, если атом начинается с заглавной буквы, или 15 | содержит другие символы, кроме подчёркиваний и \emph{at} (\texttt{@}). 16 | Например: 17 | 18 | \begin{erlang} 19 | hello 20 | phone_number 21 | 'Monday' 22 | 'phone number' 23 | \end{erlang} 24 | 25 | \texttt{'Anything inside quotes \textbackslash n\textbackslash 012'} 26 | \hfill(см. раздел \ref{datatypes:escapeseq}) 27 | 28 | 29 | \subsection{Истина и ложь} 30 | \label{datatypes:boolean} 31 | 32 | В Erlang нет специального типа данных для \textbf{логических} значений. Эту роль 33 | выполняют атомы \texttt{true} и \texttt{false}. 34 | 35 | \texttt{2 =< 3} \resultingin \texttt{true} \\ 36 | \texttt{true or false} \resultingin \texttt{true} 37 | 38 | 39 | \subsection{Целые числа} 40 | \label{datatypes:integer} 41 | 42 | В дополнение к обычному способу записи \textbf{целых чисел} Erlang предлагает 43 | ещё ряд способов записи. Запись \texttt{\$Char} даёт числовое значение для 44 | символа '\texttt{Char}' в кодировке Latin-1 (это также может быть и непечатный 45 | символ) и запись\linebreak 46 | \texttt{Base\#Value} --- даёт целое число, записанное с основанием 47 | \texttt{Base}, основание должно быть целым числом в диапазоне $2..36$. 48 | 49 | \texttt{42} \resultingin \texttt{42} \\ 50 | \$A \resultingin \texttt{65} \\ 51 | \texttt{\$\textbackslash n} \resultingin \texttt{10}\hfill(see section \ref{datatypes:escapeseq}) \\ 52 | \texttt{2\#101} \resultingin \texttt{5} \\ 53 | \texttt{16\#1f} \resultingin \texttt{31} 54 | 55 | 56 | \subsection{Действительные с плавающей точкой} 57 | \label{datatypes:float} 58 | 59 | Действительное число \textbf{с плавающей точкой} записывается, как\linebreak 60 | \texttt{Основание}[\texttt{"e"Экспонента}], где \texttt{Основание} --- это 61 | действительное число в диапазоне от 0.01 до 10000 и \texttt{Экспонента} 62 | (необязательное) --- это целое число со знаком, указывающее экспоненту (степень 63 | десятки, на которую множится \texttt{Основание}). Например: 64 | 65 | \texttt{2.3e-3} \resultingin \texttt{2.30000e-3}\hfill 66 | (соответствует $2.3 \cdot 10^{-3}$) 67 | 68 | 69 | \subsection{Ссылочные значения} 70 | \label{datatypes:reference} 71 | 72 | \textbf{Ссылка} --- это терм, значение которого является уникальным в системе 73 | времени исполнения Erlang, который создаётся встроенной функцией 74 | \texttt{make\_ref/0}. (Для дополнительной информации по встроенным функциям, 75 | или \emph{BIF}-ам, смотрите раздел \ref{functions:bifs}.) 76 | 77 | 78 | \subsection{Порты} 79 | \label{datatypes:port} 80 | 81 | \textbf{Идентификатор порта} указывает на открытый в системе порт (смотрите 82 | главу \ref{ports} про порты). 83 | 84 | 85 | \subsection{Идентификаторы процессов (Pid)} 86 | \label{datatypes:pid} 87 | 88 | \textbf{Идентификатор процесса}, или \emph{pid}, указывает на процесс в системе 89 | (смотрите главу \ref{processes} о процессах). 90 | 91 | 92 | \subsection{Анонимные функции} 93 | \label{datatypes:fun} 94 | 95 | Тип данных \emph{fun} идентифицирует \emph{анонимную функцию} или 96 | \textbf{функциональный объект} (см. раздел \ref{functions:funs}). 97 | 98 | 99 | 100 | \section{Составные типы данных} 101 | 102 | 103 | \subsection{Кортежи} 104 | \label{datatypes:tuple} 105 | 106 | \textbf{Кортеж} --- это составной тип данных, который содержит 107 | \textbf{фиксированное количество термов}, заключённое \{в фигурные скобки\}. 108 | Например: 109 | 110 | \begin{erlangru} 111 | {Терм1,...,ТермN} 112 | \end{erlangru} 113 | 114 | Каждый из \texttt{ТермX} в кортеже называется \textbf{элементом}. Количество 115 | элементов называется \textbf{размером} данного кортежа. 116 | 117 | \begin{center} 118 | \begin{tabular}{|>{\raggedright}p{220pt}|>{\raggedright}p{230pt}|} 119 | \hline 120 | \multicolumn{2}{|p{321pt}|}{BIF-функции для работы с кортежами}\tabularnewline 121 | \hline 122 | \texttt{size(Кортеж)} & 123 | Возвращает размер \texttt{Кортежа}\tabularnewline 124 | \hline 125 | \texttt{element(N,Кортеж)} & 126 | Возвращает \texttt{N}\textsuperscript{ый} элемент в \texttt{Кортеже} 127 | \tabularnewline 128 | \hline 129 | \texttt{setelement(N,Кортеж1,Выражение)} & 130 | Возвращает новый кортеж, скопированный из \texttt{Кортеж1}, в котором 131 | \texttt{N}\textsuperscript{ый} элемент заменён новым значением 132 | \texttt{Выражение}\tabularnewline 133 | \hline 134 | \end{tabular} 135 | \end{center} 136 | 137 | \texttt{P = \{adam, 24, \{july, 29\}\}} \resultingin \texttt{P} связано с 138 | \texttt{\{adam, 24, \{july, 29\}\}} \\ 139 | \texttt{element(1, P)} \resultingin \texttt{adam} \\ 140 | \texttt{element(3, P)} \resultingin \texttt{ \{july,29\}} \\ 141 | \texttt{P2 = setelement(2, P, 25)} \resultingin \texttt{P2} связано с 142 | \texttt{\{adam, 25, \{july, 29\}\}} \\ 143 | \texttt{size(P)} \resultingin \texttt{3} \\ 144 | \texttt{size(\{\})} \resultingin \texttt{0} \\ 145 | 146 | 147 | \subsection{Записи} 148 | \label{datatypes:record} 149 | 150 | \textbf{Запись} это \emph{именованный кортеж}, имеющий именованные элементы, 151 | которые называются \textbf{полями}. Тип записи определяется в виде атрибута 152 | модуля, например: 153 | 154 | \begin{erlangru} 155 | -record(Запись, {Поле1 [= Значение1], 156 | ... 157 | ПолеN [= ЗначениеN]}). 158 | \end{erlangru} 159 | 160 | Здесь имя записи \texttt{Запись} и имена полей \texttt{ПолеХ} --- атомы и каждое 161 | \texttt{ПолеX} может получить необязательное значение по умолчанию 162 | \texttt{ЗначениеX}. Это определение может быть помещено в любом месте модуля 163 | между определениями функций, но обязательно до первого использования. Если тип 164 | записи используется в нескольких модулях, рекомендуется поместить его в 165 | отдельный файл для включения. 166 | 167 | Новая запись с типом \texttt{Запись} создаётся с помощью следующего выражения: 168 | 169 | \begin{erlangru} 170 | #Запись{Поле1=Выражение1, ..., ПолеK=ВыражениеK [, _=ВыражениеL]} 171 | \end{erlangru} 172 | 173 | Поля не обязательно должны идти в том же порядке, как и в определении записи. 174 | Пропущенные поля получат свои соответствующие значения по умолчанию. Если 175 | использована последняя запись (подчёркивание равно \texttt{ВыражениеL}), то все 176 | оставшиеся поля получат значение \texttt{ВыражениеL}. Поля без значений по 177 | умолчанию и пропущенные поля получат значение \texttt{undefined}. 178 | 179 | Значение поля можно получить используя выражение 180 | \texttt{Переменная\#Запись.Поле}. 181 | 182 | \begin{erlang} 183 | -module(employee). 184 | -export([new/2]). 185 | -record(person, {name, age, employed=erixon}). 186 | 187 | new(Name, Age) -> #person{name=Name, age=Age}. 188 | \end{erlang} 189 | 190 | Здесь функция \texttt{employee:new/2} может быть использована в другом модуле, 191 | который также должен включить файл, содержащий определение использованной здесь 192 | записи \texttt{person}. 193 | 194 | \texttt{\{P = employee:new(ernie,44)\}} \resultingin \texttt{\{person, ernie, 195 | 44, erixon\}} \\ 196 | \texttt{P\#person.age} \resultingin \texttt{44} \\ 197 | \texttt{P\#person.employed} \resultingin \texttt{erixon} 198 | 199 | При работе с записями в интерпретаторе Erlang, можно использовать 200 | функции\linebreak 201 | \texttt{rd(ИмяЗаписи, ОпределениеЗаписи)} и \texttt{rr(Модуль)} для того, чтобы 202 | определить или загрузить новые определения записей. Подробнее читайте в 203 | документации\linebreak\emph{Erlang Reference Manual}. 204 | 205 | 206 | 207 | \subsection{Списки} 208 | \label{datatypes:list} 209 | 210 | \textbf{Список} --- это составной тип данных, который содержит \emph{переменное} 211 | количество \textbf{термов}, заключённое в квадратных скобках. 212 | 213 | \begin{erlangru} 214 | [Терм1,...,ТермN] 215 | \end{erlangru} 216 | 217 | Каждый \texttt{ТермX} в списке называется \textbf{элементом}. Количество 218 | элементов в списке называется \textbf{длиной списка}. Как это принято в 219 | функциональном программировании, первый элемент называется \textbf{головой} 220 | списка, а остаток (начиная с 2\textsuperscript{го} элемента и до конца) 221 | называется \textbf{хвостом} списка. Заметьте, что отдельные элементы в списке 222 | не должны быть одинакового типа, хотя часто практикуется (и это, наверное, даже 223 | удобно), иметь в списке элементы одинакового типа --- когда приходится работать 224 | с элементами разных типов, обычно используются \textbf{записи}. 225 | 226 | \begin{center} 227 | \begin{tabular}{|>{\raggedright}p{124pt}|>{\raggedright}p{290pt}|} 228 | \hline 229 | \multicolumn{2}{|p{321pt}|}{Встроенные функции для работы со списками} 230 | \tabularnewline 231 | \hline 232 | \texttt{length(Список)} & 233 | Возвращает длину \texttt{Списка} \tabularnewline 234 | \hline 235 | \texttt{hd(Список)} & 236 | Возвращает 1\textsuperscript{й} элемент \texttt{Списка} (голову) \tabularnewline 237 | \hline 238 | \texttt{tl(Список)} & 239 | Возвращает \texttt{Список} без 1\textsuperscript{го} элемента (хвост) \tabularnewline 240 | \hline 241 | \end{tabular} 242 | \end{center} 243 | 244 | Оператор "<вертикальная черта"> (\textbar{}, также в некоторых книгах по ФП он 245 | называется \texttt{cons}), отделяет ведущие элементы списка (один или более) 246 | от остальных элементов. Например: 247 | 248 | \texttt{[H | T] = [1, 2, 3, 4, 5]} \resultingin \texttt{H=1} и 249 | \texttt{T=[2, 3, 4, 5]} \\ 250 | \texttt{[X, Y | Z] = [a, b, c, d, e]} \resultingin \texttt{X=a}, 251 | \texttt{Y=b} и \texttt{Z=[c, d, e]} 252 | 253 | Список --- рекурсивная структура. Неявно список завершается ссылкой на пустой 254 | список, то есть~\texttt{[a,b]} это то же самое, как и \texttt{[a,b|[]]}. 255 | Список, выглядящий как \texttt{[a,b|c]} называется \textbf{плохо 256 | сформированным} (badly formed) и такой записи следует избегать (потому что 257 | атом '\texttt{c}', завершающий структуру списка сам \emph{не} является списком). 258 | Списки натурально способствуют рекурсивному функциональному программированию. 259 | 260 | Например, следующая функция \texttt{sum} вычисляет сумму списка и функция 261 | \texttt{double} умножает каждый элемент списка на 2, при этом конструируя и 262 | возвращая новый список по ходу выполнения. 263 | 264 | \begin{erlang} 265 | sum([]) -> 0; 266 | sum([H | T]) -> H + sum(T). 267 | 268 | double([]) -> []; 269 | double([H | T]) -> [H*2 | double(T)]. 270 | \end{erlang} 271 | 272 | Определения функций выше представляют \emph{сопоставление с образцом}, которое 273 | описано далее в главе \ref{patterns}. Образцы в такой записи часто встречаются 274 | в рекурсивном программировании, неявно предоставляя "<базовый случай"> (для 275 | пустого списка в этих примерах). 276 | 277 | Для работы со списками, оператор \texttt{++} соединяет вместе два списка 278 | (присоединяет второй аргумент к первому) и возвращает список-результат. 279 | Оператор \texttt{-{}-} создаёт список, который является копией первого 280 | аргумента, за тем исключением, что для каждого элемента во втором списке его 281 | первое вхождение в результат (если такое было) удаляется. 282 | 283 | \texttt{[1,2,3] ++ [4,5]} \resultingin \texttt{[1,2,3,4,5]} 284 | \texttt{[1,2,3,2,1,2] -{}- [2,1,2]} \resultingin \texttt{[3,1,2]} 285 | 286 | Подборка функций, работающих со списками может быть найдена в модуле стандартной 287 | библиотеки с названием \texttt{lists}. 288 | 289 | 290 | \subsection{Строки} 291 | \label{datatypes:string} 292 | 293 | \textbf{Строки} --- это цепочки символов, заключённые между двойными кавычками, 294 | на самом деле они хранятся в памяти, как списки целых чисел --- символов. 295 | 296 | \texttt{"abcdefghi"} то же самое, как и 297 | \texttt{[97,98,99,100,101,102,103,104,105]} 298 | 299 | \texttt{""} то же самое, как и \texttt{[]} 300 | 301 | Две строки, записанные подряд без разделительных знаков и операторов будут 302 | соединены в одну во время компиляции и не принесут дополнительных затрат по 303 | соединению во время исполнения. 304 | 305 | \texttt{"string" "42"} \resultingin \texttt{"string42"} 306 | 307 | 308 | \subsection{Двоичные данные} 309 | \label{datatypes:binary} 310 | 311 | \textbf{Двоичные данные} --- это блок нетипизированной памяти, по умолчанию 312 | двоичные данные являются последовательностью 8-битных элементов (байтов). 313 | 314 | \begin{erlangru} 315 | <<Элемент1,...,ЭлементN>> 316 | \end{erlangru} 317 | 318 | Каждый \texttt{ЭлементX} указывается в виде 319 | 320 | \begin{erlangru} 321 | Значение[:Размер][/СписокСпецификацийТипа] 322 | \end{erlangru} 323 | 324 | \begin{center} 325 | \begin{tabular}{|>{\raggedright}p{120pt}|>{\raggedright}p{120pt}|>{\raggedright}p{180pt}|} 326 | \hline 327 | \multicolumn{3}{|p{297pt}|}{Спецификация элемента двоичных данных} 328 | \tabularnewline 329 | \hline 330 | \texttt{Значение} & 331 | \texttt{Размер} & 332 | \texttt{СписокСпецификацийТипа}\tabularnewline 333 | \hline 334 | Выражение должно вычисляться в целое, действительное число или двоичные 335 | данные. & 336 | Выражение должно вычисляться в целое число & 337 | Последовательность необязательных спецификаторов типа, в любом порядке, 338 | разделённых дефисами (-)\tabularnewline 339 | \hline 340 | \end{tabular} 341 | \end{center} 342 | 343 | % page break at this point, so turned into two chunks. 344 | \begin{center} 345 | \begin{tabular}{|>{\raggedright}p{90pt}|>{\raggedright}p{140pt}|>{\raggedright}p{200pt}|} 346 | \hline 347 | \multicolumn{3}{|p{297pt}|}{Спецификаторы типов}\tabularnewline 348 | \hline 349 | Тип данных & 350 | \texttt{integer} \textbar{} \texttt{float} \textbar{} \texttt{binary} & 351 | По умолчанию \texttt{integer}\tabularnewline 352 | \hline 353 | Наличие знака & 354 | \texttt{signed} \textbar{} \texttt{unsigned} & 355 | По умолчанию без знака, \texttt{unsigned}\tabularnewline 356 | \hline 357 | Порядок байтов (endianness) & 358 | \texttt{big} \textbar{} \texttt{little} \textbar{} \texttt{native} & 359 | Зависит от архитектуры процессора. По умолчанию \texttt{big}\tabularnewline 360 | \hline 361 | Единица измерения (группа битов) & 362 | \texttt{unit:}\emph{ЦелоеЧисло} & 363 | Разрешены значения от 1 до 256. 364 | По умолчанию 1 для целых и действительных чисел и 8 для двоичных данных 365 | \tabularnewline 366 | \hline 367 | \end{tabular} 368 | \end{center} 369 | 370 | Значение \texttt{Размера} умножается на единицу измерения и даёт число бит, 371 | которые может занять данный сегмент двоичных данных. Каждый сегмент может 372 | состоять из нуля или более битов, но общая сумма битов должна делиться нацело 373 | на 8, иначе во время исполнения возникнет ошибка \texttt{badarg}. Также 374 | сегмент с типом \texttt{binary} должен иметь размер, делящийся нацело на 8. 375 | 376 | Двоичные данные не могут вкладываться друг в друга. 377 | 378 | \begin{erlang} 379 | <<1, 17, 42>> % <<1, 17, 42>> 380 | <<"abc">> % <<97, 98, 99>> (То же, что и <<$a, $b, $c>>) 381 | <<1, 17, 42:16>> % <<1,17,0,42>> 382 | <<>> % <<>> 383 | <<15:8/unit:10>> % <<0,0,0,0,0,0,0,0,0,15>> 384 | <<(-1)/unsigned>> % <<255>> 385 | \end{erlang} 386 | 387 | 388 | \section{Escape-последовательности} 389 | \label{datatypes:escapeseq} 390 | 391 | Escape-последовательности разрешено использовать в строках и атомах, которые 392 | заключены в кавычки, они позволяют ввести в исходный текст программы символ, 393 | который другим способом ввести трудно или невозможно. 394 | 395 | \begin{center} 396 | \begin{tabular}{|>{\raggedright}p{90pt}|>{\raggedright}p{280pt}|} 397 | \hline 398 | \multicolumn{2}{|p{321pt}|}{Escape-последовательности}\tabularnewline 399 | \hline 400 | \textbackslash{}b & Backspace (удаление слева)\tabularnewline 401 | \hline 402 | \textbackslash{}d & Delete (удаление справа)\tabularnewline 403 | \hline 404 | \textbackslash{}e & Escape\tabularnewline 405 | \hline 406 | \textbackslash{}f & Новая страница (при печати)\tabularnewline 407 | \hline 408 | \textbackslash{}n & Новая строка\tabularnewline 409 | \hline 410 | \textbackslash{}r & Возврат курсора в начало\tabularnewline 411 | \hline 412 | \textbackslash{}s & Пробел\tabularnewline 413 | \hline 414 | \textbackslash{}t & Табуляция\tabularnewline 415 | \hline 416 | \textbackslash{}v & Вертикальная табуляция\tabularnewline 417 | \hline 418 | \textbackslash{}XYZ, \textbackslash{}XY, \textbackslash{}X & 419 | Символ, записанный в восьмеричном представлении, как XYZ, XY или X\tabularnewline 420 | \hline 421 | \textbackslash{}\textasciicircum{}A .. \textbackslash{}\textasciicircum{}Z & 422 | Комбинации клавиш от Ctrl-A до Ctrl-Z\tabularnewline 423 | \hline 424 | \textbackslash{}\textasciicircum{}a .. \textbackslash{}\textasciicircum{}z & 425 | Комбинации клавиш от Ctrl-A до Ctrl-Z\tabularnewline 426 | \hline 427 | \textbackslash{}' & Единичная кавычка \tabularnewline 428 | \hline 429 | \textbackslash{}\textbf{\texttt{"}} & Двойная кавычка \tabularnewline 430 | \hline 431 | \textbackslash{}\textbackslash{} & Обратная косая черта (\textbackslash) 432 | \tabularnewline 433 | \hline 434 | \end{tabular} 435 | \end{center} 436 | 437 | 438 | \section{Преобразования типов} 439 | 440 | Erlang --- строго типизированный язык, то есть неявные автоматические 441 | преобразования типов в нём не происходят. Но есть ряд встроенных в стандартную 442 | библиотеку функций, предназначенных для преобразования между типами данных 443 | при участии программиста: 444 | 445 | \begin{center} 446 | \begin{tabular}{|>{\raggedright}p{63pt}|>{\raggedright}p{30pt}|>{\raggedright}p{35pt}|>{\raggedright}p{21pt}|>{\raggedright}p{21pt}|>{\raggedright}p{21pt}|>{\raggedright}p{30pt}|>{\raggedright}p{21pt}|>{\raggedright}p{35pt}|} 447 | \hline 448 | \multicolumn{9}{|p{243pt}|}{Преобразования типов}\tabularnewline 449 | \hline 450 | & atom & integer & float & pid & fun & tuple & list & binary\tabularnewline 451 | \hline 452 | atom & & - & - & - & - & - & X & X\tabularnewline 453 | \hline 454 | integer & - & & X & - & - & - & X & X\tabularnewline 455 | \hline 456 | float & - & X & & - & - & - & X & X\tabularnewline 457 | \hline 458 | pid & - & - & - & & - & - & X & X\tabularnewline 459 | \hline 460 | fun & - & - & - & - & & - & X & X\tabularnewline 461 | \hline 462 | tuple & - & - & - & - & - & & X & X\tabularnewline 463 | \hline 464 | list & X & X & X & X & X & X & & X\tabularnewline 465 | \hline 466 | binary & X & X & X & X & X & X & X & \tabularnewline 467 | \hline 468 | \end{tabular} 469 | \end{center} 470 | 471 | Встроенная функция \texttt{float/1} переводит целые числа в числа с 472 | плавающей точкой. Встроенные функции \texttt{round/1} и \texttt{trunc/1} 473 | переводят числа с плавающей точкой обратно в целые, округляя или отбрасывая 474 | дробную часть. 475 | 476 | Функции \texttt{Тип\_to\_list/1} и \texttt{list\_to\_Тип/1} 477 | переводят различные типы в списки (строки) и из списков. 478 | 479 | Функции \texttt{term\_to\_binary/1} и \texttt{binary\_to\_term/1} переводят 480 | любое значение в закодированную двоичную форму и обратно (Подробнее: 481 | \url{http://erlang.org/doc/apps/erts/erl_ext_dist.html}). 482 | 483 | \begin{erlang} 484 | atom_to_list(hello) % "hello" 485 | list_to_atom("hello") % hello 486 | float_to_list(7.0) % "7.00000000000000000000e+00" 487 | list_to_float("7.000e+00") % 7.00000 488 | integer_to_list(77) % "77" 489 | list_to_integer("77") % 77 490 | tuple_to_list({a, b ,c}) % [a,b,c] 491 | list_to_tuple([a, b, c]) % {a,b,c} 492 | pid_to_list(self()) % "<0.25.0>" 493 | term_to_binary(<<17>>) % <<131,109,0,0,0,1,17>> 494 | term_to_binary({a, b ,c}) % <<131,104,3,100,0,1,97,100,0,1,98, 495 | % 100,0,1,99>> 496 | binary_to_term(<<131,104,3,100,0,1,97,100,0,1,98,100,0,1,99>>) 497 | % {a,b,c} 498 | term_to_binary(math:pi()) % <<131,99,51,46,49,52,49,53,57,50,... 499 | \end{erlang} 500 | % 54,53,51,...>> 501 | 502 | -------------------------------------------------------------------------------- /chapters-RU/04-pattern-matching.tex: -------------------------------------------------------------------------------- 1 | \chapter{Сопоставление с образцом} 2 | \label{patterns} 3 | 4 | \section{Переменные} 5 | \label{patterns:variables} 6 | 7 | \textbf{Переменные} представлены, как аргументы функции или как результат 8 | сопоставления с образцом. Переменные начинаются с заглавной буквы или символа 9 | подчёркивания (\texttt{\_}) и могут содержить буквенно-цифровые символы, 10 | подчёркивания и символы \emph{at} (\texttt{@}). Переменные могут быть связаны со 11 | значением (присвоены) только один раз. 12 | 13 | \begin{erlang} 14 | Abc 15 | A_long_variable_name 16 | AnObjectOrientatedVariableName 17 | _Height 18 | \end{erlang} 19 | 20 | \textbf{Анонимная переменная} объявляется с помощью одного символа подчёркивания 21 | (\texttt{\_}) и может использоваться там, где требуется переменная, но её значение 22 | нас не интересует и может быть проигнорировано. 23 | 24 | \begin{erlang} 25 | [H|_] = [1,2,3] % H=1 и всё остальное игнорируется 26 | \end{erlang} 27 | 28 | Переменные, начинающиеся с символа подчёркивания, как, например, 29 | \texttt{\_Height}, являются обычными не анонимными переменными. Однако они 30 | игнорируются компилятором в том смысле, что они не произведут предупреждений 31 | компилятора о неиспользуемых переменных. Таким образом, возможна следующая 32 | запись: 33 | 34 | \begin{erlang} 35 | member(_Elem, []) -> 36 | false. 37 | \end{erlang} 38 | 39 | вместо: 40 | 41 | \begin{erlang} 42 | member(_, []) -> 43 | false. 44 | \end{erlang} 45 | 46 | что улучшает читаемость кода. 47 | 48 | \textit{Область видимости} для переменной --- это её уравнение функции. 49 | Переменные, связанные со значением в ветке \texttt{if}, \texttt{case} или 50 | \texttt{receive}, должны быть связаны с чем-нибудь во всех ветвях этого 51 | оператора, чтобы иметь значение за пределами выражения, иначе компилятор будет 52 | считать это значение \textit{небезопасным} (unsafe) (вероятно, не присвоенным) 53 | за пределами этого выражения, и выдаст соответствующее предупреждение. 54 | 55 | 56 | \section{Сопоставление с образцом} 57 | 58 | \textbf{Образец} имеет такую же структуру, как и терм, но может содержать новые 59 | свободные переменные. Например: 60 | 61 | \begin{erlang} 62 | Name1 63 | [H|T] 64 | {error,Reason} 65 | \end{erlang} 66 | 67 | Образцы могут встречаться в \textit{заголовках функций}, выражениях 68 | \textit{case}, \textit{receive}, и \textit{try} и в выражениях оператора 69 | сопоставления (\texttt{=}). Образцы вычисляются посредством 70 | \textbf{сопоставления образца} с выражением, и таким образом новые переменные 71 | определяются и связываются со значением. 72 | 73 | \begin{erlangru} 74 | Образец = Выражение 75 | \end{erlangru} 76 | 77 | Обе стороны выражения должны иметь одинаковую структуру. Если сопоставление 78 | проходит успешно, то все свободные переменные (если такие были) в образце слева 79 | становятся связанными. Если сопоставление не проходит, то возникает ошибка 80 | времени исполнения \texttt{badmatch}. 81 | 82 | \begin{erlang} 83 | 1> {A, B} = {answer, 42}. 84 | {answer,42} 85 | 2> A. 86 | answer 87 | 3> B. 88 | 42 89 | 90 | \end{erlang} 91 | 92 | 93 | \subsection{Оператор сопоставления (\texttt{=}) в образцах} 94 | 95 | Если \texttt{Образец1} и \texttt{Образец2} являются действительными образцами, тогда следующая запись тоже действительный образец: 96 | 97 | \begin{erlangru} 98 | Образец1 = Образец2 99 | \end{erlangru} 100 | 101 | Оператор \texttt{=} представляет собой \textbf{подмену} (alias), при 102 | сопоставлении которой с выражением, оба и \texttt{Образец1} и \texttt{Образец2} 103 | также сопоставляются с ней. Цель этого --- избежать необходимости повторно 104 | строить термы, которые были разобраны на составляющие в сопоставлении. 105 | 106 | \begin{erlang} 107 | foo({connect,From,To,Number,Options}, To) -> 108 | Signal = {connect,From,To,Number,Options}, 109 | fox(Signal), 110 | ...; 111 | \end{erlang} 112 | 113 | можно более эффективно записать, как: 114 | 115 | \begin{erlang} 116 | foo({connect,From,To,Number,Options} = Signal, To) -> 117 | fox(Signal), 118 | ...; 119 | \end{erlang} 120 | 121 | 122 | \subsection{Строковой префикс в образцах} 123 | 124 | При сопоставлении строк с образцом, следующая запись является действительным 125 | образцом: 126 | 127 | \begin{erlang} 128 | f("prefix" ++ Str) -> ... 129 | \end{erlang} 130 | 131 | что эквивалентно и легче читается, чем следующая запись: 132 | 133 | \begin{erlang} 134 | f([$p,$r,$e,$f,$i,$x | Str]) -> ... 135 | \end{erlang} 136 | 137 | Вы можете использовать строки только как префикс; варианты с постфиксом для 138 | образцов, такие как \texttt{Str ++ "postfix"} не разрешаются. 139 | 140 | 141 | \subsection{Выражения в образцах} 142 | 143 | Арифметическое выражение может быть использовано внутри образца, если оно 144 | использует только числовые, битовые операторы, и его значение является 145 | константой, которая может быть вычислена во время компиляции. 146 | 147 | \begin{erlang} 148 | case {Value, Result} of 149 | {?Threshold+1, ok} -> ... % ?Threshold - это макрос 150 | \end{erlang} 151 | 152 | 153 | \subsection{Сопоставление двоичных данных} 154 | 155 | \begin{erlang} 156 | Bin = <<1, 2, 3>> % <<1,2,3>> Все элементы - 8-битные байты 157 | <> = Bin % A=1, B=2 и C=3 158 | <> = Bin % D=258 и E=3 159 | <> = Bin % F=1 и G=<<2,3>> 160 | \end{erlang} 161 | 162 | В последней строке переменная \texttt{G} неуказанного размера сопоставляется с 163 | остатком двоичных данных \texttt{Bin}. 164 | 165 | Всегда ставьте пробел между оператором (\texttt{=}) и (\verb|<<|), чтобы 166 | избежать возможной путаницы с оператором (\texttt{=<}). 167 | 168 | -------------------------------------------------------------------------------- /chapters-RU/05-functions.tex: -------------------------------------------------------------------------------- 1 | \chapter{Функции} 2 | 3 | \section{Определение функции} 4 | 5 | Функция определяется, как последовательность из одного или нескольких 6 | \textbf{уравнений функции}. Имя функции должно быть атомом. 7 | 8 | \vspace*{4pt} 9 | \begin{erlangru} 10 | Функция(Образец11,...,Образец1N) 11 | [when ОхранныеВыражения1] -> ТелоФункции1; 12 | ...; 13 | ...; 14 | Функция(ОбразецK1,...,ОбразецKN) 15 | [when ОхранныеВыраженияK] -> ТелоФункцииK. 16 | \end{erlangru} 17 | \vspace*{4pt} 18 | 19 | Уравнения функции разделены точками с запятой (\texttt{;}) и последнее уравнение 20 | завершается точкой (\texttt{.}). Уравнение функции состоит из \textbf{заголовка 21 | уравнения} и \textbf{тела уравнения функции}, разделённых стрелкой 22 | (\texttt{->}). 23 | 24 | Заголовок уравнения состоит из имени функции (атома), списка аргументов, 25 | заключённого в скобки, и необязательного списка охранных выражений, начинающихся 26 | с ключевого слова \texttt{when}. Каждый аргумент функции --- образец. Тело 27 | функции состоит из последовательности выражений, разделённых запятыми (\texttt{,}). 28 | 29 | \vspace*{4pt} 30 | \begin{erlangru} 31 | Выражение1, 32 | ..., 33 | ВыражениеM 34 | \end{erlangru} 35 | \vspace*{4pt} 36 | 37 | Количество аргументов \texttt{N} ещё называется \textbf{арностью} функции. 38 | Функция уникально определяется именем модуля, именем функции и своей арностью. 39 | Две разные функции в одном модуле, имеющие разную арность, могут иметь одно и то 40 | же имя. \texttt{Функция} в \texttt{Модуле} с арностью \texttt{N} часто может 41 | записываться так: \texttt{Модуль:Функция/N}. 42 | 43 | \vspace*{4pt} 44 | \begin{erlang} 45 | -module(mathStuff). 46 | -export([area/1]). 47 | 48 | area({square, Side}) -> Side * Side; 49 | area({circle, Radius}) -> math:pi() * Radius * Radius; 50 | area({triangle, A, B, C}) -> 51 | S = (A + B + C)/2, 52 | math:sqrt(S*(S-A)*(S-B)*(S-C)). 53 | \end{erlang} 54 | 55 | 56 | % push this section onto the next page (orphan line) 57 | \newpage 58 | 59 | 60 | \section{Вызовы функций} 61 | 62 | Функция вызывается с помощью записи: 63 | 64 | \begin{erlangru} 65 | [Модуль:]Функция(Выражение1, ..., ВыражениеN) 66 | \end{erlangru} 67 | 68 | Выражение \texttt{Модуль} должно вычисляться в имя модуля (или быть атомом) и 69 | выражение \texttt{Функция} должно вычисляться в имя функции или в 70 | \emph{анонимную функцию}. При вызове функции в другом модуле, следует указать 71 | имя модуля и функция должна быть экспортирована. Такой вызов будет называться 72 | \textbf{полностью определённым вызовом функции}. 73 | 74 | \begin{erlang} 75 | lists:keysearch(Name, 1, List) 76 | \end{erlang} 77 | 78 | Имя модуля может быть опущено, если \texttt{Функция} вычисляется в имя 79 | локальной функции, импортированной функции или авто-импортированной встроенной 80 | (BIF) функции. Такой вызов называется \textbf{неявно определённым вызовом 81 | функции}. 82 | 83 | Перед тем, как вызвать функцию, вычисляются аргументы \texttt{ExprX}. Если 84 | функция не может быть найдена, то возникает ошибка времени исполнения 85 | \texttt{undef}. Если уравнений функции несколько, они последовательно 86 | сканируются до тех пор, пока не будет найдено подходящее уравнение, такое, что 87 | образцы в заголовке уравнения успешно могут быть сопоставлены с данными 88 | аргументами и что охранное выражение (если оно задано) равно \texttt{true}. 89 | Если такое уравнение не может быть найдено, возникает ошибка времени исполнения 90 | \texttt{function\_clause}. 91 | 92 | Если совпадающее уравнение найдено, то вычисляется соответствующее тело 93 | \linebreak 94 | функции, то есть выражения в теле функции вычисляются одно за другим и 95 | возвращается результат последнего выражения. 96 | 97 | Полностью определённое имя функции должно быть использовано, если вызывается 98 | встроенная функция с таким же именем (см. секцию \ref{functions:bifs} о 99 | встроенных BIF функциях). Компилятор не разрешит определить функцию с таким же 100 | именем, как другая импортированная функция. При вызове локальной функции есть 101 | разница между использованием неявно или полностью определённого имени функции, 102 | поскольку второе всегда относится к последней версии модуля (см. главу 103 | \ref{code} о модулях и версиях). 104 | 105 | 106 | \section{Выражения} 107 | \label{functions:expressions} 108 | 109 | \textbf{Выражение} это терм либо вызов оператора, результатом которого будет 110 | терм, например: 111 | 112 | \begin{erlangru} 113 | Терм 114 | операция Выражение 115 | Выражение1 операция Выражение2 116 | (Выражение) 117 | begin 118 | Выражение1, 119 | ..., 120 | ВыражениеM % нет запятой (,) перед end 121 | end 122 | \end{erlangru} 123 | 124 | В наличии имеются как \emph{унарные} так и \emph{бинарные} операторы. Простейшая 125 | форма выражения --- это терм, например \emph{целое число}, \emph{число с 126 | плавающей точкой}, \emph{атом}, \emph{строка}, \emph{список} или \emph{кортеж}, 127 | и возвращаемое оператором значение тоже терм. Выражение может содержать 128 | \emph{макрос} или операции над \emph{записью}, которые будут развёрнуты во 129 | время компиляции. 130 | 131 | Выражения в скобках полезны для изменения порядка вычисления операторов (см. 132 | раздел \ref{functions:expressions:precedence}): 133 | 134 | \begin{erlang} 135 | 1 + 2 * 3 % 7 136 | (1 + 2) * 3 % 9 137 | \end{erlang} 138 | 139 | Блочные выражения, заключённые в операторные скобки между \texttt{begin...end}, 140 | могут использоваться для группировки последовательности выражений и возвращают 141 | значение, равное значению последнего выражения внутри \texttt{ВыражениеM}. 142 | 143 | Все вложенные подвыражения вычисляются до главного выражения, но порядок, в 144 | котором происходит вычисление вложенных, не определён стандартом. 145 | 146 | Многие операторы могут применяться только к аргументам определённого типа. 147 | Например, арифметические операторы могут только применяться к целым числам или 148 | числам с плавающей точкой. Аргумент неверного типа вызовет ошибку времени 149 | выполнения \texttt{badarg}. 150 | 151 | 152 | \subsection{Сравнение термов} 153 | 154 | \begin{verbatim} 155 | Выражение1 оператор Выражение2 156 | \end{verbatim} 157 | 158 | \textbf{Сравнение термов} возвращает \emph{булево} (логическое) значение, в 159 | форме атомов \texttt{true} или \texttt{false}. 160 | 161 | \begin{center} 162 | \begin{tabular}{|>{\raggedright}p{40pt}|>{\raggedright}p{185pt}|>{\raggedright}p{26pt}|>{\raggedright}p{135pt}|} 163 | \hline 164 | \multicolumn{4}{|p{297pt}|}{Операторы сравнения}\tabularnewline 165 | \hline 166 | \texttt{==} & Равно (с приведением типа) & 167 | \texttt{=<} & Меньше или равно \tabularnewline 168 | \hline 169 | \texttt{/=} & Не равно (с приведением типа) & 170 | \texttt{<} & Меньше, чем \tabularnewline 171 | \hline 172 | \texttt{=:=} & Точно равно (с учётом типа) & 173 | \texttt{>}= & Больше или равно \tabularnewline 174 | \hline 175 | \texttt{=/=} & Точно не равно (с учётом типа) & 176 | \texttt{>} & Больше, чем \tabularnewline 177 | \hline 178 | \end{tabular} 179 | \end{center} 180 | 181 | \begin{erlang} 182 | 1==1.0 % true 183 | 1=:=1.0 % false 184 | 1 > a % false 185 | \end{erlang} 186 | 187 | Аргументы оператора сравнения могут иметь разные типы данных. В таком случае 188 | действует следующий порядок сравнения: 189 | 190 | \texttt{число < атом < ссылка < анонимная функция < порт < pid < кортеж < 191 | список < двоичные данные} 192 | 193 | Списки сравниваются поэлементно. Кортежи сравниваются по размеру, два кортежа 194 | одного размера сравниваются поэлементно. При сравнении целого числа и числа с 195 | плавающей точкой, целое сначала приводится к числу с плавающей точкой. В случае 196 | использования точного равенства \texttt{=:=} или \texttt{=/=} тип числа не 197 | изменяется и учитывается в равенстве. 198 | 199 | 200 | \subsection{Арифметические выражения} 201 | 202 | \begin{erlangru} 203 | оператор Выражение 204 | Выражение1 оператор Выражение2 205 | \end{erlangru} 206 | 207 | \textbf{Арифметическое выражение} возвращает результат после применения 208 | оператора. 209 | 210 | \begin{center} 211 | \begin{tabular}{|>{\raggedright}p{35pt}|>{\raggedright}p{185pt}|>{\raggedright}p{128pt}|} 212 | \hline 213 | \multicolumn{3}{|p{309pt}|}{Арифметические операторы}\tabularnewline 214 | \hline 215 | \texttt{+} & Унарный плюс & 216 | \texttt{Integer} \textbar{} \texttt{Float} \tabularnewline 217 | \hline 218 | \texttt{-} & Унарный минус & 219 | \texttt{Integer} \textbar{} \texttt{Float} \tabularnewline 220 | \hline 221 | \texttt{+} & Сложение & 222 | \texttt{Integer} \textbar{} \texttt{Float}\tabularnewline 223 | \hline 224 | \texttt{-} & Вычитание & 225 | \texttt{Integer} \textbar{} \texttt{Float}\tabularnewline 226 | \hline 227 | \texttt{*} & Умножение & 228 | \texttt{Integer} \textbar{} \texttt{Float}\tabularnewline 229 | \hline 230 | \texttt{/} & Деление с плавающей точкой & 231 | \texttt{Integer} \textbar{} \texttt{Float}\tabularnewline 232 | \hline 233 | \texttt{bnot} & Унарное битовое НЕ & 234 | \texttt{Integer} \tabularnewline 235 | \hline 236 | \texttt{div} & Целочисленное деление & 237 | \texttt{Integer}\tabularnewline 238 | \hline 239 | \texttt{rem} & Целочисленный остаток от деления X на Y & 240 | \texttt{Integer} \tabularnewline 241 | \hline 242 | \texttt{band} & Битовое И & \texttt{Integer}\tabularnewline 243 | \hline 244 | \texttt{bor} & Битовое ИЛИ & \texttt{Integer} \tabularnewline 245 | \hline 246 | \texttt{bxor} & Исключающее битовое ИЛИ & 247 | \texttt{Integer}\tabularnewline 248 | \hline 249 | \texttt{bsl} & Арифметический (с учётом знака) битовый сдвиг влево & 250 | \texttt{Integer} \tabularnewline 251 | \hline 252 | \texttt{bsr} & Битовый сдвиг вправо & 253 | \texttt{Integer}\tabularnewline 254 | \hline 255 | \end{tabular} 256 | \end{center} 257 | 258 | \begin{erlang} 259 | +1 % 1 260 | 4/2 % 2.00000 261 | 5 div 2 % 2 262 | 5 rem 2 % 1 263 | 2#10 band 2#01 % 0 264 | 2#10 bor 2#01 % 3 265 | \end{erlang} 266 | 267 | 268 | \subsection{Логические (булевы) выражения} 269 | 270 | \begin{erlangru} 271 | оператор Выражение 272 | Выражение1 оператор Выражение2 273 | \end{erlangru} 274 | 275 | \textbf{Логическое выражение} возвращает значение \texttt{true} или 276 | \texttt{false} после применения оператора. 277 | 278 | \begin{center} 279 | \begin{tabular}{|>{\raggedright}p{79pt}|>{\raggedright}p{241pt}|} 280 | \hline 281 | \multicolumn{2}{|p{321pt}|}{Логические (булевы) операторы}\tabularnewline 282 | \hline 283 | \texttt{not} & Унарное логическое НЕ (отрицание) \tabularnewline 284 | \hline 285 | \texttt{and} & Логическое И \tabularnewline 286 | \hline 287 | \texttt{or} & Логическое ИЛИ \tabularnewline 288 | \hline 289 | \texttt{xor} & Логическое исключающее ИЛИ \tabularnewline 290 | \hline 291 | \end{tabular} 292 | \end{center} 293 | 294 | \begin{erlang} 295 | not true % false 296 | true and false % false 297 | true xor false % true 298 | \end{erlang} 299 | 300 | 301 | \subsection{Умные логические выражения} 302 | 303 | \begin{erlangru} 304 | Выражение1 orelse Выражение2 305 | Выражение1 andalso Выражение2 306 | \end{erlangru} 307 | 308 | В этих логические выражениях второй операнд вычисляется только в том случае, 309 | если его значение необходимо для конечного результата. В случае с 310 | \texttt{orelse} \texttt{Выражение2} будет вычислено, только если 311 | \texttt{Выражение1} равняется \texttt{false}. В случае с \texttt{andalso} 312 | \texttt{Выражение2} будет вычислено, только если \texttt{Выражение1} равняется 313 | \texttt{true}. 314 | 315 | \begin{erlang} 316 | if A >= 0 andalso math:sqrt(A) > B -> ... 317 | 318 | if is_list(L) andalso length(L) == 1 -> ... 319 | \end{erlang} 320 | 321 | 322 | \subsection{Приоритет операторов} 323 | \label{functions:expressions:precedence} 324 | 325 | В выражении, состоящем из подвыражений, операторы будут применяться согласно 326 | определённому порядку, который называется \textbf{приоритетом операторов}: 327 | 328 | \begin{center} 329 | \begin{tabular}{|>{\raggedright}p{221pt}|>{\raggedright}p{125pt}|} 330 | \hline 331 | \multicolumn{2}{|p{321pt}|}{Приоритет операторов (от высшего к низшему)} \tabularnewline 332 | \hline 333 | \texttt{:} ~ & \tabularnewline 334 | \hline 335 | \texttt{\#} ~ & \tabularnewline 336 | \hline 337 | \texttt{Unary + - bnot not ~} & \tabularnewline 338 | \hline 339 | \texttt{/ * div rem band and} & Левоассоциативный \tabularnewline 340 | \hline 341 | \texttt{+ - bor bxor bsl bsr or xor} & Левоассоциативный \tabularnewline 342 | \hline 343 | \texttt{++ -{}-} & Правоассоциативный \tabularnewline 344 | \hline 345 | \texttt{== /= =< < >= > =:= =/=} & \tabularnewline 346 | \hline 347 | \texttt{andalso} & \tabularnewline 348 | \hline 349 | \texttt{orelse} & \tabularnewline 350 | \hline 351 | \texttt{= !} & Правоассоциативный \tabularnewline 352 | \hline 353 | \texttt{catch ~} & \tabularnewline 354 | \hline 355 | \end{tabular} 356 | \end{center} 357 | 358 | Оператор с наивысшим приоритетом вычисляется первым. Операторы с одинаковым 359 | приоритетом вычисляются согласно их \textbf{ассоциативности}. Левоассоциативные 360 | операторы вычисляются слева направо, правоассоциативные --- наоборот, справа 361 | налево: 362 | 363 | \texttt{6 + 5 * 4 - 3 / 2 \resultingin 6 + 20 - 1.5 \resultingin 26 - 1.5 364 | \resultingin 24.5} 365 | 366 | 367 | 368 | \section{Составные выражения} 369 | 370 | 371 | \subsection{If} 372 | 373 | \begin{erlangru} 374 | if 375 | ОхранноеВыражение1 -> 376 | Тело1; 377 | ...; 378 | ОхранноеВыражениеN -> 379 | ТелоN % Заметьте, нет точки с запятой (;) перед end 380 | end 381 | \end{erlangru} 382 | 383 | Ветки выражения \texttt{if} сканируются последовательно сверху вниз, пока не 384 | встретится \texttt{ОхранноеВыражениеX}, результатом которого будет 385 | \texttt{true}. Соотвествующее \texttt{ТелоX} (последовательность выражений, 386 | разделённых запятыми) будет вычислено. Возвращаемое \texttt{ТеломX} значение 387 | будет результатом всего выражения \texttt{if}. 388 | 389 | Если ни одно из охранных выражений не вычисляется в \texttt{true}, то возникнет 390 | ошибка времени выполнения \texttt{if\_clause}. При необходимости можно 391 | использовать\linebreak 392 | охранное выражение \texttt{true} в последней ветке \texttt{if}, 393 | поскольку такое охранное выражение всегда срабатывает, если другие не сработали 394 | и называется "<срабатывающим для всех значений"> (catch all). 395 | 396 | \begin{erlang} 397 | is_greater_than(X, Y) -> 398 | if 399 | X>Y -> 400 | true; 401 | true -> % работает как ветка 'else' 402 | false 403 | end 404 | \end{erlang} 405 | 406 | Следует заметить, что сопоставление с образцом в уравнениях функций может почти 407 | всегда использоваться для замены \texttt{if}. Чрезмерное использование 408 | \texttt{if} внутри функций считается плохой практикой. 409 | 410 | 411 | \subsection{Case} 412 | 413 | Выражения \texttt{case} используются для сопоставления с образцом прямо в коде, 414 | подобно тому, как сопоставляются аргументы в заголовках функций. 415 | 416 | \begin{erlangru} 417 | case Выражение of 418 | Выражение1 [when ОхранноеВыражение1] -> 419 | Тело1; 420 | ...; 421 | ВыражениеN [when ОхранноеВыражениеN] -> 422 | ТелоN % Заметьте, нет точки с запятой (;) перед end 423 | end 424 | \end{erlangru} 425 | 426 | \texttt{Выражение} вычисляется и \texttt{Образец1}...\texttt{ОбразецN} 427 | последовательно сопоставляются с результатом. Если сопоставление проходит 428 | успешно, и необязательное \texttt{Охран\-ное\-ВыражениеХ} равно \texttt{true}, 429 | тогда вычисляется соответствующее \texttt{ТелоХ}. Возвращаемое значение 430 | \texttt{ТелаХ} является результатом всего выражения \texttt{case}. 431 | 432 | В случае, если ни один из образцов и их охранных выражений не подходит, 433 | возникает ошибка времени выполнения \texttt{case\_clause}. 434 | 435 | \begin{erlang} 436 | is_valid_signal(Signal) -> 437 | case Signal of 438 | {signal, _What, _From, _To} -> 439 | true; 440 | {signal, _What, _To} -> 441 | true; 442 | _Else -> % 'catch all' 443 | false 444 | end. 445 | \end{erlang} 446 | 447 | 448 | \subsection{Генераторы списков} 449 | 450 | Генераторы списков аналогичны предикатам \texttt{setof} и \texttt{findall} 451 | в языке Prolog. 452 | 453 | \begin{erlangru} 454 | [Выражение || Квалификатор1,...,КвалификаторN] 455 | \end{erlangru} 456 | 457 | \texttt{Выражение} --- произвольное выражение, и каждый 458 | \texttt{КвалификаторX} --- это либо \textbf{генератор} (источник данных) 459 | либо \textbf{фильтр}. Генератор записывается, как: 460 | 461 | \begin{erlangru} 462 | Образец <- ВыражениеСписок 463 | \end{erlangru} 464 | 465 | где \texttt{ВыражениеСписок} должно быть выражением, результатом которого 466 | является список термов. Фильтр --- это выражение, результатом которого является 467 | \texttt{true} или \texttt{false}. Переменные внутри генератора списков 468 | \emph{затеняют} переменные с такими же именами, принадлежащие функции, 469 | окружающей генератор. 470 | 471 | Квалификаторы вычисляются слева направо, генераторы создают значения и\linebreak 472 | фильтры отбирают нужные из них. Генератор списков возвращает список, в котором 473 | элементы являются результатом вычисления \texttt{Выражения} для каждой 474 | комбинации результирующих значений. 475 | 476 | \begin{erlang} 477 | 1> [{X, Y} || X <- [1,2,3,4,5,6], X > 4, Y <- [a,b,c]]. 478 | [{5,a},{5,b},{5,c},{6,a},{6,b},{6,c}] 479 | \end{erlang} 480 | 481 | 482 | \section{Охранные последовательности} 483 | 484 | \textbf{Охранная последовательность} --- это набор \textbf{охранных выражений}, 485 | разделённых точками с запятой (\texttt{;}). Охранная последовательность 486 | равняется \texttt{true}, если как минимум одно из составляющих её охранных 487 | выражений равно \texttt{true}. 488 | 489 | \begin{erlangru} 490 | Охрана1; ...; ОхранаK 491 | \end{erlangru} 492 | 493 | \textbf{Охрана} --- это множество \textbf{охранных выражений}, разделённых 494 | запятыми (\texttt{,}). Результатом будет \texttt{true} если все охранные 495 | выражения равняются \texttt{true}. 496 | 497 | \begin{erlangru} 498 | ОхранноеВыражение1, ..., ОхранноеВыражениеN 499 | \end{erlangru} 500 | 501 | В \textbf{охранных выражениях}, которые иногда ещё называются охранными тестами, 502 | разрешены не любые выражения Erlang, а ограниченный набор, выбранный авторами 503 | Erlang, поскольку важно, чтобы ход вычисления охранного выражения не имел 504 | побочных эффектов. 505 | 506 | \begin{center} 507 | \begin{tabular}{|>{\raggedright}p{210pt}|>{\raggedright}p{210pt}|} 508 | \hline 509 | 510 | \multicolumn{2}{|p{420pt}|}{Разрешённые охранные выражения:}\tabularnewline 511 | \hline 512 | \multicolumn{2}{|p{420pt}|}{Атом \texttt{true}; Другие константы (термы, 513 | связанные переменные), все считаются равными \texttt{false};}\tabularnewline 514 | \hline 515 | \multicolumn{2}{|p{420pt}|}{Сравнения термов; Арифметические и логические 516 | выражения; Вызовы встроенных (BIF) функций, перечисленные ниже:} 517 | \tabularnewline 518 | %\multicolumn{2}{|p{420pt}|}{Разрешённые охранные выражения:}\tabularnewline 519 | %\hline 520 | %\multicolumn{2}{|p{420pt}|}{Атом \texttt{true};}\tabularnewline 521 | %\hline 522 | %\multicolumn{2}{|p{420pt}|}{Другие константы (термы, связанные переменные), все 523 | % считаются равными \texttt{false};}\tabularnewline 524 | %\hline 525 | %\multicolumn{2}{|p{420pt}|}{Сравнения термов;}\tabularnewline 526 | %\hline 527 | %\multicolumn{2}{|p{420pt}|}{Арифметические и логические 528 | % выражения;}\tabularnewline 529 | %\hline 530 | %\multicolumn{2}{|p{420pt}|}{Вызовы встроенных (BIF) функций, перечисленные 531 | % ниже:}\tabularnewline 532 | 533 | \hline 534 | Функции проверки типа & Другие позволенные функции:\tabularnewline 535 | \hline 536 | \texttt{is\_atom/1} & \texttt{abs(Integer} \textbar{} \texttt{Float)}\tabularnewline 537 | \hline 538 | \texttt{is\_constant/1} & \texttt{float(Term)}\tabularnewline 539 | \hline 540 | \texttt{is\_integer/1} & \texttt{trunc(Integer} \textbar{} \texttt{Float)}\tabularnewline 541 | \hline 542 | \texttt{is\_float/1} & \texttt{round(Integer} \textbar{} \texttt{Float)}\tabularnewline 543 | \hline 544 | \texttt{is\_number/1} & \texttt{size(Tuple} \textbar{} \texttt{Binary)}\tabularnewline 545 | \hline 546 | \texttt{is\_reference/1} & \texttt{element(N, Tuple)}\tabularnewline 547 | \hline 548 | \texttt{is\_port/1} & \texttt{hd(List)}\tabularnewline 549 | \hline 550 | \texttt{is\_pid/1} & \texttt{tl(List)}\tabularnewline 551 | \hline 552 | \texttt{is\_function/1} & \texttt{length(List)}\tabularnewline 553 | \hline 554 | \texttt{is\_tuple/1} & \texttt{self()}\tabularnewline 555 | \hline 556 | \texttt{is\_record/2} Второй аргумент имя записи & 557 | \texttt{node(})\tabularnewline 558 | \hline 559 | \texttt{is\_list/1} & \texttt{node(Pid} \textbar{} \texttt{Ref} \textbar 560 | \texttt{Port)}\tabularnewline 561 | \hline 562 | \texttt{is\_binary/1} & \tabularnewline 563 | \hline 564 | \end{tabular} 565 | \end{center} 566 | 567 | Небольшой пример 568 | 569 | \begin{erlang} 570 | fact(N) when N>0 -> % Заголовок первого уравнения 571 | N * fact(N-1); % Тело первого уравнения 572 | fact(0) -> % Заголовок второго уравнения 573 | 1. % Тело второго уравнения 574 | \end{erlang} 575 | 576 | 577 | \section{Хвостовая рекурсия} 578 | 579 | Если последнее выражение тела функции является вызовом функции, то выполняется 580 | \textbf{хвостовой рекурсивный} вызов так, что ресурсы системы (например, стек 581 | вызовов) не расходуются. Это означает, что можно создать бесконечный цикл, 582 | такой, как, например, сервер, если использовать хвостовые рекурсивные вызовы. 583 | 584 | Функция \texttt{fact/1} выше может быть переписана для использования хвостовой 585 | рекурсии следующим образом: 586 | 587 | \begin{erlang} 588 | fact(N) when N>1 -> fact(N, N-1); 589 | fact(N) when N==1; N==0 -> 1. 590 | 591 | fact(F,0) -> F; % Переменная F используется как аккумулятор 592 | fact(F,N) -> fact(F*N, N-1). 593 | \end{erlang} 594 | 595 | 596 | 597 | \section{Анонимные функции} 598 | \label{functions:funs} 599 | 600 | Ключевое слово \textbf{fun} определяет \emph{функциональный объект}. Анонимные 601 | функции делают возможным передавать целую функцию, а не только её имя, в 602 | качестве аргумента. Выражение, определяющее анонимную функцию, начинается с 603 | ключевого слова \texttt{fun} и заканчивается ключевым словом \texttt{end} 604 | вместо точки (\texttt{.}). Между ними должно находиться обычное объявление 605 | функции, за тем исключением, что имя её не пишется. 606 | 607 | \begin{erlangru} 608 | fun 609 | (Образец11,...,Образец1N) [when Охрана1] -> 610 | ТелоУравнения1; 611 | ...; 612 | (ОбразецK1,...,ОбразецKN) [when ОхранаK] -> 613 | ТелоУравненияK 614 | end 615 | \end{erlangru} 616 | 617 | Переменные в заголовке анонимной функции \emph{затеняют} переменные в уравнении 618 | функции, которое окружает \texttt{fun}, но переменные, связанные в теле 619 | \texttt{fun} являются для него локальными. Возвращаемое выражением \texttt{fun 620 | Имя/N} значение является функцией. Выражение \texttt{fun Имя/N} эквивалентно 621 | следующей записи: 622 | 623 | \begin{erlangru} 624 | fun (Аргумент1,...,АргументN) -> Имя(Аргумент1,...,АргументN) end 625 | \end{erlangru} 626 | 627 | Выражение \texttt{fun Модуль:Функция/Арность} также разрешено, но только если 628 | \texttt{Функция} экспортирована из \texttt{Модуля}. 629 | 630 | \begin{erlang} 631 | Fun1 = fun (X) -> X+1 end. 632 | Fun1(2) % результат: 3 633 | 634 | Fun2 = fun (X) when X>=1000 -> big; (X) -> small end. 635 | Fun2(2000) % результат: big 636 | \end{erlang} 637 | 638 | Поскольку функция, созданная \texttt{fun} анонимна, то есть не имеет имени в 639 | определении функции, то для определения рекурсивной функции следует сделать два 640 | шага. Пример ниже показывает, как определить рекурсивную функцию 641 | \texttt{sum(List)} (смотрите раздел \ref{datatypes:list}) как анонимную с 642 | помощью \texttt{fun}. Такой подход ещё называется \emph{Y-комбинатор}. 643 | 644 | \begin{erlang} 645 | Sum1 = fun ([], _Foo) -> 0;([H|T], Foo) -> H + Foo(T, Foo) end. 646 | Sum = fun (List) -> Sum1(List, Sum1) end. 647 | Sum([1,2,3,4,5]) % 15 648 | \end{erlang} 649 | 650 | Определение \texttt{Sum1} сделано так, что оно принимает \emph{само себя} в 651 | качестве аргумента, сопоставляется с \texttt{\_Foo} (пустым списком) или 652 | \texttt{Foo}, который затем рекурсивно вызывается. Определение \texttt{Sum} 653 | вызывает \texttt{Sum1}, также передавая \texttt{Sum1} в качестве аргумента. 654 | 655 | \textbf{Примечание:} В Erlang версии R17 эта проблема устранена и анонимные 656 | функции могут ссылаться сами на себя. 657 | 658 | 659 | 660 | \section{Встроенные функции (BIF)} 661 | \label{functions:bifs} 662 | 663 | \textbf{Встроенные функции}, или BIF (built-in functions) --- это функции, 664 | реализованные на языке C, на котором также написана система Erlang, и делают 665 | вещи, которые трудно или невозможно реализовать на языке Erlang. Большинство 666 | встроенных функций принадлежат модулю \texttt{erlang}, но есть некоторые, 667 | принадлежащие и другим модулям, таким как \texttt{lists} и \texttt{ets}. 668 | Используемые чаще всего встроенные функции, принадлежащие модулю 669 | \texttt{erlang}, импортируются во все ваши модули автоматически, то есть перед 670 | ними не требуется писать имя модуля. 671 | 672 | \begin{center} 673 | \begin{tabular}{|>{\raggedright}p{135pt}|>{\raggedright}p{290pt}|} 674 | \hline 675 | \multicolumn{2}{|p{321pt}|}{Некоторые полезные встроенные функции} \tabularnewline 676 | \hline 677 | \texttt{date()} & 678 | Возвращает сегодняшнюю дату в формате \texttt{\{Год, Месяц, День\}} \tabularnewline 679 | \hline 680 | \texttt{now()} & 681 | Возвращает текущее время в микросекундах. Точность и реализация зависит от 682 | операционной системы \tabularnewline 683 | \hline 684 | \texttt{time()} & 685 | Возвращает текущее время в формате \texttt{\{Часы, Минуты, Секунды\}}. Реализация зависит от операционной системы \tabularnewline 686 | \hline 687 | \texttt{halt()} & 688 | Аварийно останавливает работу Erlang-системы \tabularnewline 689 | \hline 690 | \texttt{processes()} & 691 | Возвращает список всех Erlang-процессов в системе \tabularnewline 692 | \hline 693 | \texttt{process\_info(Pid)} & 694 | Возвращает словарь, содержащий информацию о процессе \texttt{Pid} \tabularnewline 695 | \hline 696 | \texttt{Модуль:module\_info()} & 697 | Возвращает словарь, содержащий информацию о \texttt{Модуле} \tabularnewline 698 | \hline 699 | \end{tabular} 700 | \end{center} 701 | 702 | \textbf{Словарь} --- это список кортежей в формате \texttt{\{Ключ, Значение\}} 703 | (см. также раздел \ref{processes:dicts}). 704 | 705 | \begin{erlang} 706 | size({a, b, c}) % 3 707 | atom_to_list('Erlang') % "Erlang" 708 | date() % {2013,5,27} 709 | time() % {01,27,42} 710 | \end{erlang} 711 | -------------------------------------------------------------------------------- /chapters-RU/06-processes.tex: -------------------------------------------------------------------------------- 1 | \chapter{Процессы} 2 | \label{processes} 3 | 4 | \textbf{Процесс} соответствует одному \emph{потоку управления}. Erlang разрешает 5 | создавать очень большое количество параллельно работающих процессов, каждый из 6 | которых исполняется, как будто он имеет свой собственный виртуальный процессор. 7 | Когда процесс, исполняющися внутри функции \texttt{functionA} вызывает другую 8 | функцию \texttt{functionB}, он будет ждать, пока \texttt{functionB} не 9 | завершится и затём извлечёт или получит результат. Если вместо этого он 10 | \emph{породит} новый процесс, исполняющий ту же \texttt{functionB}, то оба 11 | процесса продолжат исполняться одновремено (конкурентно). \texttt{functionA} 12 | не будет ждать завершения \texttt{functionB} и единственный способ передать 13 | результат --- это \emph{передача сообщений}. 14 | 15 | Процессы Erlang --- очень лёгкие с малым расходом памяти, легко стартуют и легко 16 | завершают работу, и расходы на их планировку во время выполнения очень 17 | небольшие. \textbf{Идентификатор процесса}, или \texttt{Pid}, идентифицирует 18 | существующий или недавно существовавший процесс. Встроенная функция 19 | \texttt{self/0} возвращает \texttt{Pid} вызвавшего её процесса. 20 | 21 | 22 | \section{Создание процессов} 23 | 24 | Процесс создаётся с помощью встроенной функции \texttt{spawn/3}. 25 | 26 | \begin{erlangru} 27 | spawn(Модуль, Функция, [Аргумент1, ..., АргументN]) 28 | \end{erlangru} 29 | 30 | Аргумент \texttt{Модуль} должен быть равен имени модуля, который содержит 31 | нужную функцию, и \texttt{Функция} --- имени экспортированной функции в этом 32 | модуле. Список \texttt{Аргумент1}$...$\texttt{АргументN} --- параметры, которые 33 | будут переданы запущенной в новом процессе функции. \texttt{spawn} создаёт 34 | новый процесс и возвращает его идентификатор, \texttt{Pid}. Новый процесс 35 | начинается с выполнения такого кода: 36 | 37 | \begin{erlangru} 38 | Модуль:Функция(Аргумент1, ..., АргументN) 39 | \end{erlangru} 40 | 41 | \texttt{Функция} должна быть экспортирована, даже если процесс с ней порождается 42 | другой функцией в том же модуле. Есть и другие встроенные функции для 43 | порождения процессов, например \texttt{spawn/4} порождает процесс на другом 44 | узле Erlang. 45 | 46 | 47 | \section{Зарегистрированные процессы} 48 | 49 | Процесс может быть связан с некоторым именем. Имя процесса должно быть атомом и 50 | оно автоматически освобождается, если процесс завершает свою работу. Следует 51 | регистрировать только статические (постоянно живущие) процессы. 52 | 53 | \begin{center} 54 | \begin{tabular}{|>{\raggedright}p{140pt}|>{\raggedright}p{245pt}|} 55 | \hline 56 | \multicolumn{2}{|p{321pt}|}{Встроенные функции для регистрации имён} 57 | \tabularnewline 58 | \hline 59 | \texttt{register(Имя, Pid)} & 60 | Назначает атом \texttt{Имя} в качестве имени для процесса \texttt{Pid} 61 | \tabularnewline 62 | \hline 63 | \texttt{registered()} & 64 | Возвращает список имён, которые были зарегистрированы \tabularnewline 65 | \hline 66 | \texttt{whereis(Name)} & 67 | Возвращает \texttt{Pid}, который был зарегистрирован для имени \texttt{Имя} или 68 | атом \texttt{undefined} если имя не было зарегистрировано \tabularnewline 69 | \hline 70 | \end{tabular} 71 | \end{center} 72 | 73 | 74 | \section{Сообщения между процессами} 75 | 76 | Процессы сообщаются друг с другом посредством отправки и получения 77 | \textbf{сообщений}. Сообщения отправляются используя оператор отправки 78 | (\texttt{!}) и принимаются с помощью конструкции \texttt{receive}. Передача 79 | сообщений \emph{асинхронная} (не блокирует отправителя до доставки сообщения) и 80 | \emph{надёжная} (сообщение гарантированно достигает получателя, если он 81 | существует). 82 | 83 | 84 | \subsection{Отправка} 85 | \begin{erlangru} 86 | Pid ! Выражение 87 | \end{erlangru} 88 | 89 | Оператор отправки (\texttt{!}) посылает значение \texttt{Выражения} в форме 90 | сообщения процессу, указанному идентификатором \texttt{Pid}, где сообщение 91 | будет помещено в конец его \textbf{очереди сообщений}. Значение 92 | \texttt{Выражения} также будет значением, возвращённым оператором 93 | (\texttt{!}). \texttt{Pid} должен быть идентификатором процесса, 94 | зарегистрированным в системе именем или кортежем в виде \texttt{\{Имя,Узел\}}, 95 | где \texttt{Имя} --- это зарегистрированное имя процесса на удалённом 96 | \texttt{Узле} (см. главу \ref{distribution}). Оператор отправки сообщения 97 | (\texttt{!}) не может возвратить ошибку, даже если в качестве получателя был 98 | указан несуществующий процесс. 99 | 100 | 101 | \subsection{Получение} 102 | 103 | \begin{erlangru} 104 | receive 105 | Образец1 [when ОхранныеВыражения1] -> 106 | Тело1; 107 | ... 108 | ОбразецN [when ОхранныеВыраженияN] -> 109 | ТелоN % Заметьте, нет точки с запятой (;) перед end 110 | end 111 | \end{erlangru} 112 | 113 | Это выражение принимает сообщения, отправленные процессу с помощью оператора 114 | отправки (\texttt{!}). \texttt{ОбразцыX} последовательно сопоставляются с первым 115 | сообщением в очереди сообщений, затем со вторым и так далее. Если сопоставление 116 | проходит успешно и необязательный список охранных выражений 117 | \texttt{ОхранныеВы\-раженияX} тоже равен \texttt{true}, то сообщение удаляется 118 | из очереди сообщений и соответствующая цепочка выражений \texttt{ТелоX} 119 | вычисляется. Именно порядок уравнений с образцами решает порядок получения 120 | сообщений, а не порядок, в котором они прибывают. Это называется 121 | \emph{избирательным приёмом} сообщений. Значение, возвращаемое \texttt{ТеломX} 122 | и будет значением, возвращённым всем выражением \texttt{receive}. 123 | 124 | \texttt{receive} никогда не приводит к возникновению ошибки. Процесс может быть 125 | поставлен на паузу во время ожидания, возможно навсегда, до тех пор, пока не 126 | появится сообщение, отвечающее одному из образцов с охранной 127 | последовательностью, равной \texttt{true}. 128 | 129 | \newpage 130 | \begin{erlang} 131 | wait_for_onhook() -> 132 | receive 133 | onhook -> 134 | disconnect(), 135 | idle(); 136 | {connect, B} -> 137 | B ! {busy, self()}, 138 | wait_for_onhook() 139 | end. 140 | \end{erlang} 141 | 142 | 143 | \subsection{Получение с таймаутом} 144 | 145 | \begin{erlangru} 146 | receive 147 | Образец1 [when ОхранныеВыражения1] -> 148 | Тело1; 149 | ...; 150 | ОбразецN [when ОхранныеВыраженияN] -> 151 | ТелоN 152 | after 153 | ВыражениеТ -> 154 | ТелоT 155 | end 156 | \end{erlangru} 157 | 158 | \texttt{ВыражениеТ} должно вычисляться в целое число между \texttt{0} и 159 | \texttt{16\#ffffffff} (значение должно помещаться в 32 бита). Если ни одно 160 | подходящее сообщение не прибыло в течение \texttt{ВыражениеТ} миллисекунд, то 161 | выражение \texttt{ТелоT} вычисляется и его возвращаемое значение становится 162 | результатом всего выражения \texttt{receive}. 163 | 164 | \pagebreak 165 | 166 | \begin{erlang} 167 | wait_for_onhook() -> 168 | receive 169 | onhook -> 170 | disconnect(), 171 | idle(); 172 | {connect, B} -> 173 | B ! {busy, self()}, 174 | wait_for_onhook() 175 | after 176 | 60000 -> 177 | disconnect(), 178 | error() 179 | end. 180 | \end{erlang} 181 | 182 | Выражение \texttt{receive...after} без образцов может быть использовано для 183 | реализации простых таймаутов. 184 | 185 | \begin{erlangru} 186 | receive 187 | after 188 | ВыражениеТ -> 189 | ТелоТ 190 | end 191 | \end{erlangru} 192 | 193 | \begin{center} 194 | \begin{tabular}{|>{\raggedright}p{65pt}|>{\raggedright}p{340pt}|} 195 | \hline 196 | \multicolumn{2}{|p{321pt}|}{Два особых случая для значения таймаута 197 | \texttt{ВыражениеT}}\tabularnewline 198 | \hline 199 | \texttt{infinity} & 200 | Является эквивалентом бесконечного ожидания и может пригодиться, если значение 201 | таймаута вычисляется во время исполнения и передаётся параметром в функцию 202 | \tabularnewline 203 | \hline 204 | \texttt{0} & 205 | Если в почтовом ящике нет подходящего сообщения, таймаут произойдёт немедленно 206 | \tabularnewline 207 | \hline 208 | \end{tabular} 209 | \end{center} 210 | 211 | 212 | \section{Завершение работы процесса} 213 | \label{processes:termination} 214 | 215 | Процесс всегда завершается по некоторой \textbf{причине выхода} (exit reason), 216 | которая может быть любым термом Erlang. Если процесс завершился нормально, то 217 | есть его код исполнился до конца, то причиной выхода будет атом \texttt{normal}. 218 | Процесс может завершить себя сам вызывая одну из следующих встроенных функций: 219 | 220 | \begin{erlangru} 221 | exit(Причина) 222 | erlang:error(Причина) 223 | erlang:error(Причина, Аргументы) 224 | \end{erlangru} 225 | 226 | Процесс завершается с причиной выхода \texttt{\{Причина,СтекВызовов\}}, когда 227 | происходит ошибка времени исполнения. 228 | 229 | Процесс также может быть завершён, если он получает сигнал выхода с любой другой 230 | причиной кроме \texttt{normal} (см. раздел \ref{processes:recvexitsignals}). 231 | 232 | 233 | \section{Связи между процессами} 234 | \label{processes:links} 235 | 236 | Два процесса могут быть \textbf{связаны} друг с другом. Связи двунаправленны и 237 | может существовать только одна связь между любыми двумя процессами (имеются в 238 | виду уникальные идентификаторы процессов). Процесс с идентификатором 239 | \texttt{Pid1} может связаться с процессом, имеющим идентификатор \texttt{Pid2} 240 | используя встроенную функцию \texttt{link(Pid2)}. Функция 241 | \texttt{spawn\_link(Модуль, Функция, Аргументы)} порождает и сразу же связывает 242 | процессы одной атомарной операцией. 243 | 244 | Связь между процессами можно убрать используя функцию \texttt{unlink(Pid)}. 245 | 246 | 247 | \subsection{Обработка ошибок между процессами} 248 | 249 | Когда процесс завершает работу, он отправляет \textbf{сигналы выхода} всем 250 | процессам, с которыми он связан. Они в свою очередь также завершают работу 251 | \emph{или обрабатывают сигнал выхода каким-либо способом}. Эта возможность 252 | может использоваться для построения иерархических программных структур, где 253 | некоторые из процессов присматривают за другими процессами, например рестартуя 254 | их, если они завершаются аварийно. 255 | 256 | 257 | \subsection{Отправка сигналов выхода} 258 | \label{processes:sendexitsignals} 259 | 260 | Процесс всегда завершает работу с причиной выхода, которая отправляется в виде 261 | сигнала выхода всем связанным процессам. Встроенная функция \texttt{exit(Pid, 262 | Причина)} посылает сигнал выхода другому процессу \texttt{Pid} по указанной 263 | \texttt{Причине}, не влияя на процесс-отправитель. 264 | 265 | 266 | \subsection{Получение сигналов выхода} 267 | \label{processes:recvexitsignals} 268 | 269 | Если процесс получает сигнал выхода с причиной выхода другой, кроме 270 | как\linebreak 271 | \texttt{normal}, он также завершит свою работу и отправит сигналы выхода с той 272 | же причиной всем своим связанным процессам. Сигнал выхода с причиной 273 | \texttt{normal} игнорируется и не приводит к такому поведению. Это поведение 274 | можно изменить с помощью вызова встроенной функции 275 | \texttt{process\_flag(trap\_exit, true)}. 276 | 277 | Процесс после этого способен \textbf{перехватывать сигналы выхода}. Это 278 | означает, что сигнал выхода трансформируется в обычное сообщение: 279 | \texttt{\{'EXIT', PidОтправителя, Причина\}}, который помещается в почтовый 280 | ящик процесса и может быть принят и обработан, как обычное сообщение используя 281 | \texttt{receive}. 282 | 283 | Однако, вызов встроенной функции \texttt{exit(Pid, kill)} завершает работу 284 | процесса \texttt{Pid} безусловно, независимо от того, способен ли он 285 | перехватывать сигналы выхода или нет. 286 | 287 | 288 | \section{Мониторы} 289 | 290 | Процесс \texttt{Pid1} может создать \textbf{монитор} для процесса \texttt{Pid2} 291 | используя встроенную функцию: 292 | 293 | \begin{erlang} 294 | erlang:monitor(process, Pid2) 295 | \end{erlang} 296 | 297 | которая возвращает ссылочное значение (\texttt{Ссылку}). Если после этого 298 | \texttt{Pid2} завершит работу с \texttt{Причиной} выхода, то следующее 299 | сообщение будет отправлено процессу \texttt{Pid1}: 300 | 301 | \begin{erlangru} 302 | {'DOWN', Ссылка, process, Pid2, Причина} 303 | \end{erlangru} 304 | 305 | Если процесс \texttt{Pid2} не существует, то сообщение \texttt{'DOWN'} будет 306 | отправлено немедленно и поле \texttt{Причина} будет установлено равным 307 | \texttt{noproc}. Мониторы однонаправлены, то есть если \texttt{Pid1} следит за 308 | \texttt{Pid2}, то он получит сообщение о смерти \texttt{Pid2}, но \texttt{Pid2} 309 | \textbf{не} получит сообщение о смерти \texttt{Pid1}. Повторные вызовы функции 310 | \linebreak 311 | \texttt{erlang:monitor(process, Pid)} создадут несколько независимых мониторов и 312 | каждый из них отправит сообщение \texttt{'DOWN'}, когда процесс \texttt{Pid} 313 | завершит работу. 314 | 315 | Монитор можно удалить, вызывая функцию \texttt{erlang:demonitor(Ссылка)}. 316 | Возможно создание мониторов для процессов с зарегистрированными именами, а 317 | также запущенных на других узлах. 318 | 319 | 320 | \section{Приоритетность процессов} 321 | 322 | Встроенная функция \texttt{process\_flag(priority, Приоритет)} определяет 323 | приоритет текущего процесса. \texttt{Приоритет} может быть одним из следующих 324 | значений \texttt{normal} (по умолчанию), \texttt{low}, \texttt{high} или 325 | \texttt{max}. 326 | 327 | Изменение приоритета процесса не рекомендуется и должно производиться только в 328 | особых случаях. Проблема, которая требует смены приоритета процесса, чаще всего 329 | может быть решена и другим подходом. 330 | 331 | 332 | \section{Словарь процесса} 333 | \label{processes:dicts} 334 | 335 | Каждый процесс имеет собственный словарь, являющийся списком пар термов 336 | в форме \texttt{\{Ключ, Значение\}}. 337 | 338 | \begin{center} 339 | \begin{tabular}{|>{\raggedright}p{140pt}|>{\raggedright}p{290pt}|} 340 | \hline 341 | \multicolumn{2}{|p{326pt}|}{Встроенные функции для работы со словарём 342 | процесса}\tabularnewline 343 | \hline 344 | \texttt{put(Ключ, Значение)} & 345 | Сохраняет \texttt{Значение} с \texttt{Ключом} или заменяет уже существующее 346 | \tabularnewline 347 | \hline 348 | \texttt{get(Ключ)} & 349 | Извлекает значение, сохранённое с \texttt{Ключом}, иначе возвращает 350 | \texttt{undefined} \tabularnewline 351 | \hline 352 | \texttt{get()} & 353 | Возвращает весь словарь процесса целиком, в виде списка пар 354 | \texttt{\{Ключ, Значение\}} \tabularnewline 355 | \hline 356 | \texttt{get\_keys(Значение)} & 357 | Возвращает список ключей, которые имеют \texttt{Значение} \tabularnewline 358 | \hline 359 | \texttt{erase(Ключ)} & 360 | Удаляет пару \texttt{\{Ключ, Значение\}}, если она была, и возвращает 361 | \texttt{Ключ} \tabularnewline 362 | \hline 363 | \texttt{erase()} & 364 | Возвращает словарь процесса целиком и удаляет его содержимое \tabularnewline 365 | \hline 366 | \end{tabular} 367 | \end{center} 368 | 369 | Словари процессов могут использоваться для того, чтобы хранить глобальные 370 | переменные в приложении, но их слишком активное использование обычно усложняет 371 | отладку и считается плохим стилем программирования. 372 | 373 | -------------------------------------------------------------------------------- /chapters-RU/07-error-handling.tex: -------------------------------------------------------------------------------- 1 | \chapter{Обработка ошибок} 2 | \label{errorhandling} 3 | 4 | Эта глава описывает обработку ошибок внутри процесса. Такие ошибки известны ещё 5 | под названием \textbf{исключения}. 6 | 7 | 8 | \section{Классы исключений и причины ошибок} 9 | 10 | \begin{center} 11 | \begin{tabular}{|>{\raggedright}p{55pt}|>{\raggedright}p{350pt}|} 12 | \hline 13 | \multicolumn{2}{|p{326pt}|}{Классы исключений}\tabularnewline 14 | \hline 15 | \texttt{error} & 16 | Ошибка времени выполнения, например, при применении оператора к недопустимым 17 | типам аргументов. Ошибки времени выполнения могут быть вызваны программистом с 18 | помощью встроенной функции \texttt{erlang:error(Причина)} или 19 | \texttt{erlang:error(Причина, Аргументы)} \tabularnewline 20 | \hline 21 | \texttt{exit} & 22 | Процесс вызвал \texttt{exit(Причина)}, см. раздел \ref{processes:termination} 23 | о завершении процессов \tabularnewline 24 | \hline 25 | \texttt{throw} & 26 | Процесс вызвал \texttt{throw(Выражение)}, см. раздел 27 | \ref{errorhandling:catchthrow} о бросках исключений\tabularnewline 28 | \hline 29 | \end{tabular} 30 | \end{center} 31 | 32 | Появление исключения приводит к аварийной остановке процесса, то есть его 33 | исполнение останавливается и он и его данные удаляются из системы. Также это 34 | действие называется \emph{уничтожением} (termination). После этого сигналы 35 | выхода посылаются всем связанным процессам. Исключение состоит из класса, 36 | причины выхода и копии стека вызовов. Стек вызовов можно сформировать и 37 | получить в удобном виде с помощью функции \texttt{erlang:get\_stacktrace/0}. 38 | 39 | Ошибки времени исполнения и другие исключения могут не приводить к смерти 40 | процесса, если использовать выражения \texttt{try} и \texttt{catch}. 41 | 42 | Для исключений, имеющих класс \texttt{error}, например для обычных ошибок 43 | времени выполнения, \textbf{причиной выхода} будет кортеж \texttt{\{Причина, 44 | Стек\}} где \texttt{Причина} --- это терм, указывающий более точно на тип 45 | ошибки. 46 | 47 | \begin{center} 48 | \begin{tabular}{|>{\raggedright}p{110pt}|>{\raggedright}p{320pt}|} 49 | \hline 50 | \multicolumn{2}{|p{326pt}|}{Причины выхода}\tabularnewline 51 | \hline 52 | \texttt{badarg} & 53 | Передан аргумент недопустимого типа. \tabularnewline 54 | \hline 55 | \texttt{badarith} & 56 | Аргумент в арифметическом выражении имеет недопустимый тип. \tabularnewline 57 | \hline 58 | \texttt{\{badmatch, Значение\}} & 59 | Вычисление сопоставления с образцом прошло неудачно. \texttt{Значение} не совпало 60 | с образцом. 61 | \tabularnewline 62 | \hline 63 | \texttt{function\_clause} & 64 | Не найдено ни одного подходящего уравнения функции по образцам аргументов и 65 | охранных выражений при вычислении вызова функции. \tabularnewline 66 | \hline 67 | \texttt{\{case\_clause, Значение\}} & 68 | При вычислении выражения \texttt{case} \texttt{Значение} не совпало ни с чем. \tabularnewline 69 | \hline 70 | \texttt{if\_clause} & 71 | Ни одна из веток выражения \texttt{if} не оказалась равна \texttt{true}. 72 | \tabularnewline 73 | \hline 74 | \texttt{\{try\_clause, Value\}} & 75 | При вычислении секции выражения \texttt{try} со \texttt{Значением} не совпала ни 76 | одна из веток. \tabularnewline 77 | \hline 78 | \texttt{undef} & 79 | Функция не была найдена при попытке исполнить вызов функции \tabularnewline 80 | \hline 81 | \texttt{\{badfun, Fun\}} & 82 | Что-то не так с анонимной функцией \texttt{Fun} \tabularnewline 83 | \hline 84 | \texttt{\{badarity, Fun\}} & 85 | Функция вызвана с неверным количеством аргументов. Значение \texttt{Fun} описывает 86 | и её и переданные аргументы \tabularnewline 87 | \hline 88 | \texttt{timeout\_value} & 89 | Значение таймаута в \texttt{receive}$...$\texttt{after} было вычислено и оказалось 90 | не целым 32-битным числом и не атомом \texttt{infinity} \tabularnewline 91 | \hline 92 | \texttt{noproc} & 93 | Попытка создать связь с несуществующим процессом \tabularnewline 94 | \hline 95 | \texttt{\{nocatch, Значение\}} & 96 | Попытка выполнить \texttt{throw} за пределами кода, защищённого оператором 97 | \texttt{catch}. \texttt{Значение} --- терм, который был брошен \tabularnewline 98 | \hline 99 | \texttt{system\_limit} & Сработало одно из системных ограничений, заданных 100 | реализацией виртуальной машины или операционной системы \tabularnewline 101 | \hline 102 | \end{tabular} 103 | \end{center} 104 | 105 | \texttt{Стек} --- это цепочка вызовов функций, которые исполнялись в тот момент, 106 | когда произошла ошибка, даётся в виде списка кортежей \texttt{\{Модуль, Имя, 107 | Арность\}}, где первым идёт самый недавний вызов. Иногда самый последний вызов 108 | вместо \texttt{Арности} будет содержать \texttt{Аргументы}: \texttt{\{Модуль, 109 | Имя, Аргументы\}}. 110 | 111 | 112 | \section{Catch и throw} 113 | \label{errorhandling:catchthrow} 114 | \begin{erlangru} 115 | catch Выражение 116 | \end{erlangru} 117 | 118 | Такая запись возвращает результат вычисления \texttt{Выражения} если во время 119 | вычисления не возникло исключение. В случае исключения возвращаемое значение 120 | будет кортежем с информацией о нём. 121 | 122 | \begin{erlangru} 123 | {'EXIT', {Причина, Стек}} 124 | \end{erlangru} 125 | 126 | Такое исключение считается \emph{пойманным}. Непойманное исключение приведёт к 127 | уничтожению процесса. Если исключение было вызвано вызовом функции 128 | \texttt{exit(Терм)} то будет возвращён кортеж с причиной в виде 129 | \texttt{\{'EXIT',Терм\}}. Если исключение возникло при вызове 130 | \texttt{throw(Терм)}, тогда будет возвращено значение \texttt{Терма}. 131 | 132 | \texttt{catch 1+2} \resultingin \texttt{3}\\ 133 | \texttt{catch 1+a } \resultingin \texttt{\{'EXIT',\{badarith,[...]\}\}} 134 | 135 | Оператор \texttt{catch} имеет низкий приоритет и выражения, использующие его 136 | часто требуют заключения в блок \texttt{begin..end} или круглые скобки. 137 | 138 | \texttt{A = (catch 1+2)} \resultingin \texttt{3} 139 | 140 | Встроенная функция \texttt{throw(Выражение)} используется для 141 | \emph{нелокального} выхода из функций. Её можно вызывать только под защитой 142 | \texttt{catch}, что возвратит результат вычисления \texttt{Выражения}. 143 | 144 | \texttt{catch begin 1,2,3,throw(four),5,6 end} \resultingin \texttt{four} 145 | 146 | Если \texttt{throw/1} вычисляется за пределами оператора \texttt{catch}, то 147 | возникнет ошибка времени выполнения \texttt{nocatch}. 148 | 149 | Оператор \texttt{catch} не спасёт процесс от завершения по сигналу выхода из 150 | другого связанного с ним процесса (если только не был включен режим перехвата 151 | сигналов выхода, trap\_exit). 152 | 153 | 154 | \section{Try} 155 | \label{errorhandling:try} 156 | 157 | Выражение \texttt{try} способно различить различные классы исключений. 158 | Следующий пример эмулирует поведение описанного чуть выше \texttt{catch 159 | Выражение}: 160 | 161 | \begin{erlang} 162 | try Expr 163 | catch 164 | throw:Term -> Term; 165 | exit:Reason -> {'EXIT', Reason}; 166 | error:Reason -> {'EXIT',{Reason, erlang:get_stacktrace()}} 167 | end 168 | \end{erlang} 169 | 170 | Полное описание \texttt{try} следующее: 171 | 172 | \begin{erlangru} 173 | try Выражение [of 174 | Образец1 [when ОхранныеВыражения1] -> Тело1; 175 | ...; 176 | ОбразецN [when ОхранныеВыраженияN] -> ТелоN] 177 | [catch 178 | [КлассОшибки1:]ОбразецИсключения1 [when ОхранаИсключения1] -> 179 | ТелоИсключения1; 180 | ...; 181 | [КлассОшибкиN:]ОбразецИсключенияN [when ОхранаИсключенияN] -> 182 | ТелоИсключенияN] 183 | [after ТелоПосле] 184 | end 185 | \end{erlangru} 186 | 187 | В наличии должны обязательно быть как минимум одна строка \texttt{catch} или 188 | одно предложение \texttt{after}. Может дополнительно использоваться оператор 189 | \texttt{of} после \texttt{Выражения}, который добавляет вычисление \texttt{case} 190 | к значению \texttt{Выражения}. 191 | 192 | \texttt{try} возвратит значение \texttt{Выражения}, если только не произойдёт 193 | исключение во время его вычисления. Тогда исключение \emph{ловится} и ряд 194 | \texttt{ОбразцовИсключения} с подходящим \texttt{КлассомОшибки} сопоставляются 195 | один за другим с пойманным исключением. Если \texttt{КлассОшибки} не указан, то 196 | подразумевается \texttt{throw}. Если сопоставление удачно проходит и 197 | необязательные выражения \texttt{ОхраныИсключения} тоже равны \texttt{true}, то 198 | вычисляется соответствующее \texttt{ТелоИсключения} и его результат становится 199 | возвращаемым значением. 200 | 201 | Если не найдено подходящего \texttt{ОбразцаИсключения} с таким же 202 | \texttt{КлассомОшибки} и выражениями \texttt{ОхраныИсключения}, равными 203 | \texttt{true}, то исключение передаётся дальше, как если бы начальное 204 | \texttt{Выражение} не было заключено в \texttt{try}. Исключение, происходящее 205 | во время вычисления \texttt{ТелаИсключения} не будет поймано. 206 | 207 | Если ни один из \texttt{Образцов} не совпал, то произойдёт ошибка времени 208 | исполнения \texttt{try\_clause}. 209 | 210 | Если определено, то \texttt{ТелоПосле} всегда вычисляется \textbf{после} всех 211 | операций в\linebreak 212 | \texttt{try..catch}, независимо от возникновения ошибки. Его 213 | возвращаемое значение игнорируется и не влияет на значение всего оператора 214 | \texttt{try} (как если бы \texttt{after} не было). \texttt{ТелоПосле} 215 | вычисляется даже если исключение произошло в \texttt{Теле} или 216 | \texttt{ТелеИсключения}, в этом случае исключение передаётся выше по коду. 217 | 218 | %% The \texttt{AfterBody} is evaluated after either \texttt{Body} or 219 | %% \texttt{ExceptionBody} no matter which one. The evaluated value of the 220 | %% \texttt{AfterBody} is lost; the return value of the try expression is 221 | %% the same with an after section as without. Even if an exception occurs 222 | %% during evaluation of \texttt{Body} or \texttt{ExceptionBody}, the 223 | %% \texttt{AfterBody} is evaluated. In this case the exception is caught 224 | %% and passed on after the \texttt{AfterBody} has been evaluated, so the 225 | %% exception from the try expression is the same with an after section as 226 | %% without. 227 | 228 | Исключение, которое происходит во время вычисления \texttt{ТелаПосле} не 229 | ловится, то есть если \texttt{ТелоПосле} вычислилось по причине исключения в 230 | \texttt{Выражении}, \texttt{Теле} или \texttt{ТелеИсключения}, то оригинальное 231 | исключение будет потеряно и вместо него полёт вверх по стеку вызовов продолжит 232 | уже новое исключение. 233 | 234 | -------------------------------------------------------------------------------- /chapters-RU/08-distributed-erlang.tex: -------------------------------------------------------------------------------- 1 | \chapter{Распределённый Erlang} 2 | \label{distribution} 3 | 4 | \textbf{Распределённая Erlang-система} состоит из некоторого количества систем 5 | времени исполнения Erlang, которые сообщаются друг с другом. Каждая такая 6 | система называется \textbf{узлом} (node). Узлы могут находиться на одной 7 | физической машине или на разных и быть соединёнными посредством сети. 8 | Стандартный механизм распределения реализован на основе TCP/IP сокетов, но 9 | могут быть реализованы и другие механизмы. 10 | 11 | Передача сообщений между процессами на разных узлах, так же как и связи между 12 | процессами и мониторы, прозрачно реализована используя идентификаторы процессов 13 | (pid). Однако, зарегистрированные имена локальны для каждого из узлов. 14 | На зарегистрированный процесс на конкретном узле можно ссылаться с помощью 15 | кортежа \texttt{\{Имя,Узел\}}. 16 | 17 | Служба отображения портов Erlang (Erlang Port Mapper Daemon, или \textbf{epmd}) 18 | автоматически стартует на каждом компьютере, где имеется запущенный узел Erlang. 19 | Он отвечает за отображение имён узлов в сетевые адреса компьютеров. 20 | 21 | 22 | \section{Узлы} 23 | 24 | \textbf{Узел} --- это исполняемая в данный момент Erlang-система, которой было 25 | назначено имя, используя параметр командной строки \texttt{-name} (длинное имя) 26 | или \texttt{-sname} (короткое имя). 27 | 28 | Формат имени узла --- атом вида \texttt{Имя@Адрес} (помните, \texttt{@} 29 | является допустимым в атомах символом), где \texttt{Имя} задаётся 30 | пользователем, запустившим узел, а \texttt{Адрес} --- полное имя сервера, если 31 | были включены длинные имена, или первая часть имени сервера (если были 32 | использованы короткие имена). Функция \texttt{node()} возвращает имя узла. 33 | Узлы, использующие длинные имена не могут связываться с узлами, использующими 34 | короткие имена. 35 | 36 | 37 | \section{Соединение между узлами} 38 | 39 | Узлы распределённой Erlang-системы полностью соединены (каждый с каждым). Первый 40 | раз, когда используется новое имя узла, производится попытка подключения к этому 41 | узлу. Если узел \texttt{A} подключается к узлу \texttt{B}, и узел \texttt{B} 42 | имел открытое подключение к узлу \texttt{C}, то узел \texttt{А} тоже попытается 43 | подключиться к узлу \texttt{C}. Эта возможность может быть отключена используя 44 | параметр командной строки: 45 | 46 | \qquad\texttt{-connect\_all false} 47 | 48 | Если узел прекращает работу или теряет сеть, все подключения к нему удаляются. 49 | Встроенная функция: 50 | 51 | \begin{erlangru} 52 | erlang:disconnect(Узел) 53 | \end{erlangru} 54 | 55 | отключает заданный \texttt{Узел}. Встроенная функция \texttt{nodes()} вернёт 56 | список подключенных в данный момент (видимых) узлов. 57 | 58 | 59 | \section{Скрытые узлы} 60 | 61 | Иногда полезно подключиться к нужному узлу, не инициируя веер подключений ко 62 | всем остальным узлам. Для этой цели можно использовать \textbf{скрытый узел}. 63 | Скрытый узел это узел, запущенный с параметром командной строки 64 | \texttt{-hidden}. Подключения между скрытыми узлами и другими узлами должны 65 | устанавливаться вручную и явно. Скрытые узлы не видны в списке узлов, 66 | возвращаемом функцией \texttt{nodes()}. Вместо этого следует использовать 67 | \texttt{nodes(hidden)} или \texttt{nodes(connected)}. Скрытый узел не будет 68 | включён в набор узлов, за которыми следит модуль \texttt{global}. 69 | 70 | \textbf{Узел на языке С} это С-программа, написанная, чтобы действовать и 71 | выглядеть, как скрытый узел в распределённой Erlang-системе. Библиотека 72 | \texttt{erl\_interface} содержит необходимые для этого функции. 73 | 74 | 75 | \section{Секретный куки (cookie)} 76 | 77 | Каждый узел имеет свой собственный ключ, ещё называемый 78 | \textbf{магический куки} (cookie), который является атомом. Сервер сетевой 79 | аутентикации Erlang (под названием \texttt{auth}) читает содержимое куки из 80 | файла \texttt{\$HOME/.erlang.cookie}. Если файл не существовал, он будет 81 | создан и в него будет записана случайная строка. 82 | 83 | % FRMB CHECK: the implication here is that "erlang:set_cookie(node(), Cookie)" 84 | % sets *this* node's cookie, as well as the cookie that will be used to connect 85 | % to other nodes, if not explicitly set otherwise. 86 | 87 | Права доступа к файлу должны быть установлены в восьмеричное 0400 (только для 88 | чтения владельцем). Куки локального узла также можно установить с помощью 89 | встроенной функции \texttt{erlang:set\_cookie(node(), Куки)}. 90 | 91 | Текущему узлу позволяется подключаться к другому узлу \texttt{Узел2}, если он 92 | знает значение его куки. Если оно отличается от куки текущего узла (чей куки 93 | будет использован по умолчанию), то его надо явно установить с помощью 94 | встроенной функции \texttt{erlang:set\_cookie(Узел2, Куки2)}. 95 | 96 | 97 | \section{Встроенные функции для распределения} 98 | 99 | \begin{center} 100 | \begin{tabular}{|>{\raggedright}p{150pt}|>{\raggedright}p{280pt}|} 101 | \hline 102 | \multicolumn{2}{|p{326pt}|}{Встроенные функции для распределения}\tabularnewline 103 | \hline 104 | \texttt{node()} & 105 | Возвращает имя текущего узла. Позволяется использовать в охранных выражениях 106 | \tabularnewline 107 | \hline 108 | \texttt{is\_alive()} & 109 | Возвращает \texttt{true} если система является узлом и может подключаться к другим 110 | узлам, иначе \texttt{false} \tabularnewline 111 | \hline 112 | \texttt{erlang:get\_cookie()} & 113 | Возвращает магический куки текущего узла \tabularnewline 114 | \hline 115 | \texttt{set\_cookie(\\ 116 | \qquad{}Узел, Куки)} & 117 | Устанавливает магический \texttt{Куки}, который будет использован при подключении 118 | к \texttt{Узлу}. Если \texttt{Узел} --- текущий узел, то \texttt{Куки} будет 119 | использован для всех подключений к новым узлам \tabularnewline 120 | \hline 121 | \texttt{nodes()} & 122 | Возвращает список всех видимых узлов, к которым подключен текущий \tabularnewline 123 | \hline 124 | \texttt{nodes(connected)\\ 125 | nodes(hidden)} & 126 | Возвращает список не только видимых, но и скрытых и ранее известных узлов, и т.д. 127 | \tabularnewline 128 | \hline 129 | \texttt{monitor\_node(Узел,}\\ 130 | \texttt{\qquad{}true\textbar{}false)} & 131 | Отслеживает статус \texttt{Узла}. Сообщение \texttt{\{nodedown, Узел\}} будет 132 | прислано процессу, если подключение к узлу потеряно \tabularnewline 133 | \hline 134 | \texttt{node(Pid\textbar{}Ref\textbar{}Port)} & 135 | Возвращает имя узла, на котором зарегистрирован аргумент \tabularnewline 136 | \hline 137 | \texttt{erlang:disconnect\_node\\ 138 | \qquad(Узел)} & 139 | Принудительно отключает \texttt{Узел} от кластера \tabularnewline 140 | \hline 141 | \texttt{spawn[\_link\textbar{}\_opt](}\\ 142 | \texttt{Узел, Модуль, Функция, 143 | Аргументы)} & Создаёт процесс на другом (удалённом) узле \tabularnewline 144 | \hline 145 | \texttt{spawn[\_link\textbar{}\_opt](\\ 146 | Узел, Функция)} & 147 | Создаёт процесс на удалённом узле \tabularnewline 148 | \hline 149 | \end{tabular} 150 | \end{center} 151 | 152 | 153 | \section{Параметры командной строки} 154 | 155 | \begin{center} 156 | \begin{tabular}{|>{\raggedright}p{120pt}|>{\raggedright}p{310pt}|} 157 | \hline 158 | \multicolumn{2}{|p{430pt}|}{Параметры командной строки для распределённого 159 | Erlang}\tabularnewline 160 | \hline 161 | \texttt{-connect\_all false} & 162 | Подключение новых узлов только вручную и явно перечисляется каждый узел 163 | \tabularnewline 164 | \hline 165 | \texttt{-hidden} & 166 | Стартует узел как скрытый \tabularnewline 167 | \hline 168 | \texttt{-name Имя} & 169 | Превращает систему Erlang в узел кластера, используя длинные имена узлов 170 | \tabularnewline 171 | \hline 172 | \texttt{-setcookie Куки} & Аналогично вызову \linebreak{} 173 | \texttt{erlang:set\_cookie(node(), Куки))}\tabularnewline 174 | \hline 175 | \texttt{-sname Имя} & 176 | Превращает систему Erlang в узел кластера, используя короткие имена узлов 177 | \tabularnewline 178 | \hline 179 | \end{tabular} 180 | \end{center} 181 | 182 | 183 | \section{Модули с поддержкой распределённых систем} 184 | 185 | Есть несколько доступных модулей, которые пригодятся при программировании 186 | распределённых систем: 187 | 188 | \begin{center} 189 | \begin{tabular}{|>{\raggedright}p{93pt}|>{\raggedright}p{233pt}|} 190 | \hline 191 | \multicolumn{2}{|p{326pt}|}{Модули с поддержкой распределённых 192 | систем}\tabularnewline 193 | \hline 194 | \texttt{global} & 195 | Глобальное средство регистрации имён \tabularnewline 196 | \hline 197 | \texttt{global\_group} & 198 | Соединение узлов в глобальные группы регистрации имён \tabularnewline 199 | \hline 200 | \texttt{net\_adm} & 201 | Различные функции для управления сетью в Erlang-системе \tabularnewline 202 | \hline 203 | \texttt{net\_kernel} & 204 | Ядро работы с сетью \tabularnewline 205 | \hline 206 | \multicolumn{2}{|p{326pt}|}{Модули стандартной библиотеки, полезные для 207 | разработки распределённых систем}\tabularnewline 208 | \hline 209 | \texttt{slave} & Запуск и управление ведомыми узлами \tabularnewline 210 | \hline 211 | \end{tabular} 212 | \end{center} 213 | -------------------------------------------------------------------------------- /chapters-RU/09-ports-and-port-drivers.tex: -------------------------------------------------------------------------------- 1 | \chapter{Порты и драйверы портов} 2 | \label{ports} 3 | 4 | \textbf{Порты} предоставляют байто-ориентированный интерфейс к внешним 5 | программам и связывается с процессами Erlang посылая и принимая сообщения в 6 | виде списков байтов. Процесс Erlang, который создаёт порт, называется 7 | \textbf{владельцем порта} или \textbf{подключенным к порту процессом}. Все 8 | коммуникации в и из порта должны пройти через владельца порта. Если владелец 9 | порта завершает работу, порт тоже закроется (а также и внешняя программа, 10 | подключенная к порту, если она была правильно написана и среагирует на закрытие 11 | ввода/вывода). 12 | 13 | Внешняя программа является другим процессом операционной системы. По умолчанию, 14 | она должна считывать данные из стандартного входа (файловый дескриптор 0) и 15 | отвечать на стандартный вывод (файловый дескриптор 1). Внешняя программа 16 | должна завершать свою работу когда порт закрывается (ввод/вывод закрывается). 17 | 18 | 19 | \section{Драйверы портов} 20 | 21 | Драйверы портов обычно пишутся на языке С и динамически подключаются к системе 22 | исполнения Erlang. Встроенный драйвер ведёт себя как порт и называется 23 | \textbf{драйвером порта}. Однако, ошибка в драйвере порта может привести к 24 | нестабильности во всей системе Erlang, утечкам памяти, зависаниям и краху 25 | системы. 26 | 27 | 28 | \section{Встроенные функции для портов} 29 | 30 | \begin{center} 31 | \begin{tabular}{|>{\raggedright}p{140pt}|>{\raggedright}p{300pt}|} 32 | \hline 33 | \multicolumn{2}{|p{440pt}|}{Функция для создания порта} \tabularnewline 34 | \hline 35 | \texttt{open\_port(ИмяПорта, НастройкиПорта)} & 36 | Возвращает \textbf{идентификатор порта} \texttt{Порт}, как результат открытия 37 | нового Erlang-порта. Сообщения могут быть отправлены в и получены через 38 | идентификатор порта, так же как это можно делать с идентификаторами процессов. 39 | Идентификаторы портов могут быть связаны с процессами, или зарегистрированы под 40 | каким-либо именем с помощью \texttt{link/1} и \texttt{register/2}. \tabularnewline 41 | \hline 42 | \end{tabular} 43 | \end{center} 44 | 45 | \texttt{ИмяПорта} обычно является кортежем вида \texttt{\{spawn,Команда\}}, где 46 | строка \texttt{Команда} является именем внешней программы. Внешняя программа 47 | выполняется за пределами Erlang-системы, если только не найден драйвер порта с 48 | именем \texttt{Команда}. Если драйвер найден, он будет активирован вместо 49 | команды. 50 | 51 | \texttt{НастройкиПорта} --- это список настроек (опций) для порта. Список обычно 52 | содержит как минимум один кортеж \texttt{\{packet,N\}}, указывающий, что данные, 53 | пересылаемые между портом и внешней программой, предваряются N-байтовым 54 | индикатором длины. Разрешённые значения для \texttt{N} --- 1, 2 или 4. Если 55 | двоичные данные должны использоваться вместо списков байтов, то должна быть 56 | включена опция \texttt{binary}. 57 | 58 | Владелец порта Pid связывается с \texttt{Портом} с помощью отправки и получения 59 | Erlang-сообщений. (Любой процесс может послать сообщение в порт, но ответы от 60 | порта всегда будут отправлены только владельцу порта). 61 | 62 | \begin{center} 63 | \begin{tabular}{|>{\raggedright}p{140pt}|>{\raggedright}p{300pt}|} 64 | \hline 65 | \multicolumn{2}{|p{440pt}|}{Сообщения, отсылаемые в порт}\tabularnewline 66 | \hline 67 | \texttt{\{Pid, \{command, Данные\}\}} & 68 | Посылает \texttt{Данные} в порт. \tabularnewline 69 | \hline 70 | \texttt{\{Pid, close\}} & 71 | Закрывает порт. Если порт был открыт, он отвечает сообщением 72 | \texttt{\{Порт, closed\}}, когда все буферы были сброшены и порт закрылся. 73 | \tabularnewline 74 | \hline 75 | \texttt{\{Pid, \{connect, НовыйPid\}\}} & 76 | Устанавливает владельца \texttt{Порта} равным \texttt{НовомуPid}. Если порт был 77 | открыт, он отвечает сообщением \texttt{\{Порт, connected\}} старому владельцу. 78 | Заметьте, что старый владелец порта остаётся связанным с портом, тогда как новый 79 | --- нет. \tabularnewline 80 | \hline 81 | \end{tabular} 82 | \end{center} 83 | 84 | Данные должны быть списком ввода-вывода. \textbf{Список ввода-вывода} (iolist) 85 | --- это либо двоичные данные, либо смешанный (возможно вложенный) список 86 | двоичных данных и целых чисел в диапазоне от 0 до 255. 87 | 88 | \begin{center} 89 | \begin{tabular}{|>{\raggedright}p{140pt}|>{\raggedright}p{300pt}|} 90 | \hline 91 | \multicolumn{2}{|p{440pt}|}{Сообщения, получаемые из порта}\tabularnewline 92 | \hline 93 | \texttt{\{Порт, \{data, Данные\}\}} & 94 | Данные получены от внешней программы \tabularnewline 95 | \hline 96 | \texttt{\{Порт, closed\}} & 97 | Ответ на команду \texttt{Порт ! \{Pid,close\}} \tabularnewline 98 | \hline 99 | \texttt{\{Порт, connected\}} & 100 | Ответ на команду \texttt{Порт ! \{Pid,\{connect, NewPid\}\}} \tabularnewline 101 | \hline 102 | \texttt{\{'EXIT', Порт, Причина\}} & 103 | Присылается, если порт был отключен по какой-либо причине. \tabularnewline 104 | \hline 105 | \end{tabular} 106 | \end{center} 107 | 108 | Вместо того, чтобы отправлять и получать сообщения, имеется ряд встроенных 109 | функций, которые можно использовать. Они могут быть вызваны любым процессом, а 110 | не только владельцем порта. 111 | 112 | \begin{center} 113 | \begin{tabular}{|>{\raggedright}p{140pt}|>{\raggedright}p{300pt}|} 114 | \hline 115 | \multicolumn{2}{|p{440pt}|}{Встроенные функции для работы с портами} 116 | \tabularnewline 117 | \hline 118 | \texttt{port\_command(Порт, Данные)} & 119 | Отправляет \texttt{Данные} в \texttt{Порт} \tabularnewline 120 | \hline 121 | \texttt{port\_close(Порт)} & 122 | Закрывает \texttt{Порт} \tabularnewline 123 | \hline 124 | \texttt{port\_connect(Порт, НовыйPid)} & 125 | Устанавливает владельца \texttt{Порта} равным \texttt{НовомуPid}. Старый 126 | владелец остаётся связанным с портом и должен сам вызвать \texttt{unlink(Порт)} 127 | если связь не требуется. \tabularnewline 128 | \hline 129 | \texttt{erlang:port\_info(\\ 130 | Порт, Элемент)} & 131 | Возвращает информацию о \texttt{Порте} с ключом \texttt{Элемент} \tabularnewline 132 | \hline 133 | \texttt{erlang:ports()} & 134 | Возвращает список всех открытых портов на текущем узле \tabularnewline 135 | \hline 136 | \end{tabular} 137 | \end{center} 138 | 139 | Есть несколько дополнительных встроенных функций, которые применимы только к 140 | драйверам портов: это \texttt{port\_control/3} и \texttt{erlang:port\_call/3}. -------------------------------------------------------------------------------- /chapters-RU/10-code-loading.tex: -------------------------------------------------------------------------------- 1 | \chapter{Загрузка кода} 2 | \label{code} 3 | 4 | Erlang поддерживает обновление кода во время работы без остановки системы. 5 | Замена кода выполняется на уровне модулей. 6 | 7 | Код модуля может существовать в системе в двух версиях: \textbf{текущая} и 8 | \textbf{старая}. Когда модуль загружается в систему в первый раз, код становится 9 | \emph{текущим}. Если загружается новая версия модуля, то код предыдущей версии, 10 | уже имеющийся в памяти, становится \emph{старым} и новая загруженная версия 11 | становится \emph{текущей}. Обычно модуль автоматически загружается, когда 12 | вызвана одна из находящихся в нём функций. Если модуль уже загружен, то он 13 | должен быть явно перезагружен в новую версию. 14 | 15 | И старый и текущий код полностью функциональны и могут использоваться 16 | одновременно. Полностью определённые вызовы функций (с именем модуля) всегда 17 | ссылаются на текущую версию кода. Однако старый код может продолжать 18 | исполняться другими процессами. 19 | 20 | Если загрузить третью версию загруженного модуля, то сервер кода удалит 21 | (операция называется \emph{purge}) старый код и все процессы, всё ещё 22 | использующие его, будут принудительно завершены. Затем третья версия 23 | становится \emph{текущей} и предыдущий текущий код становится \emph{старым}. 24 | 25 | Чтобы перейти от старого кода к текущему, процесс должен выполнить один 26 | полностью определённый вызов функции (с именем модуля). 27 | 28 | \pagebreak 29 | \begin{erlang} 30 | -module(mod). 31 | -export([loop/0]). 32 | 33 | loop() -> 34 | receive 35 | code_switch -> 36 | mod:loop(); 37 | Msg -> 38 | ... 39 | loop() 40 | end. 41 | \end{erlang} 42 | 43 | Чтобы заставить процесс (в этом примере) сменить версию кода, отправьте ему 44 | сообщение \texttt{code\_switch}. Процесс после этого выполнит полностью 45 | определённый вызов \texttt{mod:loop()} и это переключит его на текущую версию 46 | кода. Заметьте, что \texttt{mod:loop/0} должна быть для этого экспортирована. -------------------------------------------------------------------------------- /chapters-RU/11-macros.tex: -------------------------------------------------------------------------------- 1 | \chapter{Макросы} 2 | \label{macros} 3 | 4 | \section{Определение и использование макросов} 5 | 6 | \begin{erlangru} 7 | -define(Константа, Замена). 8 | -define(Функция(Переменная1, ..., ПеременнаяN), Замена). 9 | \end{erlangru} 10 | 11 | \textbf{Макрос} должен быть определён перед тем, как он используется, но 12 | определение макроса можно поместить где угодно среди атрибутов и определений 13 | функций в модуле. Если макрос используется в нескольких модулях, рекомендуется 14 | поместить его определение во включаемый файл. Макрос используется так: 15 | 16 | \begin{erlangru} 17 | ?Константа 18 | ?Функция(Переменная1,...,ПеременнаяN) 19 | \end{erlangru} 20 | 21 | Макросы разворачиваются во время компиляции на самом раннем этапе. 22 | Ссылка на макрос \texttt{?Константа} будет заменена на текст \texttt{Замена} 23 | так: 24 | 25 | \begin{erlang} 26 | -define(TIMEOUT, 200). 27 | ... 28 | call(Request) -> 29 | server:call(refserver, Request, ?TIMEOUT). 30 | \end{erlang} 31 | 32 | разворачивается перед компиляцией в: 33 | 34 | \begin{erlang} 35 | call(Request) -> 36 | server:call(refserver, Request, 200). 37 | \end{erlang} 38 | 39 | Ссылка на макрос \texttt{?Функция(Аргумент1, ..., АргументN)} будет заменена на 40 | \texttt{Замену}, где все вхождения переменной \texttt{ПеременнаяX} из 41 | определения макроса будут заменены на соответствующий \texttt{АргументX}. 42 | 43 | \begin{erlang} 44 | -define(MACRO1(X, Y), {a, X, b, Y}). 45 | ... 46 | bar(X) -> 47 | ?MACRO1(a, b), 48 | ?MACRO1(X, 123). 49 | \end{erlang} 50 | 51 | будет развёрнуто в: 52 | 53 | \begin{erlang} 54 | bar(X) -> 55 | {a, a, b, b}, 56 | {a, X, b, 123}. 57 | \end{erlang} 58 | 59 | Для просмотра результата разворачивания макросов, модуль можно скомпилировать с 60 | параметром \texttt{'P'} таким образом: 61 | 62 | \begin{erlangru} 63 | compile:file(Файл, ['P']). 64 | \end{erlangru} 65 | 66 | Это производит распечатку разобранного кода после применения к нему 67 | предварительной обработки и трансформаций разбора (parse transform), в файле с 68 | именем \texttt{Файл.P}. 69 | 70 | 71 | \section{Предопределённые макросы} 72 | 73 | \begin{center} 74 | \begin{tabular}{|>{\raggedright}p{110pt}|>{\raggedright}p{250pt}|} 75 | \hline 76 | \multicolumn{2}{|p{330pt}|}{Предопределённые макросы}\tabularnewline 77 | \hline 78 | \texttt{?MODULE} & 79 | Атом, имя текущего модуля \tabularnewline 80 | \hline 81 | \texttt{?MODULE\_STRING} & 82 | Строка, имя текущего модуля \tabularnewline 83 | \hline 84 | \texttt{?FILE} & 85 | Имя исходного файла текущего модуля \tabularnewline 86 | \hline 87 | \texttt{?LINE} & 88 | Текущий номер строки \tabularnewline 89 | \hline 90 | \texttt{?MACHINE} & 91 | Имя виртуальной машины, 'BEAM'\tabularnewline 92 | \hline 93 | \end{tabular} 94 | \end{center} 95 | 96 | 97 | \section{Управление исполнением макросов} 98 | 99 | \begin{erlang} 100 | -undef(Macro). % Это отменяет определённый ранее макрос 101 | 102 | -ifdef(Macro). 103 | %% Строки, которые будут скомпилированы, если Macro существует 104 | -else. 105 | %% Иначе будут скомпилированы эти строки 106 | -endif. 107 | \end{erlang} 108 | 109 | \texttt{ifndef(Macro)} можно использовать вместо \texttt{ifdef} и имеет обратный 110 | смысл. 111 | 112 | \begin{erlang} 113 | -ifdef(debug). 114 | -define(LOG(X), io:format("{~p,~p}:~p~n",[?MODULE,?LINE,X])). 115 | -else. 116 | -define(LOG(X), true). 117 | -endif. 118 | \end{erlang} 119 | 120 | Если макрос \texttt{debug} определён в то время, когда идёт компиляция модуля, 121 | то макрос \texttt{?LOG(Arg)} развернётся в вызов печати текста 122 | \texttt{io:format/2} и обеспечит пользователя отладочным выводом в консоль. 123 | 124 | 125 | \section{Превращение аргументов макроса в строку} 126 | 127 | Запись вида \texttt{??Аргумент}, где \texttt{Аргумент} --- это параметр, передаваемый в макрос, развернётся в представление аргумента в строковом виде. 128 | 129 | \begin{erlang} 130 | -define(TESTCALL(Call), io:format("Call ~s: ~w~n", [??Call, Call])). 131 | 132 | ?TESTCALL(myfunction(1,2)), 133 | ?TESTCALL(you:function(2,1)), 134 | \end{erlang} 135 | 136 | \pagebreak 137 | Разворачивается в: 138 | 139 | \begin{erlang} 140 | io:format("Call ~s: ~w~n", 141 | ["myfunction(1,2)", m:myfunction(1,2)]), 142 | io:format("Call ~s: ~w~n", 143 | ["you:function(2,1)", you:function(2,1)]), 144 | \end{erlang} 145 | 146 | Таким образом, получается отладочный вывод как вызванной функции так и 147 | результата. 148 | -------------------------------------------------------------------------------- /chapters-RU/12-further-reading.tex: -------------------------------------------------------------------------------- 1 | \chapter{Дальнейшие материалы для чтения} 2 | 3 | Следующие вебсайты предлагают более подробное объяснение тем и концепций, кратко 4 | описанных в данном документе: 5 | 6 | \section{Русскоязычные ресурсы} 7 | 8 | \begin{itemize} 9 | \item Русские новости из мира Erlang \url{http://erlanger.ru} 10 | \item Группа \texttt{erlang-russian} и \texttt{erlang-in-ukraine} на сервере 11 | Google Groups. 12 | \item Книга Ф. Чезарини "<Программирование в Erlang">, русский перевод 13 | \url{http://dmkpress.com/catalog/computer/programming/functional/978-5-94074-617-1/} 14 | \end{itemize} 15 | 16 | Также обратите внимание на русскоязычный канал \texttt{erlang} на сервере 17 | \url{http://jabber.ru} 18 | 19 | \section{Англоязычные ресурсы} 20 | 21 | \begin{itemize} 22 | \item Официальная документация по Erlang: \url{http://www.erlang.org/doc/} 23 | \item Learn You Some Erlang for Great Good: \url{http://learnyousomeerlang.com/} 24 | \item Раздел с уроками на Erlang Central: 25 | \url{https://erlangcentral.org/wiki/index.php?title=Category:HowTo} 26 | \end{itemize} 27 | 28 | Ещё вопросы? Список рассылки \texttt{erlang-questions} (адрес для подписки 29 | \url{http://erlang.org/mailman/listinfo/erlang-questions}) является хорошим местом 30 | для неспешных общих дискуссий об Erlang/OTP, языке, реализации, использовании и 31 | вопросы новичков. Если вы не планируете писать в рассылку, её можно прочесть без 32 | подписки на сервере Google Groups, группа \texttt{erlang-programming}. 33 | 34 | Также обратите внимание на англоязычный IRC канал \texttt{\#erlang} в сети 35 | Freenode. 36 | -------------------------------------------------------------------------------- /chapters/01-background.tex: -------------------------------------------------------------------------------- 1 | \chapter{Background, or Why Erlang is that it is} 2 | \label{background} 3 | 4 | Erlang is the result of a project at Ericsson's Computer Science Laboratory to 5 | improve the programming of telecommunication applications. A critical 6 | requirement was supporting the characteristics of such applications, that include: 7 | 8 | \begin{itemize} 9 | \item Massive concurrency 10 | 11 | \item Fault-tolerance 12 | 13 | \item Isolation 14 | 15 | \item Dynamic code upgrading at runtime 16 | 17 | \item Transactions 18 | \end{itemize} 19 | 20 | Throughout the whole of Erlang's history the development process has 21 | been extremely pragmatic. The characteristics and properties of the 22 | types of systems in which Ericsson was interested drove Erlang's 23 | development. These properties were considered to be so 24 | fundamental that it was decided to build support for them into the 25 | language itself, rather than in libraries. Because of the pragmatic development 26 | process, rather than a result of prior planning, Erlang ``became'' a functional language --- since 27 | the features of functional languages fitted well with the properties of the systems being developed. 28 | 29 | -------------------------------------------------------------------------------- /chapters/02-structure-of-an-erlang-program.tex: -------------------------------------------------------------------------------- 1 | \chapter{Structure of an Erlang program} 2 | 3 | \section{Module syntax} 4 | 5 | An Erlang program is made up of \textbf{modules} where each module is 6 | a text file with the extension \textbf{.erl}. For small programs, all 7 | modules typically reside in one directory. 8 | A module consists of module attributes and function definitions. 9 | 10 | \begin{erlang} 11 | -module(demo). 12 | -export([double/1]). 13 | 14 | double(X) -> times(X, 2). 15 | 16 | times(X, N) -> X * N. 17 | \end{erlang} 18 | 19 | The above module \texttt{demo} consists of the function \texttt{times/2} 20 | which is local to the module and the function \texttt{double/1} which 21 | is exported and can be called from outside the module. 22 | 23 | \texttt{demo:double(10)} \resultingin \texttt{20}\hfill 24 | (the arrow $\Rightarrow$ should be read as ``resulting in'') 25 | 26 | \texttt{double/1} means the function ``double'' with \textit{one} 27 | argument. A function \texttt{double/2} taking \textit{two} arguments 28 | is regarded as a different function. The number of arguments is called 29 | the \textbf{arity} of the function. 30 | 31 | 32 | \section{Module attributes} 33 | A \textbf{module attribute} defines a certain property of a module and 34 | consists of a \textbf{tag} and a \textbf{value}: 35 | 36 | \texttt{-Tag(Value).} 37 | 38 | \texttt{Tag} must be an atom, while \texttt{Value} must be a literal 39 | term (see chapter \ref{datatypes}). Any module attribute can be specified. The 40 | attributes are stored in the compiled code and can be retrieved by 41 | calling the function \texttt{Module:module\_info(attributes).} 42 | 43 | \subsection{Pre-defined module attributes} 44 | Pre-defined module attributes must be placed before any function 45 | declaration. 46 | 47 | \begin{itemize} 48 | 49 | \item \begin{erlangim} 50 | -module(Module). 51 | \end{erlangim} 52 | This attribute is mandatory and must be specified first. It 53 | defines the name of the module. The name Module, an atom (see section \ref{datatypes:atom}), 54 | should be the same as the filename without the `\texttt{.erl}' extension. 55 | 56 | \item \begin{erlangim} 57 | -export([Func1/Arity1, ..., FuncN/ArityN]). 58 | \end{erlangim} 59 | This attribute specifies which functions in the module that 60 | can be called from outside the module. Each function name 61 | \texttt{FuncX} is an atom and \texttt{ArityX} an integer. 62 | 63 | \item \begin{erlangim} 64 | -import(Module,[Func1/Arity1, ..., FuncN/ArityN]). 65 | \end{erlangim} 66 | This attribute indicates a \texttt{Module} from which a list of functions 67 | are imported. For example: 68 | 69 | \begin{erlangim} 70 | -import(demo, [double/1]). 71 | \end{erlangim} 72 | This means that it is possible to write \texttt{double(10)} instead of 73 | the longer \texttt{demo:double(10)} which can be impractical if the 74 | function is used frequently. 75 | 76 | \item \begin{erlangim} 77 | -compile(Options). 78 | \end{erlangim} 79 | Compiler options. 80 | 81 | \item \begin{erlangim} 82 | -vsn(Vsn). 83 | \end{erlangim} 84 | Module version. If this attribute is not specified, the 85 | version defaults to the checksum of the module. 86 | 87 | \item \begin{erlangim} 88 | -behaviour(Behaviour). 89 | \end{erlangim} 90 | This attribute either specifies a user defined behaviour or 91 | one of the OTP standard behaviours \texttt{gen\_server}, 92 | \texttt{gen\_fsm}, \texttt{gen\_event} or 93 | \texttt{supervisor}. The spelling ``behavior'' is also accepted. 94 | 95 | \end{itemize} 96 | 97 | 98 | \subsection{Macro and record definitions} 99 | 100 | Records and macros are defined in the same way as module attributes: 101 | 102 | \begin{erlang} 103 | -record(Record,Fields). 104 | 105 | -define(Macro,Replacement). 106 | \end{erlang} 107 | 108 | Records and macro definitions are also allowed between functions, as 109 | long as the definition comes before its first use. (About records see 110 | section \ref{datatypes:record} and about macros see chapter \ref{macros}.) 111 | 112 | \subsection{File inclusion} 113 | 114 | File inclusion is specified in the same way as module attributes: 115 | 116 | \begin{erlang} 117 | -include(File). 118 | 119 | -include_lib(File). 120 | \end{erlang} 121 | 122 | \texttt{File} is a string that represents a file name. Include files 123 | are typically used for record and macro definitions that are shared by 124 | several modules. By convention, the extension \texttt{.hrl} is used 125 | for include files. 126 | 127 | \begin{erlang} 128 | -include("my_records.hrl"). 129 | -include("incdir/my_records.hrl"). 130 | -include("/home/user/proj/my_records.hrl"). 131 | \end{erlang} 132 | 133 | If \texttt{File} starts with a path component \texttt{\$Var}, then the value of 134 | the environment variable \texttt{Var} (returned by 135 | \texttt{os:getenv(Var)}) is substituted for \texttt{\$Var}. 136 | 137 | \begin{erlang} 138 | -include("$PROJ_ROOT/my_records.hrl"). 139 | \end{erlang} 140 | %%$ texmaker parser bug 141 | 142 | \texttt{include\_lib} is similar to \texttt{include}, but the 143 | first path component is assumed to be the name of an application. 144 | 145 | \begin{erlang} 146 | -include_lib("kernel/include/file.hrl"). 147 | \end{erlang} 148 | 149 | The code server uses \texttt{code:lib\_dir(kernel)} to find the 150 | directory of the current (latest) version of \texttt{kernel}, and then 151 | the subdirectory \texttt{include} is searched for the file \texttt{file.hrl}. 152 | 153 | 154 | \section{Comments} 155 | Comments may appear anywhere in a module except within strings and 156 | quoted atoms. A comment begins with the percentage character 157 | (\texttt{\%}) and covers the rest of the line but not the 158 | end-of-line. The terminating end-of-line has the effect of a blank. 159 | 160 | 161 | \section{Character Set} 162 | Erlang handles the full Latin-1 (ISO-8859-1) character set. Thus all 163 | Latin-1 printable characters can be used and displayed without the 164 | escape backslash. Atoms and variables can use all Latin-1 characters. 165 | 166 | \vspace*{12pt} 167 | \begin{center} 168 | \begin{tabular}{|>{\raggedright}p{52pt}|>{\raggedright}p{53pt}|>{\raggedright}p{103pt}|>{\raggedright}p{87pt}|} 169 | \hline 170 | \multicolumn{4}{|p{297pt}|}{Character classes}\tabularnewline 171 | \hline 172 | Octal & Decimal~ & & Class\tabularnewline 173 | \hline 174 | 40 - 57 & 32 - 47 & ! \texttt{"} \# \$ \% \& ' / & Punctuation 175 | characters\tabularnewline 176 | \hline 177 | 60 - 71 & 48 - 57 & 0 - 9 & Decimal digits\tabularnewline 178 | \hline 179 | 72 - 100 & 58 - 64 & : ; \texttt{<} = \texttt{>} @ & Punctuation characters\tabularnewline 180 | \hline 181 | 101 - 132 & 65 - 90 & A - Z & Uppercase letters\tabularnewline 182 | \hline 183 | 133 - 140 & 91 - 96 & [ \textbackslash{} ] \textasciicircum{} \_ ` & Punctuation 184 | characters\tabularnewline 185 | \hline 186 | 141 - 172 & 97 - 122 & a - z & Lowercase letters\tabularnewline 187 | \hline 188 | 173 - 176 & 123 - 126 & \{ \textbar{} \} \textasciitilde{} & Punctuation characters\tabularnewline 189 | \hline 190 | 200 - 237 & 128 - 159 ~ & & Control characters \tabularnewline 191 | \hline 192 | 240 - 277 & 160 - 191 & - ¿ & Punctuation characters \tabularnewline 193 | \hline 194 | 300 - 326 & 192 - 214 & À - Ö & Uppercase letters \tabularnewline 195 | \hline 196 | 327 & 215 & × & Punctuation character \tabularnewline 197 | \hline 198 | 330 - 336 & 216 - 222 & Ø - Þ & Uppercase letters \tabularnewline 199 | \hline 200 | 337 - 366 & 223 - 246 & ß - ö & Lowercase letters \tabularnewline 201 | \hline 202 | 367 & 247 & ÷ & Punctuation character \tabularnewline 203 | \hline 204 | 370 - 377 & 248 - 255 & ø - ÿ & Lowercase letters \tabularnewline 205 | \hline 206 | \end{tabular} 207 | \end{center} 208 | 209 | % because of where this lands, force a page break to avoid orphan. 210 | \newpage 211 | \section{Reserved words} 212 | 213 | %\vspace{12pt} 214 | 215 | The following are reserved words in Erlang: 216 | 217 | \begin{erlang} 218 | after and andalso band begin bnot bor bsl bsr bxor case catch cond 219 | div end fun if let not of or orelse receive rem try when xor 220 | \end{erlang} 221 | -------------------------------------------------------------------------------- /chapters/03-data-types.tex: -------------------------------------------------------------------------------- 1 | \chapter{Data types (terms)} 2 | \label{datatypes} 3 | 4 | \section{Unary data types} 5 | 6 | \subsection{Atoms} 7 | \label{datatypes:atom} 8 | An \textbf{atom} is a symbolic name, also known as a 9 | \textit{literal}. Atoms begin with a lower-case letter, and may contain alphanumeric characters, underscores (\texttt{\_}) or at-signs (\texttt{@}). 10 | Alternatively atoms can be specified by enclosing them in single quotes (\texttt{'}), necessary when they start with an uppercase character or contain 11 | characters other than underscores and at-signs. For example: 12 | 13 | \texttt{hello} 14 | 15 | \texttt{phone\_number} 16 | 17 | \texttt{'Monday'} 18 | 19 | \texttt{'phone number'} 20 | 21 | \texttt{'Anything inside quotes \textbackslash n\textbackslash 012'} 22 | \hfill(see section \ref{datatypes:escapeseq}) 23 | 24 | 25 | \subsection{Booleans} 26 | \label{datatypes:boolean} 27 | There is no \textbf{boolean} data type in Erlang. The atoms \texttt{true} and 28 | \texttt{false} are used instead. 29 | 30 | \texttt{2 =< 3} \resultingin \texttt{true} \\ 31 | \texttt{true or false} \resultingin \texttt{true} 32 | 33 | 34 | \subsection{Integers} 35 | \label{datatypes:integer} 36 | In addition to the normal way of writing \textbf{integers} Erlang 37 | provides further notations. \texttt{\$Char} is the Latin-1 numeric value of the 38 | character `\texttt{Char}' (that may be an escape sequence) and \texttt{Base\#Value} is an integer in base \texttt{Base}, which 39 | must be an integer in the range $2..36$. 40 | 41 | \texttt{42} \resultingin \texttt{42} \\ 42 | \$A \resultingin \texttt{65} \\ 43 | \texttt{\$\textbackslash n} \resultingin \texttt{10}\hfill(see section \ref{datatypes:escapeseq}) \\ 44 | \texttt{2\#101} \resultingin \texttt{5} \\ 45 | \texttt{16\#1f} \resultingin \texttt{31} 46 | 47 | 48 | \subsection{Floats} 49 | \label{datatypes:float} 50 | A \textbf{float} is a real number written \texttt{Num}[\texttt{eExp}] 51 | where \texttt{Num} is a decimal number between 0.01 and 10000 and 52 | \texttt{Exp} (optional) is a signed integer specifying the power-of-10 exponent. For example: 53 | 54 | \texttt{2.3e-3} \resultingin \texttt{2.30000e-3}\hfill 55 | (corresponding to 2.3*10\textsuperscript{-3}) 56 | 57 | 58 | \subsection{References} 59 | \label{datatypes:reference} 60 | A \textbf{reference} is a term which is unique in an Erlang runtime 61 | system, created by the built-in function \texttt{make\_ref/0}. (For more information on built-in functions, or \textit{BIF}s, see section \ref{functions:bifs}.) 62 | 63 | 64 | \subsection{Ports} 65 | \label{datatypes:port} 66 | A \textbf{port identifier} identifies a port (see chapter \ref{ports}). 67 | 68 | 69 | \subsection{Pids} 70 | \label{datatypes:pid} 71 | A \textbf{process identifier}, \textit{pid}, identifies a process (see 72 | chapter \ref{processes}). 73 | 74 | 75 | \subsection{Funs} 76 | \label{datatypes:fun} 77 | A \textit{fun} identifies a \textbf{functional object} (see section 78 | \ref{functions:funs}). 79 | 80 | 81 | \section{Compound data types} 82 | 83 | \subsection{Tuples} 84 | \label{datatypes:tuple} 85 | A \textbf{tuple} is a compound data type that holds a \textbf{fixed 86 | number of terms} enclosed within curly braces. 87 | 88 | \texttt{\{Term1,...,TermN\}} 89 | 90 | Each \texttt{TermX} in the tuple is called an \textbf{element}. The 91 | number of elements is called the \textbf{size} of the tuple. 92 | 93 | \begin{center} 94 | \begin{tabular}{|>{\raggedright}p{134pt}|>{\raggedright}p{186pt}|} 95 | \hline 96 | \multicolumn{2}{|p{321pt}|}{BIFs to manipulate tuples}\tabularnewline 97 | \hline 98 | \texttt{size(Tuple)} & Returns the size of \texttt{Tuple}\tabularnewline 99 | \hline 100 | \texttt{element(N,Tuple)} & Returns the \texttt{N}\textsuperscript{th} element in \texttt{Tuple}\tabularnewline 101 | \hline 102 | \texttt{setelement(N,Tuple,Expr)} & Returns a new tuple copied from \texttt{Tuple} except that the 103 | \texttt{N}\textsuperscript{th} element is replaced by \texttt{Expr}\tabularnewline 104 | \hline 105 | \end{tabular} 106 | \end{center} 107 | 108 | \texttt{P = \{adam, 24, \{july, 29\}\}} \resultingin \texttt{P} is bound to \texttt{\{adam, 24, \{july, 29\}\}} \\ 109 | \texttt{element(1, P)} \resultingin \texttt{adam} \\ 110 | \texttt{element(3, P)} \resultingin \texttt{ \{july,29\}} \\ 111 | \texttt{P2 = setelement(2, P, 25)} \resultingin \texttt{P2} is bound to \texttt{\{adam, 25, \{july, 29\}\}} \\ 112 | \texttt{size(P)} \resultingin \texttt{3} \\ 113 | \texttt{size(\{\})} \resultingin \texttt{0} \\ 114 | 115 | 116 | \subsection{Records} 117 | \label{datatypes:record} 118 | A \textbf{record} is a \textit{named tuple} with named elements 119 | called \textbf{fields}. A record type is defined as a module attribute, for example: 120 | 121 | \begin{erlang} 122 | -record(Rec, {Field1 [= Value1], 123 | ... 124 | FieldN [= ValueN]}). 125 | \end{erlang} 126 | 127 | \texttt{Rec} and \texttt{Fields} are atoms and each \texttt{FieldX} 128 | can be given an optional default \texttt{ValueX}. This definition may 129 | be placed amongst the functions of a module, but only before it is used. If a record type is 130 | used by several modules it is advisable to put it in a separate file for inclusion. 131 | 132 | A new record of type \texttt{Rec} is created using an expression like this: 133 | 134 | \begin{erlang} 135 | #Rec{Field1=Expr1, ..., FieldK=ExprK [, _=ExprL]} 136 | \end{erlang} 137 | 138 | The fields need not be in the same order as in the record 139 | definition. Fields omitted will get their respective default 140 | values. If the final clause is used, omitted fields will get the value 141 | \texttt{ExprL}. Fields without default values and that are omitted 142 | will have their value set to the atom \texttt{undefined}. 143 | 144 | The value of a field is retrieved using the expression 145 | ``\texttt{Variable\#Rec.Field}''. 146 | 147 | \begin{erlang} 148 | -module(employee). 149 | -export([new/2]). 150 | -record(person, {name, age, employed=erixon}). 151 | 152 | new(Name, Age) -> #person{name=Name, age=Age}. 153 | \end{erlang} 154 | 155 | The function \texttt{employee:new/2} can be used in another module 156 | which must also include the same record definition of \texttt{person}. 157 | 158 | \texttt{\{P = employee:new(ernie,44)\}} \resultingin \texttt{\{person, ernie, 44, 159 | erixon\}} \\ 160 | \texttt{P\#person.age} \resultingin \texttt{44} \\ 161 | \texttt{P\#person.employed} \resultingin \texttt{erixon} 162 | 163 | When working with records in the Erlang shell, the functions \texttt{rd(RecordName, RecordDefinition)} and \texttt{rr(Module)} can be used to 164 | define and load record definitions. Refer to the \textit{Erlang Reference Manual} for more information. 165 | 166 | 167 | \subsection{Lists} 168 | \label{datatypes:list} 169 | A \textbf{list} is a compound data type that holds a \textit{variable} 170 | number of \textbf{terms} enclosed within square brackets. 171 | 172 | \texttt{[Term1,...,TermN]} 173 | 174 | Each term \texttt{TermX} in the list is called an 175 | \textbf{element}. The \textbf{length} of a list refers to the number of elements. Common in functional programming, 176 | the first element is called the \textbf{head} of the list 177 | and the remainder (from the 2\textsuperscript{nd} element onwards) is called 178 | the \textbf{tail} of the list. Note that individual elements within a list do not have to have the same type, although it is common (and perhaps good) 179 | practice to do so --- where mixed types are involved, \textbf{records} are more commonly used. 180 | 181 | \begin{center} 182 | \begin{tabular}{|>{\raggedright}p{90pt}|>{\raggedright}p{230pt}|} 183 | \hline 184 | \multicolumn{2}{|p{321pt}|}{BIFs to manipulate lists}\tabularnewline 185 | \hline 186 | \texttt{length(List)} & Returns the length of \texttt{List}\tabularnewline 187 | \hline 188 | \texttt{hd(List)} & Returns the 1\textsuperscript{st} (head) element of \texttt{List}\tabularnewline 189 | \hline 190 | \texttt{tl(List)} & Returns \texttt{List} with the 1\textsuperscript{st} element removed (tail)\tabularnewline 191 | \hline 192 | \end{tabular} 193 | \end{center} 194 | 195 | The vertical bar operator (\textbar{}) separates the leading elements of a list (one or more) from the remainder. For example: 196 | 197 | \texttt{[H | T] = [1, 2, 3, 4, 5]} \resultingin \texttt{H=1} and \texttt{T=[2, 3, 4, 5]} \\ 198 | \texttt{[X, Y | Z] = [a, b, c, d, e]} \resultingin \texttt{X=a}, \texttt{Y=b} and \texttt{Z=[c, d, e]} 199 | 200 | Implicitly a list will end with an empty list, i.e.~\texttt{[a, b]} is 201 | the same as \texttt{[a, b | []]}. A list looking like \texttt{[a, b | c]} 202 | is \textbf{badly formed} and should be avoided (because the atom '\texttt{c}' is \textit{not} a list). 203 | Lists lend themselves naturally to recursive functional programming. For example, the following 204 | function `\texttt{sum}' computes the sum of a list, and `\texttt{double}' multiplies each element in a list by 2, constructing and returning a new list 205 | as it goes. 206 | 207 | \begin{erlang} 208 | sum([]) -> 0; 209 | sum([H | T]) -> H + sum(T). 210 | 211 | double([]) -> []; 212 | double([H | T]) -> [H*2 | double(T)]. 213 | \end{erlang} 214 | 215 | The above definitions introduce \textit{pattern matching}, described in chapter \ref{patterns}. Patterns of this form are common in recursive programming, 216 | explicitly providing a ``base case'' (for the empty list in these examples). 217 | 218 | For working with lists, the operator \texttt{++} joins two lists together (appends the second argument to the first) and 219 | returns the resulting list. The operator \texttt{-{}-} produces a list that 220 | is a copy of its first argument, except that for each element in 221 | the second argument, the first occurrence of this element (if any) in the resulting list is 222 | removed. 223 | 224 | \texttt{[1,2,3] ++ [4,5]} \resultingin \texttt{[1,2,3,4,5]} \\ 225 | \texttt{[1,2,3,2,1,2] -{}- [2,1,2]} \resultingin \texttt{[3,1,2]} 226 | 227 | A collection of list processing functions can be found in the 228 | \texttt{STDLIB} module \texttt{lists}. 229 | 230 | 231 | \subsection{Strings} 232 | \label{datatypes:string} 233 | \textbf{Strings} are character strings enclosed within double quotes 234 | but are, in fact, stored as lists of integers. 235 | 236 | \texttt{"abcdefghi"} is the same as \texttt{[97,98,99,100,101,102,103,104,105]} 237 | 238 | \texttt{""} is the same as \texttt{[]} 239 | 240 | Two adjacent strings will be concatenated into one at compile-time and 241 | do not incur any runtime overhead. 242 | 243 | \texttt{"string" "42"} \resultingin \texttt{"string42"} 244 | 245 | 246 | \subsection{Binaries} 247 | \label{datatypes:binary} 248 | A binary is a chunk of untyped memory by default a sequence of 8-bit 249 | bytes. 250 | 251 | \texttt{<}\texttt{}\texttt{>} 252 | 253 | Each \texttt{ElemX} is specified as \texttt{Value}[\texttt{:Size}][\texttt{/TypeSpecifierList}]. 254 | 255 | \begin{center} 256 | \begin{tabular}{|>{\raggedright}p{73pt}|>{\raggedright}p{81pt}|>{\raggedright}p{147pt}|} 257 | \hline 258 | \multicolumn{3}{|p{297pt}|}{Element specification}\tabularnewline 259 | \hline 260 | \texttt{Value} & \texttt{Size} & \texttt{TypeSpecifierList}\tabularnewline 261 | \hline 262 | Should evaluate to an integer, float or binary & Should 263 | evaluate to an integer & A sequence of optional type specifiers, in any order, 264 | separated by hyphens (-)\tabularnewline 265 | \hline 266 | \end{tabular} 267 | \end{center} 268 | 269 | % page break at this point, so turned into two chunks. 270 | \begin{center} 271 | \begin{tabular}{|>{\raggedright}p{47pt}|>{\raggedright}p{115pt}|>{\raggedright}p{147pt}|} 272 | \hline 273 | \multicolumn{3}{|p{297pt}|}{Type specifiers}\tabularnewline 274 | \hline 275 | Type & \texttt{integer} \textbar{} \texttt{float} \textbar{} \texttt{binary} & Default 276 | is \texttt{integer}\tabularnewline 277 | \hline 278 | Signedness & \texttt{signed} \textbar{} \texttt{unsigned} & Default is 279 | \texttt{unsigned}\tabularnewline 280 | \hline 281 | Endianness & \texttt{big} \textbar{} \texttt{little} \textbar{} \texttt{native} & CPU 282 | dependent. Default is \texttt{big}\tabularnewline 283 | \hline 284 | Unit & \texttt{unit:}\textit{IntegerLiteral} & Allowed range is $1..256$. 285 | Default is 1 for integer and float, and 8 for binary\tabularnewline 286 | \hline 287 | \end{tabular} 288 | \end{center} 289 | 290 | The value of \texttt{Size} multiplied by the unit gives the number of 291 | bits for the segment. Each segment can consist of zero or more bits 292 | but the total number of bits must be a multiple of 8, or a 293 | \texttt{badarg} run-time error will occur. Also, a segment of type 294 | binary must have a size evenly divisible by 8. 295 | 296 | Binaries cannot be nested. 297 | 298 | \begin{erlang} 299 | <<1, 17, 42>> % <<1, 17, 42>> 300 | <<"abc">> % <<97, 98, 99>> (The same as <<$a, $b, $c>>) 301 | <<1, 17, 42:16>> % <<1,17,0,42>> 302 | <<>> % <<>> 303 | <<15:8/unit:10>> % <<0,0,0,0,0,0,0,0,0,15>> 304 | <<(-1)/unsigned>> % <<255>> 305 | \end{erlang} 306 | 307 | 308 | \section{Escape sequences} 309 | \label{datatypes:escapeseq} 310 | Escape sequences are allowed in strings and quoted atoms. 311 | 312 | \begin{center} 313 | \begin{tabular}{|>{\raggedright}p{91pt}|>{\raggedright}p{229pt}|} 314 | \hline 315 | \multicolumn{2}{|p{321pt}|}{Escape sequences}\tabularnewline 316 | \hline 317 | \textbackslash{}b & Backspace\tabularnewline 318 | \hline 319 | \textbackslash{}d & Delete\tabularnewline 320 | \hline 321 | \textbackslash{}e & Escape\tabularnewline 322 | \hline 323 | \textbackslash{}f & Form feed\tabularnewline 324 | \hline 325 | \textbackslash{}n & New line\tabularnewline 326 | \hline 327 | \textbackslash{}r & Carriage return\tabularnewline 328 | \hline 329 | \textbackslash{}s & Space\tabularnewline 330 | \hline 331 | \textbackslash{}t & Tab\tabularnewline 332 | \hline 333 | \textbackslash{}v & Vertical tab\tabularnewline 334 | \hline 335 | \textbackslash{}XYZ, \textbackslash{}XY, \textbackslash{}X & Character with octal 336 | representation XYZ, XY or X\tabularnewline 337 | \hline 338 | \textbackslash{}\textasciicircum{}A .. \textbackslash{}\textasciicircum{}Z & Control 339 | A to control Z\tabularnewline 340 | \hline 341 | \textbackslash{}\textasciicircum{}a .. \textbackslash{}\textasciicircum{}z & Control 342 | A to control Z\tabularnewline 343 | \hline 344 | \textbackslash{}' & Single quote\tabularnewline 345 | \hline 346 | \textbackslash{}\textbf{\texttt{"}} & Double quote\tabularnewline 347 | \hline 348 | \textbackslash{}\textbackslash{} & Backslash\tabularnewline 349 | \hline 350 | \end{tabular} 351 | \end{center} 352 | 353 | \section{Type conversions} 354 | There are a number of built-in functions for type conversion: 355 | 356 | \begin{center} 357 | \begin{tabular}{|>{\raggedright}p{63pt}|>{\raggedright}p{21pt}|>{\raggedright}p{25pt}|>{\raggedright}p{21pt}|>{\raggedright}p{21pt}|>{\raggedright}p{21pt}|>{\raggedright}p{21pt}|>{\raggedright}p{21pt}|>{\raggedright}p{24pt}|} 358 | \hline 359 | \multicolumn{9}{|p{243pt}|}{Type conversions}\tabularnewline 360 | \hline 361 | & atom & integer & float & pid & fun & tuple & list & binary\tabularnewline 362 | \hline 363 | atom & & - & - & - & - & - & X & X\tabularnewline 364 | \hline 365 | integer & - & & X & - & - & - & X & X\tabularnewline 366 | \hline 367 | float & - & X & & - & - & - & X & X\tabularnewline 368 | \hline 369 | pid & - & - & - & & - & - & X & X\tabularnewline 370 | \hline 371 | fun & - & - & - & - & & - & X & X\tabularnewline 372 | \hline 373 | tuple & - & - & - & - & - & & X & X\tabularnewline 374 | \hline 375 | list & X & X & X & X & X & X & & X\tabularnewline 376 | \hline 377 | binary & X & X & X & X & X & X & X & \tabularnewline 378 | \hline 379 | \end{tabular} 380 | \end{center} 381 | 382 | The BIF \texttt{float/1} converts integers to floats. The BIFs 383 | \texttt{round/1} and \texttt{trunc/1} convert floats to integers. 384 | 385 | The BIFs \texttt{Type\_to\_list/1} and \texttt{list\_to\_Type/1} 386 | convert to and from lists. 387 | 388 | The BIFs \texttt{term\_to\_binary/1} and \texttt{binary\_to\_term/1} 389 | convert to and from binaries. 390 | 391 | \begin{erlang} 392 | atom_to_list(hello) % "hello" 393 | list_to_atom("hello") % hello 394 | float_to_list(7.0) % "7.00000000000000000000e+00" 395 | list_to_float("7.000e+00") % 7.00000 396 | integer_to_list(77) % "77" 397 | list_to_integer("77") % 77 398 | tuple_to_list({a, b ,c}) % [a,b,c] 399 | list_to_tuple([a, b, c]) % {a,b,c} 400 | pid_to_list(self()) % "<0.25.0>" 401 | term_to_binary(<<17>>) % <<131,109,0,0,0,1,17>> 402 | term_to_binary({a, b ,c}) % <<131,104,3,100,0,1,97,100,0,1,98,100,0,1,99>> 403 | binary_to_term(<<131,104,3,100,0,1,97,100,0,1,98,100,0,1,99>>) % {a,b,c} 404 | term_to_binary(math:pi()) % <<131,99,51,46,49,52,49,53,57,50,54,53,51,...>> 405 | \end{erlang} 406 | 407 | -------------------------------------------------------------------------------- /chapters/04-pattern-matching.tex: -------------------------------------------------------------------------------- 1 | \chapter{Pattern Matching} 2 | \label{patterns} 3 | 4 | \section{Variables} 5 | \label{patterns:variables} 6 | 7 | \textbf{Variables} are introduced as arguments to a function or as a 8 | result of pattern matching. Variables begin with an uppercase letter 9 | or underscore (\texttt{\_}) and may contain alphanumeric characters, 10 | underscores and at-signs (\texttt{@}). Variables can only be bound 11 | (assigned) once. 12 | 13 | \begin{erlang} 14 | Abc 15 | A_long_variable_name 16 | AnObjectOrientatedVariableName 17 | _Height 18 | \end{erlang} 19 | 20 | An \textbf{anonymous variable} is denoted by a single underscore (\texttt{\_}) 21 | and can be used when a variable is required but its value can be 22 | ignored. 23 | 24 | \begin{erlang} 25 | [H|_] = [1,2,3] % H=1 and the rest is ignored 26 | \end{erlang} 27 | 28 | Variables beginning with underscore like \texttt{\_Height} are normal 29 | variables, not anonymous. They are however ignored by the compiler in 30 | the sense that they will not generate any warnings for unused 31 | variables. Thus it is possible to write: 32 | 33 | \begin{erlang} 34 | member(_Elem, []) -> 35 | false. 36 | \end{erlang} 37 | 38 | instead of: 39 | 40 | \begin{erlang} 41 | member(_, []) -> 42 | false. 43 | \end{erlang} 44 | 45 | which can make for more readable code. 46 | 47 | The \textit{scope} for a variable is its function clause. Variables 48 | bound in a branch of an \texttt{if}, \texttt{case}, or 49 | \texttt{receive} expression must be bound in all branches to have a 50 | value outside the expression, otherwise they will be regarded as 51 | \textit{unsafe} (possibly undefined) outside the expression. 52 | 53 | 54 | \section{Pattern Matching} 55 | A \textbf{pattern} has the same structure as a term but may contain 56 | new unbound variables. 57 | 58 | \begin{erlang} 59 | Name1 60 | [H|T] 61 | {error,Reason} 62 | \end{erlang} 63 | 64 | Patterns occur in \textit{function heads}, \textit{case}, 65 | \textit{receive}, and \textit{try} expressions and in match operator 66 | (\texttt{=}) expressions. Patterns are evaluated through 67 | \textbf{pattern matching} against an expression and this is how 68 | variables are defined and bound. 69 | 70 | \begin{erlang} 71 | Pattern = Expr 72 | \end{erlang} 73 | 74 | Both sides of the expression must have the same structure. If the 75 | matching succeeds, all unbound variables, if any, in the pattern 76 | become bound. If the matching fails, a \texttt{badmatch} run-time 77 | error will occur. 78 | 79 | 80 | \begin{minted}{console} 81 | > {A, B} = {answer, 42}. 82 | {answer,42} 83 | > A. 84 | answer 85 | > B. 86 | 42 87 | \end{minted} 88 | 89 | \subsection{Match operator (\texttt{=}) in patterns} 90 | If \texttt{Pattern1} and \texttt{Pattern2} are valid patterns, then 91 | the following is also a valid pattern: 92 | 93 | \begin{erlang} 94 | Pattern1 = Pattern2 95 | \end{erlang} 96 | 97 | The \texttt{=} introduces an \textbf{alias} which when matched against an 98 | expression, both \texttt{Pattern1} and \texttt{Pattern2} are matched 99 | against it. The purpose of this is to avoid the reconstruction of terms. 100 | 101 | \begin{erlang} 102 | foo({connect,From,To,Number,Options}, To) -> 103 | Signal = {connect,From,To,Number,Options}, 104 | fox(Signal), 105 | ...; 106 | \end{erlang} 107 | 108 | which can be written more efficiently as: 109 | 110 | \begin{erlang} 111 | foo({connect,From,To,Number,Options} = Signal, To) -> 112 | fox(Signal), 113 | ...; 114 | \end{erlang} 115 | 116 | 117 | \subsection{String prefix in patterns} 118 | When matching strings, the following is a valid pattern: 119 | 120 | \begin{erlang} 121 | f("prefix" ++ Str) -> ... 122 | \end{erlang} 123 | 124 | which is equivalent to and easier to read than: 125 | 126 | \begin{erlang} 127 | f([$p,$r,$e,$f,$i,$x | Str]) -> ... 128 | \end{erlang} 129 | 130 | You can only use strings as prefix expressions; patterns such as \texttt{Str ++ "postfix"} are not allowed. 131 | 132 | \subsection{Expressions in patterns} 133 | An arithmetic expression can be used within a pattern, provided it 134 | only uses numeric or bitwise operators and its value can be evaluated 135 | to a constant at compile-time. 136 | 137 | \begin{erlang} 138 | case {Value, Result} of 139 | {?Threshold+1, ok} -> ... % ?Threshold is a macro 140 | \end{erlang} 141 | 142 | \subsection{Matching binaries} 143 | 144 | \begin{erlang} 145 | Bin = <<1, 2, 3>> % <<1,2,3>> All elements are 8-bit bytes 146 | <> = Bin % A=1, B=2 and C=3 147 | <> = Bin % D=258 and E=3 148 | <> = Bin % F=1 and G=<<2,3>> 149 | \end{erlang} 150 | 151 | In the last line, the variable \texttt{G} of unspecified size matches the 152 | rest of the binary \texttt{Bin}. 153 | 154 | Always put a space between (\texttt{=}) and (\verb|<<|) so as to 155 | avoid confusion with the (\texttt{=<}) operator. 156 | 157 | -------------------------------------------------------------------------------- /chapters/05-functions.tex: -------------------------------------------------------------------------------- 1 | \chapter{Functions} 2 | 3 | \section{Function definition} 4 | A function is defined as a sequence of one or more \textbf{function 5 | clauses}. The function name is an atom. 6 | 7 | \vspace*{4pt} 8 | \begin{erlang} 9 | Func(Pattern11,...,Pattern1N) [when GuardSeq1] -> Body1; 10 | ...; 11 | ...; 12 | Func(PatternK1,...,PatternKN) [when GuardSeqK] -> BodyK. 13 | 14 | \end{erlang} 15 | \vspace*{4pt} 16 | 17 | The function clauses are separated by semicolons (\texttt{;}) and 18 | terminated by full stop (\texttt{.}). A function clause consists of a 19 | \textbf{clause head} and a \textbf{clause body} separated by an arrow 20 | (\texttt{->}). A clause head consists of the function name (an atom), 21 | arguments within parentheses and an optional guard sequence beginning 22 | with the keyword \texttt{when}. Each argument is a pattern. A clause 23 | body consists of a sequence of expressions separated by commas 24 | (\texttt{,}). 25 | 26 | \vspace*{4pt} 27 | \begin{erlang} 28 | Expr1, 29 | ..., 30 | ExprM 31 | \end{erlang} 32 | \vspace*{4pt} 33 | 34 | The number of arguments \texttt{N} is the \textbf{arity} of the 35 | function. A function is uniquely defined by the module name, function name 36 | and arity. Two different functions in the same module with different 37 | arities may have the same name. A function \texttt{Func} in \texttt{Module} 38 | with arity \texttt{N} is often denoted as \texttt{Module:Func/N}. 39 | 40 | \vspace*{4pt} 41 | \begin{erlang} 42 | -module(mathStuff). 43 | -export([area/1]). 44 | 45 | area({square, Side}) -> Side * Side; 46 | area({circle, Radius}) -> math:pi() * Radius * Radius; 47 | area({triangle, A, B, C}) -> 48 | S = (A + B + C)/2, 49 | math:sqrt(S*(S-A)*(S-B)*(S-C)). 50 | \end{erlang} 51 | 52 | % push this section onto the next page (orphan line) 53 | \newpage 54 | \section{Function calls} 55 | A function is called using: 56 | 57 | \begin{erlang} 58 | [Module:]Func(Expr1, ..., ExprN) 59 | \end{erlang} 60 | 61 | \texttt{Module} evaluates to a module name and \texttt{Func} to 62 | a function name or a \textit{fun}. When calling a function in another 63 | module, the module name must be provided and the function must be 64 | exported. This is referred to as a \textbf{fully qualified function name}. 65 | 66 | \begin{erlang} 67 | lists:keysearch(Name, 1, List) 68 | \end{erlang} 69 | 70 | The module name can be omitted if \texttt{Func} evaluates to the name 71 | of a local function, an imported function, or an auto-imported 72 | BIF. In such cases, the function is called using an \textbf{implicitly qualified function name}. 73 | 74 | Before calling a function the arguments \texttt{ExprX} are 75 | evaluated. If the function cannot be found, an \texttt{undef} run-time 76 | error will occur. Next the function clauses are scanned sequentially 77 | until a clause is found such that the patterns in the clause head can 78 | be successfully matched against the given arguments and that the guard 79 | sequence, if any, is true. If no such clause can be found, a 80 | \texttt{function\_clause} run-time error will occur. 81 | 82 | If a matching clause is found, the corresponding clause body is evaluated, 83 | i.e.~the expressions in the body are evaluated sequentially and the 84 | value of the last expression is returned. 85 | 86 | The fully qualified function name must be used when calling a function 87 | with the same name as a BIF (built-in function, see section 88 | \ref{functions:bifs}). The compiler does not allow defining a function 89 | with the same name as an imported function. When calling a local 90 | function, there is a difference between using the implicitly or fully 91 | qualified function name, as the latter always refers to the latest 92 | version of the module (see chapter \ref{code}). 93 | 94 | 95 | \section{Expressions} 96 | \label{functions:expressions} 97 | An \textbf{expression} is either a term or the invocation of an 98 | operator, for example: 99 | 100 | \begin{erlang} 101 | Term 102 | op Expr 103 | Expr1 op Expr2 104 | (Expr) 105 | begin 106 | Expr1, 107 | ..., 108 | ExprM % no comma (,) before end 109 | end 110 | 111 | \end{erlang} 112 | 113 | The simplest form of expression is a term, i.e.~an \textit{integer}, 114 | \textit{float}, \textit{atom}, \textit{string}, \textit{list} or 115 | \textit{tuple} and the return value is the term itself. 116 | There are both \textit{unary} and \textit{binary} operators. An expression 117 | may contain \textit{macro} or \textit{record} expressions which will 118 | expanded at compile time. 119 | 120 | Parenthesised expressions are useful to override operator precedence (see section \ref{functions:expressions:precedence}): 121 | 122 | \begin{erlang} 123 | 1 + 2 * 3 % 7 124 | (1 + 2) * 3 % 9 125 | \end{erlang} 126 | 127 | Block expressions within \texttt{begin...end} can be used to group a 128 | sequence of expressions and the return value is the value of the last 129 | expression \texttt{ExprM}. 130 | 131 | All subexpressions are evaluated before the expression itself is 132 | evaluated, but the order in which subexpressions are evaluated is undefined. 133 | 134 | Most operators can only be applied to arguments of a certain type. For 135 | example, arithmetic operators can only be applied to integers or 136 | floats. An argument of the wrong type will cause a \texttt{badarg} 137 | run-time error. 138 | 139 | 140 | \subsection{Term comparisons} 141 | \begin{erlang} 142 | Expr1 op Expr2 143 | \end{erlang} 144 | 145 | A \textbf{term comparison} returns a \textit{boolean} value, 146 | in the form of atoms \texttt{true} or \texttt{false}. 147 | 148 | \begin{center} 149 | \begin{tabular}{|>{\raggedright}p{40pt}|>{\raggedright}p{105pt}|>{\raggedright}p{26pt}|>{\raggedright}p{124pt}|} 150 | \hline 151 | \multicolumn{4}{|p{297pt}|}{Comparison operators}\tabularnewline 152 | \hline 153 | \texttt{==} & Equal to & \texttt{=<} & Less than or equal to\tabularnewline 154 | \hline 155 | \texttt{/=} & Not equal to & \texttt{<} & Less than\tabularnewline 156 | \hline 157 | \texttt{=:=} & Exactly equal to & \texttt{>}= & Greater than or equal to\tabularnewline 158 | \hline 159 | \texttt{=/=} & Exactly not equal to & \texttt{>} & Greater than\tabularnewline 160 | \hline 161 | \end{tabular} 162 | \end{center} 163 | 164 | \begin{erlang} 165 | 1==1.0 % true 166 | 1=:=1.0 % false 167 | 1 > a % false 168 | \end{erlang} 169 | 170 | The arguments may be of different data types. The following order is 171 | defined: 172 | 173 | \texttt{number < atom < reference < fun < port < pid < tuple < list < binary} 174 | 175 | Lists are compared element by element. Tuples are ordered by size, two 176 | tuples with the same size are compared element by element. When 177 | comparing an integer and a float, the integer is first converted to a 178 | float. In the case of \texttt{=:=} or \texttt{=/=} there is no type conversion. 179 | 180 | 181 | \subsection{Arithmetic expressions} 182 | 183 | \begin{erlang} 184 | op Expr 185 | Expr1 op Expr2 186 | \end{erlang} 187 | 188 | An \textbf{arithmetic expression} returns the result after applying 189 | the operator. 190 | 191 | \begin{center} 192 | \begin{tabular}{|>{\raggedright}p{35pt}|>{\raggedright}p{145pt}|>{\raggedright}p{128pt}|} 193 | \hline 194 | \multicolumn{3}{|p{309pt}|}{Arithmetic operators}\tabularnewline 195 | \hline 196 | \texttt{+} & Unary + & \texttt{Integer \textbar{} Float} \tabularnewline 197 | \hline 198 | \texttt{-} & Unary - & \texttt{Integer \textbar{} Float}\tabularnewline 199 | \hline 200 | \texttt{+} & Addition & \texttt{Integer} \textbar{} \texttt{Float}\tabularnewline 201 | \hline 202 | \texttt{-} & Subtraction & \texttt{Integer} \textbar{} \texttt{Float}\tabularnewline 203 | \hline 204 | \texttt{*} & Multiplication & \texttt{Integer} \textbar{} \texttt{Float}\tabularnewline 205 | \hline 206 | \texttt{/} & Floating point division & \texttt{Integer} \textbar{} \texttt{Float}\tabularnewline 207 | \hline 208 | \texttt{bnot} & Unary bitwise not & \texttt{Integer} \tabularnewline 209 | \hline 210 | \texttt{div} & Integer division & \texttt{Integer}\tabularnewline 211 | \hline 212 | \texttt{rem} & Integer remainder of X/Y & \texttt{Integer} \tabularnewline 213 | \hline 214 | \texttt{band} & Bitwise and & \texttt{Integer}\tabularnewline 215 | \hline 216 | \texttt{bor} & Bitwise or & \texttt{Integer} \tabularnewline 217 | \hline 218 | \texttt{bxor} & Arithmetic bitwise xor & \texttt{Integer}\tabularnewline 219 | \hline 220 | \texttt{bsl} & Arithmetic bitshift left & \texttt{Integer} \tabularnewline 221 | \hline 222 | \texttt{bsr} & Bitshift right & \texttt{Integer}\tabularnewline 223 | \hline 224 | \end{tabular} 225 | \end{center} 226 | 227 | \begin{erlang} 228 | +1 % 1 229 | 4/2 % 2.00000 230 | 5 div 2 % 2 231 | 5 rem 2 % 1 232 | 2#10 band 2#01 % 0 233 | 2#10 bor 2#01 % 3 234 | \end{erlang} 235 | 236 | 237 | \subsection{Boolean expressions} 238 | 239 | \begin{erlang} 240 | op Expr 241 | Expr1 op Expr2 242 | \end{erlang} 243 | 244 | A \textbf{boolean expression} returns the value \texttt{true} or 245 | \texttt{false} after applying the operator. 246 | 247 | \begin{center} 248 | \begin{tabular}{|>{\raggedright}p{79pt}|>{\raggedright}p{241pt}|} 249 | \hline 250 | \multicolumn{2}{|p{321pt}|}{Boolean operators}\tabularnewline 251 | \hline 252 | \texttt{not} & Unary logical not \tabularnewline 253 | \hline 254 | \texttt{and} & Logical and \tabularnewline 255 | \hline 256 | \texttt{or} & Logical or \tabularnewline 257 | \hline 258 | \texttt{xor} & Logical exclusive or\tabularnewline 259 | \hline 260 | \end{tabular} 261 | \end{center} 262 | 263 | \begin{erlang} 264 | not true % false 265 | true and false % false 266 | true xor false % true 267 | \end{erlang} 268 | 269 | 270 | \subsection{Short-circuit boolean expressions} 271 | 272 | \begin{erlang} 273 | Expr1 orelse Expr2 274 | Expr1 andalso Expr2 275 | \end{erlang} 276 | 277 | These are boolean expressions where \texttt{Expr2} is evaluated only 278 | if necessary. In an \texttt{orelse} expression \texttt{Expr2} will be 279 | evaluated only if \texttt{Expr1} evaluates to false. In an 280 | \texttt{andalso} expression \texttt{Expr2} will be evaluated only if 281 | \texttt{Expr1} evaluates to true. 282 | 283 | \begin{erlang} 284 | if A >= 0 andalso math:sqrt(A) > B -> ... 285 | 286 | if is_list(L) andalso length(L) == 1 -> ... 287 | \end{erlang} 288 | 289 | 290 | \subsection{Operator precedences} 291 | \label{functions:expressions:precedence} 292 | In an expression consisting of subexpressions the operators will be 293 | applied according to a defined \textbf{operator precedence} order: 294 | 295 | \begin{center} 296 | \begin{tabular}{|>{\raggedright}p{221pt}|>{\raggedright}p{99pt}|} 297 | \hline 298 | \multicolumn{2}{|p{321pt}|}{Operator precedence (from high to low)}\tabularnewline 299 | \hline 300 | \texttt{:} ~ & \tabularnewline 301 | \hline 302 | \texttt{\#} ~ & \tabularnewline 303 | \hline 304 | \texttt{Unary + - bnot not ~} & \tabularnewline 305 | \hline 306 | \texttt{/ * div rem band and} & Left associative \tabularnewline 307 | \hline 308 | \texttt{+ - bor bxor bsl bsr or xor} & Left associative \tabularnewline 309 | \hline 310 | \texttt{++ -{}-} & Right associative \tabularnewline 311 | \hline 312 | \texttt{== /= =< < >= > =:= =/=} & \tabularnewline 313 | \hline 314 | \texttt{andalso} & \tabularnewline 315 | \hline 316 | \texttt{orelse} & \tabularnewline 317 | \hline 318 | \texttt{= !} & Right associative \tabularnewline 319 | \hline 320 | \texttt{catch ~} & \tabularnewline 321 | \hline 322 | \end{tabular} 323 | \end{center} 324 | 325 | The operator with the highest priority is evaluated first. Operators 326 | with the same priority are evaluated according to their 327 | \textbf{associativity}. The left associative arithmetic operators 328 | are evaluated left to right: 329 | 330 | \texttt{6 + 5 * 4 - 3 / 2 \resultingin 6 + 20 - 1.5 \resultingin 26 - 1.5 \resultingin 24.5} 331 | 332 | 333 | \section{Compound expressions} 334 | 335 | 336 | \subsection{If} 337 | 338 | \begin{erlang} 339 | if 340 | GuardSeq1 -> 341 | Body1; 342 | ...; 343 | GuardSeqN -> 344 | BodyN % Note no semicolon (;) before end 345 | end 346 | \end{erlang} 347 | 348 | The branches of an \texttt{if} expression are scanned sequentially 349 | until a guard sequence \texttt{GuardSeq} which evaluates to 350 | \texttt{true} is found. The corresponding \texttt{Body} (sequence 351 | of expressions separated by commas) is then evaluated. The return value of 352 | \texttt{Body} is the return value of the \texttt{if} expression. 353 | 354 | If no guard sequence is true, an \texttt{if\_clause} run-time error 355 | will occur. If necessary, the guard expression \texttt{true} can be used in the 356 | last branch, as that guard sequence is always true (known as a ``catch 357 | all''). 358 | 359 | \begin{erlang} 360 | is_greater_than(X, Y) -> 361 | if 362 | X>Y -> 363 | true; 364 | true -> % works as an 'else' branch 365 | false 366 | end 367 | \end{erlang} 368 | 369 | It should be noted that pattern matching in function clauses can be used to replace \texttt{if} cases (most of the time). 370 | Overuse of \texttt{if} sentences withing function bodies is considered a bad Erlang practice. 371 | 372 | \subsection{Case} 373 | 374 | Case expressions provide for inline pattern matching, similar to the way in which function clauses are matched. 375 | 376 | \begin{erlang} 377 | case Expr of 378 | Pattern1 [when GuardSeq1] -> 379 | Body1; 380 | ...; 381 | PatternN [when GuardSeqN] -> 382 | BodyN % Note no semicolon (;) before end 383 | end 384 | \end{erlang} 385 | 386 | The expression \texttt{Expr} is evaluated and the patterns 387 | \texttt{Pattern1}...\texttt{PatternN} are sequentially matched against the result. If a 388 | match succeeds and the optional guard sequence \texttt{GuardSeqX} is 389 | \texttt{true}, then the corresponding \texttt{BodyX} is evaluated. The return value 390 | of \texttt{BodyX} is the return value of the case expression. 391 | 392 | If there is no matching pattern with a true guard sequence, a 393 | \texttt{case\_clause} run-time error will occur. 394 | 395 | \begin{erlang} 396 | is_valid_signal(Signal) -> 397 | case Signal of 398 | {signal, _What, _From, _To} -> 399 | true; 400 | {signal, _What, _To} -> 401 | true; 402 | _Else -> % 'catch all' 403 | false 404 | end. 405 | \end{erlang} 406 | 407 | 408 | \subsection{List comprehensions} 409 | List comprehensions are analogous to the \texttt{setof} and 410 | \texttt{findall} predicates in Prolog. 411 | 412 | \begin{erlang} 413 | [Expr || Qualifier1,...,QualifierN] 414 | \end{erlang} 415 | 416 | \texttt{Expr} is an arbitrary expression, and each \texttt{QualifierX} 417 | is either a \textbf{generator} or a \textbf{filter}. A generator is 418 | written as: 419 | 420 | \begin{erlang} 421 | Pattern <- ListExpr 422 | \end{erlang} 423 | 424 | where \texttt{ListExpr} must be an expression which evaluates to a 425 | list of terms. A filter is an expression which evaluates to 426 | \texttt{true} or \texttt{false}. Variables in list generator 427 | expressions \textit{shadow} variables in the function clause 428 | surrounding the list comprehension. 429 | 430 | The qualifiers are evaluated from left to right, the generators 431 | creating values and the filters constraining them. The list 432 | comprehension then returns a list where the elements are the result of 433 | evaluating \texttt{Expr} for each combination of the resulting values. 434 | 435 | \begin{minted}{console} 436 | > [{X, Y} || X <- [1,2,3,4,5,6], X > 4, Y <- [a,b,c]]. 437 | [{5,a},{5,b},{5,c},{6,a},{6,b},{6,c}] 438 | \end{minted} 439 | 440 | 441 | \section{Guard sequences} 442 | A \textbf{guard sequence} is a set of \textbf{guards} separated by 443 | semicolons (\texttt{;}). The guard sequence is \texttt{true} if at 444 | least one of the guards is \texttt{true}. 445 | 446 | \begin{erlang} 447 | Guard1; ...; GuardK 448 | \end{erlang} 449 | 450 | A \textbf{guard} is a set of \textbf{guard expressions} separated by 451 | commas (\texttt{,}). The guard is \texttt{true} if all guard 452 | expressions evaluate to \texttt{true}. 453 | 454 | \begin{erlang} 455 | GuardExpr1, ..., GuardExprN 456 | \end{erlang} 457 | 458 | The permitted \textbf{guard expressions} (sometimes called guard 459 | tests) are a subset of valid Erlang expressions, since the 460 | evaluation of a guard expression must be guaranteed to be free of side-effects. 461 | 462 | \begin{center} 463 | \begin{tabular}{|>{\raggedright}p{154pt}|>{\raggedright}p{166pt}|} 464 | \hline 465 | \multicolumn{2}{|p{321pt}|}{Valid guard expressions:}\tabularnewline 466 | \hline 467 | \multicolumn{2}{|p{321pt}|}{The atom \texttt{true};}\tabularnewline 468 | \hline 469 | \multicolumn{2}{|p{321pt}|}{Other constants (terms and bound variables), are all regarded 470 | as \texttt{false};}\tabularnewline 471 | \hline 472 | \multicolumn{2}{|p{321pt}|}{Term comparisons;}\tabularnewline 473 | \hline 474 | \multicolumn{2}{|p{321pt}|}{Arithmetic and boolean expressions;}\tabularnewline 475 | \hline 476 | \multicolumn{2}{|p{321pt}|}{Calls to the BIFs specified below.}\tabularnewline 477 | \hline 478 | Type test BIFs & Other BIFs allowed in guards:\tabularnewline 479 | \hline 480 | \texttt{is\_atom/1} & \texttt{abs(Integer} \textbar{} \texttt{Float)}\tabularnewline 481 | \hline 482 | \texttt{is\_constant/1} & \texttt{float(Term)}\tabularnewline 483 | \hline 484 | \texttt{is\_integer/1} & \texttt{trunc(Integer} \textbar{} \texttt{Float)}\tabularnewline 485 | \hline 486 | \texttt{is\_float/1} & \texttt{round(Integer} \textbar{} \texttt{Float)}\tabularnewline 487 | \hline 488 | \texttt{is\_number/1} & \texttt{size(Tuple} \textbar{} \texttt{Binary)}\tabularnewline 489 | \hline 490 | \texttt{is\_reference/1} & \texttt{element(N, Tuple)}\tabularnewline 491 | \hline 492 | \texttt{is\_port/1} & \texttt{hd(List)}\tabularnewline 493 | \hline 494 | \texttt{is\_pid/1} & \texttt{tl(List)}\tabularnewline 495 | \hline 496 | \texttt{is\_function/1} & \texttt{length(List)}\tabularnewline 497 | \hline 498 | \texttt{is\_tuple/1} & \texttt{self()}\tabularnewline 499 | \hline 500 | \texttt{is\_record/2} The 2\textsuperscript{nd} argument is \linebreak{} 501 | the record name & \texttt{node(})\tabularnewline 502 | \hline 503 | \texttt{is\_list/1} & \texttt{node(Pid} \textbar{} \texttt{Ref} \textbar \texttt{Port)}\tabularnewline 504 | \hline 505 | \texttt{is\_binary/1} & \tabularnewline 506 | \hline 507 | \end{tabular} 508 | \end{center} 509 | 510 | A small example: 511 | 512 | \begin{erlang} 513 | fact(N) when N>0 -> % first clause head 514 | N * fact(N-1); % first clause body 515 | fact(0) -> % second clause head 516 | 1. % second clause body 517 | \end{erlang} 518 | 519 | 520 | \section{Tail recursion} 521 | If the last expression of a function body is a function call, a 522 | \textbf{tail recursive} call is performed in such a way that no system 523 | resources (like the call stack) are consumed. This means that an 524 | infinite loop like a server can be programmed provided it only uses 525 | tail recursive calls. 526 | 527 | The function \texttt{fact/1} above could be rewritten using tail 528 | recursion in the following manner: 529 | 530 | \begin{erlang} 531 | fact(N) when N>1 -> fact(N, N-1); 532 | fact(N) when N==1; N==0 -> 1. 533 | 534 | fact(F,0) -> F; % The variable F is used as an accumulator 535 | fact(F,N) -> fact(F*N, N-1). 536 | \end{erlang} 537 | 538 | 539 | \section{Funs} 540 | \label{functions:funs} 541 | A \textbf{fun} defines a \textit{functional object}. Funs make it 542 | possible to pass an entire function, not just the function name, as an 543 | argument. A `fun' expression begins with the keyword \texttt{fun} and 544 | ends with the keyword \texttt{end} instead of a full stop 545 | (\texttt{.}). Between these should be a regular function 546 | declaration, except that no function name is specified. 547 | 548 | \begin{erlang} 549 | fun 550 | (Pattern11,...,Pattern1N) [when GuardSeq1] -> 551 | Body1; 552 | ...; 553 | (PatternK1,...,PatternKN) [when GuardSeqK] -> 554 | BodyK 555 | end 556 | \end{erlang} 557 | 558 | Variables in a \texttt{fun} head \textit{shadow} variables in the function 559 | clause surrounding the \texttt{fun} but variables bound in a \texttt{fun} body are local 560 | to the body. The return value of the expression is the resulting function. The expression 561 | \texttt{fun Name/N is} equivalent to: 562 | 563 | \begin{erlang} 564 | fun (Arg1,...,ArgN) -> Name(Arg1,...,ArgN) end 565 | \end{erlang} 566 | 567 | The expression \texttt{fun Module:Func/Arity} is also allowed, provided that \texttt{Func} is exported 568 | from \texttt{Module}. 569 | 570 | \begin{erlang} 571 | Fun1 = fun (X) -> X+1 end. 572 | Fun1(2) % 3 573 | 574 | Fun2 = fun (X) when X>=1000 -> big; (X) -> small end. 575 | Fun2(2000) % big 576 | \end{erlang} 577 | 578 | Anonymous \texttt{funs}: When a \texttt{fun} is anonymous, i.e.~there is no function name in the definition of the \texttt{fun}, the definition of a recursive \texttt{fun} has to be done in two steps. This example shows how to define an anonymous \texttt{fun} \texttt{sum(List)} (see section \ref{datatypes:list}) as an anonymous \texttt{fun}. 579 | 580 | \begin{erlang} 581 | Sum1 = fun ([], _Foo) -> 0;([H|T], Foo) -> H + Foo(T, Foo) end. 582 | Sum = fun (List) -> Sum1(List, Sum1) end. 583 | Sum([1,2,3,4,5]) % 15 584 | \end{erlang} 585 | 586 | The definition of \texttt{Sum} is done in a way such that it takes \textit{itself} as a parameter, matched to \texttt{\_Foo} (empty list) or \texttt{Foo}, 587 | which it then calls recursively. The definition of \texttt{Sum} calls \texttt{Sum1}, also passing \texttt{Sum1} as a parameter. 588 | 589 | 590 | Names in \texttt{funs}: In Erlang you can use a name inside a \texttt{fun} before the name has been 591 | defined. The syntax of \texttt{funs with names} allows a variable name to be 592 | consistently present before each argument list. This allows \texttt{funs} to be 593 | recursive in one steps. This example shows how to define the function 594 | \texttt{sum(List)} (see section \ref{datatypes:list}) as a \texttt{funs with names}. 595 | 596 | \begin{erlang} 597 | Sum = fun Sum([])-> 0;Sum([H|T]) -> H + Sum(T) end. 598 | Sum([1,2,3,4,5]) % 15 599 | \end{erlang} 600 | 601 | 602 | \section{BIFs --- Built-in functions} 603 | \label{functions:bifs} 604 | The \textbf{built-in functions}, BIFs, are implemented in the C code of 605 | the runtime system and do things that are difficult or impossible to 606 | implement in Erlang. Most of the built-in functions belong to the 607 | module \texttt{erlang} but there are also built-in functions that belong 608 | to other modules like \texttt{lists} and \texttt{ets}. The most 609 | commonly used BIFs belonging to the module \texttt{erlang} are 610 | \textbf{auto-imported}, i.e.~they do not need to be prefixed with the 611 | module name. 612 | 613 | \begin{center} 614 | \begin{tabular}{|>{\raggedright}p{103pt}|>{\raggedright}p{217pt}|} 615 | \hline 616 | \multicolumn{2}{|p{321pt}|}{Some useful BIFs}\tabularnewline 617 | \hline 618 | \texttt{date()} & Returns today's date as \texttt{\{Year, Month, Day\}}\tabularnewline 619 | \hline 620 | \texttt{now()} & Returns current time in microseconds. System dependent\tabularnewline 621 | \hline 622 | \texttt{time()} & Returns current time as \texttt{\{Hour, Minute, Second\}} System dependent\tabularnewline 623 | \hline 624 | \texttt{halt()} & Stops the Erlang system\tabularnewline 625 | \hline 626 | \texttt{processes()} & Returns a list of all processes currently known to the system\tabularnewline 627 | \hline 628 | \texttt{process\_info(Pid)} & Returns a dictionary containing information about \texttt{Pid}\tabularnewline 629 | \hline 630 | \texttt{Module:module\_info()} & Returns a dictionary containing information about the code 631 | in Module\tabularnewline 632 | \hline 633 | \end{tabular} 634 | \end{center} 635 | 636 | A \textbf{dictionary} is a list of \texttt{\{Key, Value\} terms (see 637 | also section \ref{processes:dicts}).} 638 | 639 | \begin{erlang} 640 | size({a, b, c}) % 3 641 | atom_to_list('Erlang') % "Erlang" 642 | date() % {2013,5,27} 643 | time() % {01,27,42} 644 | \end{erlang} 645 | -------------------------------------------------------------------------------- /chapters/06-processes.tex: -------------------------------------------------------------------------------- 1 | \chapter{Processes} 2 | \label{processes} 3 | 4 | A \textbf{process} corresponds to one \textit{thread of control}. 5 | Erlang permits very large numbers of concurrent processes, 6 | each executing like it had an own virtual processor. When a process 7 | executing \texttt{functionA} calls another \texttt{functionB}, it 8 | will wait until \texttt{functionB} is finished and then retrieve its 9 | result. If instead it \textit{spawns} another process executing 10 | \texttt{functionB}, both will continue in parallel 11 | (concurrently). \texttt{functionA} will not wait for \texttt{functionB} 12 | and the only way they can communicate is through \textit{message passing}. 13 | 14 | Erlang processes are light-weight with a small memory footprint, fast to 15 | create and shut-down, and the scheduling overhead is low. A 16 | \textbf{process identifier}, \texttt{Pid}, identifies a process. The 17 | BIF \texttt{self/0} returns the \texttt{Pid} of the calling process. 18 | 19 | 20 | \section{Process creation} 21 | A process is created using the BIF \texttt{spawn/3}. 22 | 23 | \begin{erlang} 24 | spawn(Module, Func, [Expr1, ..., ExprN]) 25 | \end{erlang} 26 | 27 | \texttt{Module} should evaluate to a module name and \texttt{Func} to 28 | a function name in that module. The list \texttt{Expr1}$...$\texttt{ExprN} are the 29 | arguments to the function. \texttt{spawn} creates a new process and 30 | returns the process identifier, \texttt{Pid}. The new process starts 31 | by executing: 32 | 33 | \begin{erlang} 34 | Module:Func(Expr1, ..., ExprN) 35 | \end{erlang} 36 | 37 | The function \texttt{Func} has to be exported even if it is spawned by 38 | another function in the same module. There are other spawn BIFs, for 39 | example \texttt{spawn/4} for spawning a process on another node. 40 | 41 | 42 | \section{Registered processes} 43 | A process can be associated with a name. The name must be an atom and 44 | is automatically unregistered if the process terminates. Only static 45 | (cyclic) processes should be registered. 46 | 47 | \begin{center} 48 | \begin{tabular}{|>{\raggedright}p{117pt}|>{\raggedright}p{204pt}|} 49 | \hline 50 | \multicolumn{2}{|p{321pt}|}{Name registration BIFs}\tabularnewline 51 | \hline 52 | \texttt{register(Name, Pid)} & Associates the atom \texttt{Name} with the process \texttt{Pid}\tabularnewline 53 | \hline 54 | \texttt{registered()} & Returns a list of names which have been registered \tabularnewline 55 | \hline 56 | \texttt{whereis(Name)} & Returns the \texttt{Pid} registered under \texttt{Name} or \texttt{undefined} if the name 57 | is not registered\tabularnewline 58 | \hline 59 | \end{tabular} 60 | \end{center} 61 | 62 | 63 | \section{Process communication} 64 | Processes communicate by sending and receiving 65 | \textbf{messages}. Messages are sent using the send operator 66 | (\texttt{!}) and are received using \texttt{receive}. Message passing 67 | is asynchronous and reliable, i.e.~the message is guaranteed to 68 | eventually reach the recipient, provided that the recipient exists. 69 | 70 | \subsection{Send} 71 | \begin{erlang} 72 | Pid ! Expr 73 | \end{erlang} 74 | 75 | The send (\texttt{!}) operator sends the value of \texttt{Expr} as a 76 | message to the process specified by \texttt{Pid} where it will be 77 | placed last in its \textbf{message queue}. The value of \texttt{Expr} 78 | is also the return value of the (\texttt{!}) expression. \texttt{Pid} 79 | must evaluate to a process identifier, a registered name or a tuple 80 | \texttt{\{Name,Node\}}, where \texttt{Name} is a registered process at 81 | \texttt{Node} (see chapter \ref{distribution}). The message sending operator 82 | (\texttt{!}) never fails, even if it addresses a non-existent process. 83 | 84 | 85 | \subsection{Receive} 86 | 87 | \begin{erlang} 88 | receive 89 | Pattern1 [when GuardSeq1] -> 90 | Body1; 91 | ... 92 | PatternN [when GuardSeqN] -> 93 | BodyN % Note no semicolon (;) before end 94 | end 95 | \end{erlang} 96 | 97 | This expression receives messages sent to the process using the send 98 | operator (\texttt{!}). The patterns \texttt{PatternX} are sequentially 99 | matched against the first message in time order in the message queue, 100 | then the second and so on. If a match succeeds and the optional guard 101 | sequence \texttt{GuardSeqX} is true, then the message is removed from 102 | the message queue and the corresponding \texttt{BodyX} is 103 | evaluated. It is the order of the pattern clauses that decides the 104 | order in which messages will be received prior to the order in which 105 | they arrive. This is called \textit{selective receive}. The 106 | return value of \texttt{BodyX} is the return value of the receive 107 | expression. 108 | 109 | \texttt{receive} never fails. The process may be suspended, possibly 110 | indefinitely, until a message arrives that matches one of the patterns 111 | and with a true guard sequence. 112 | 113 | \newpage 114 | \begin{erlang} 115 | wait_for_onhook() -> 116 | receive 117 | onhook -> 118 | disconnect(), 119 | idle(); 120 | {connect, B} -> 121 | B ! {busy, self()}, 122 | wait_for_onhook() 123 | end. 124 | \end{erlang} 125 | 126 | 127 | \subsection{Receive with timeout} 128 | 129 | \begin{erlang} 130 | receive 131 | Pattern1 [when GuardSeq1] -> 132 | Body1; 133 | ...; 134 | PatternN [when GuardSeqN] -> 135 | BodyN 136 | after 137 | ExprT -> 138 | BodyT 139 | end 140 | \end{erlang} 141 | 142 | \texttt{ExprT} should evaluate to an integer between \texttt{0} and 143 | \texttt{16\#ffffffff} (the value must fit in 32 bits). If no matching 144 | message has arrived within \texttt{ExprT} milliseconds, then 145 | \texttt{BodyT} will be evaluated and its return value becomes the 146 | return value of the receive expression. 147 | 148 | \begin{erlang} 149 | wait_for_onhook() -> 150 | receive 151 | onhook -> 152 | disconnect(), 153 | idle(); 154 | {connect, B} -> 155 | B ! {busy, self()}, 156 | wait_for_onhook() 157 | after 158 | 60000 -> 159 | disconnect(), 160 | error() 161 | end. 162 | \end{erlang} 163 | 164 | A \texttt{receive...after} expression with no branches can be used to 165 | implement simple timeouts. 166 | 167 | \begin{erlang} 168 | receive 169 | after 170 | ExprT -> 171 | BodyT 172 | end 173 | \end{erlang} 174 | 175 | \begin{center} 176 | \begin{tabular}{|>{\raggedright}p{47pt}|>{\raggedright}p{273pt}|} 177 | \hline 178 | \multicolumn{2}{|p{321pt}|}{Two special cases for the timeout value \texttt{ExprT}}\tabularnewline 179 | \hline 180 | \texttt{infinity} & This is equivalent to not using a timeout and can be useful for timeout 181 | values that are calculated at run-time\tabularnewline 182 | \hline 183 | \texttt{0} & If there is no matching message in the mailbox, the timeout will occur immediately\tabularnewline 184 | \hline 185 | \end{tabular} 186 | \end{center} 187 | 188 | 189 | \section{Process termination} 190 | \label{processes:termination} 191 | A process always terminates with an \textbf{exit reason} which may be 192 | any term. If a process terminates normally, i.e.~it has run 193 | to the end of its code, then the reason is the atom \texttt{normal}. A process 194 | can terminate itself by calling one of the following BIFs. 195 | 196 | \begin{erlang} 197 | exit(Reason) 198 | 199 | erlang:error(Reason) 200 | 201 | erlang:error(Reason, Args) 202 | \end{erlang} 203 | 204 | A process terminates with the exit reason \texttt{\{Reason,Stack\}} when a 205 | run-time error occurs. 206 | 207 | A process may also be terminated if it receives an exit signal with 208 | a reason other than \texttt{normal} (see section \ref{processes:recvexitsignals}). 209 | 210 | 211 | \section{Process links} 212 | \label{processes:links} 213 | Two processes can be \textbf{linked} to each other. Links are 214 | bidirectional and there can only be one link between two distinct processes (unique \texttt{Pid}s). A 215 | process with \texttt{Pid1} can link to a process with \texttt{Pid2} 216 | using the BIF \texttt{link(Pid2)}. The BIF \texttt{spawn\_link(Module, Func, Args)} 217 | spawns and links a process in one atomic operation. 218 | 219 | A link can be removed using the BIF \texttt{unlink(Pid)}. 220 | 221 | 222 | \subsection{Error handling between processes} 223 | When a process terminates it will send \textbf{exit signals} to all 224 | processes that it is linked to. These in turn will also be terminated 225 | \textit{or handle the exit signal in some way}. This feature can be 226 | used to build hierarchical program structures where some processes are 227 | supervising other processes, for example restarting them if they 228 | terminate abnormally. 229 | 230 | 231 | \subsection{Sending exit signals} 232 | \label{processes:sendexitsignals} 233 | A process always terminates with an exit reason which is sent as an 234 | exit signal to all linked processes. The BIF \texttt{exit(Pid, Reason)} sends 235 | an exit signal with the reason \texttt{Reason} to \texttt{Pid}, without 236 | affecting the calling process. 237 | 238 | 239 | \subsection{Receiving exit signals} 240 | \label{processes:recvexitsignals} 241 | If a process receives an exit signal with an exit reason other than 242 | \texttt{normal} it will also be terminated, and will send exit signals with the 243 | same exit reason to its linked processes. An exit signal with reason 244 | \texttt{normal} is ignored. This behaviour can be changed using the BIF 245 | \texttt{process\_flag(trap\_exit, true)}. 246 | 247 | The process is then able to \textbf{trap exits}. This means that an 248 | exit signal will be transformed into a message \texttt{\{'EXIT', FromPid, Reason\}} which is 249 | put into the process's mailbox and can be handled by the process like a regular 250 | message using \texttt{receive}. 251 | 252 | However, a call to the BIF \texttt{exit(Pid, kill)} unconditionally 253 | terminates the process \texttt{Pid} regardless whether it is able to 254 | trap exit signals or not. 255 | 256 | 257 | \section{Monitors} 258 | A process \texttt{Pid1} can create a \textbf{monitor} for 259 | \texttt{Pid2} using the BIF: 260 | 261 | \begin{erlang} 262 | erlang:monitor(process, Pid2) 263 | \end{erlang} 264 | 265 | which returns a reference \texttt{Ref}. If \texttt{Pid2} terminates 266 | with exit reason \texttt{Reason}, a message as follows will be sent to 267 | \texttt{Pid1}: 268 | 269 | \begin{erlang} 270 | {'DOWN', Ref, process, Pid2, Reason} 271 | \end{erlang} 272 | 273 | If \texttt{Pid2} does not exist, the \texttt{'DOWN'} message is sent 274 | immediately with \texttt{Reason} set to \texttt{noproc}. Monitors are 275 | unidirectional in that if \texttt{Pid1} monitors \texttt{Pid2} then it 276 | will receive a message when \texttt{Pid2} dies but \texttt{Pid2} will 277 | \textbf{not} receive a message when \texttt{Pid1} dies. Repeated calls 278 | to \texttt{erlang:monitor(process, Pid)} will create several, 279 | independent monitors and each one will be sent a \texttt{'DOWN'} message 280 | when \texttt{Pid} terminates. 281 | 282 | A monitor can be removed by calling \texttt{erlang:demonitor(Ref)}. It 283 | is possible to create monitors for processes with registered names, 284 | also at other nodes. 285 | 286 | 287 | \section{Process priorities} 288 | The BIF \texttt{process\_flag(priority, Prio)} defines the priority of 289 | the current process. \texttt{Prio} may have the value \texttt{normal}, 290 | which is the default, \texttt{low}, \texttt{high} or \texttt{max}. 291 | 292 | Modifying a process's priority is discouraged and should only be done in 293 | special circumstances. A problem that requires changing process priorities 294 | can generally be solved by another approach. 295 | 296 | 297 | \section{Process dictionary} 298 | \label{processes:dicts} 299 | Each process has its own process dictionary which is a list of 300 | \texttt{\{Key, Value\}} terms. 301 | 302 | \begin{center} 303 | \begin{tabular}{|>{\raggedright}p{79pt}|>{\raggedright}p{247pt}|} 304 | \hline 305 | \multicolumn{2}{|p{326pt}|}{Process dictionary BIFs}\tabularnewline 306 | \hline 307 | \texttt{put(Key, Value)} & Saves the \texttt{Value} under the \texttt{Key} or replaces an older value\tabularnewline 308 | \hline 309 | \texttt{get(Key)} & Retrieves the value stored under \texttt{Key} or \texttt{undefined}\tabularnewline 310 | \hline 311 | \texttt{get()} & Returns the entire process dictionary as a list of \texttt{\{Key, Value\}} terms\tabularnewline 312 | \hline 313 | \texttt{get\_keys(Value)} & Returns a list of keys that have the value \texttt{Value}\tabularnewline 314 | \hline 315 | \texttt{erase(Key)} & Deletes \texttt{\{Key, Value\}}, if any, and returns \texttt{Key}\tabularnewline 316 | \hline 317 | \texttt{erase()} & Returns the entire process dictionary and deletes it\tabularnewline 318 | \hline 319 | \end{tabular} 320 | \end{center} 321 | 322 | Process dictionaries could be used to keep global variables within an application, 323 | but the extensive use of them for this is usually regarded as poor programming style. 324 | 325 | -------------------------------------------------------------------------------- /chapters/07-error-handling.tex: -------------------------------------------------------------------------------- 1 | \chapter{Error handling} 2 | \label{errorhandling} 3 | 4 | This chapter deals with error handling within a process. Such errors 5 | are known as \textbf{exceptions}. 6 | 7 | 8 | \section{Exception classes and error reasons} 9 | 10 | \begin{center} 11 | \begin{tabular}{|>{\raggedright}p{49pt}|>{\raggedright}p{277pt}|} 12 | \hline 13 | \multicolumn{2}{|p{326pt}|}{Exception classes}\tabularnewline 14 | \hline 15 | \texttt{error} & Run-time error for example when applying an operator to the wrong types of arguments. Run-time errors can be raised by calling 16 | the BIFs \texttt{erlang:error(Reason)} or \texttt{erlang:error(Reason, Args)} \tabularnewline 17 | \hline 18 | \texttt{exit} & The process calls \texttt{exit(Reason)}, see section \ref{processes:termination}\tabularnewline 19 | \hline 20 | \texttt{throw} & The process calls \texttt{throw(Expr)}, see section \ref{errorhandling:catchthrow}\tabularnewline 21 | \hline 22 | \end{tabular} 23 | \end{center} 24 | 25 | An exception will cause the process to crash, i.e. its execution is 26 | stopped and it is removed from the system. It is also said to 27 | \textit{terminate}. Then exit signals will be sent to any linked 28 | processes.\textit{ }An exception consists of its class, an exit reason 29 | and a stack. The stack trace can be retrieved using the BIF 30 | \texttt{erlang:get\_stacktrace/0}. 31 | 32 | Run-time errors and other exceptions can be prevented from causing the 33 | process to terminate by using the expressions \texttt{try} and \texttt{catch}. 34 | 35 | For exceptions of class \texttt{error}, for example normal run-time errors, the 36 | \textbf{exit reason} is a tuple \texttt{\{Reason, Stack\}} where 37 | \texttt{Reason} is a term indicating which type of error. 38 | 39 | \begin{center} 40 | \begin{tabular}{|>{\raggedright}p{100pt}|>{\raggedright}p{226pt}|} 41 | \hline 42 | \multicolumn{2}{|p{326pt}|}{Exit reasons}\tabularnewline 43 | \hline 44 | \texttt{badarg} & Argument is of wrong type. \tabularnewline 45 | \hline 46 | \texttt{badarith} & Argument is of wrong type in an arithmetic expression. \tabularnewline 47 | \hline 48 | \texttt{\{badmatch, Value\}} & Evaluation of a match expression failed. \texttt{Value} did not match. 49 | \tabularnewline 50 | \hline 51 | \texttt{function\_clause} & No matching function clause is found when evaluating a function 52 | call. \tabularnewline 53 | \hline 54 | \texttt{\{case\_clause, Value\}} & No matching branch is found when evaluating a case expression. 55 | \texttt{Value} did not match. \tabularnewline 56 | \hline 57 | \texttt{if\_clause} & No true branch is found when evaluating an \texttt{if} expression. \tabularnewline 58 | \hline 59 | \texttt{\{try\_clause, Value\}} & No matching branch is found when evaluating the of section 60 | of a \texttt{try} expression. \texttt{Value} did not match. \tabularnewline 61 | \hline 62 | \texttt{undef} & The function cannot be found when evaluating a function call\tabularnewline 63 | \hline 64 | \texttt{\{badfun, Fun\}} & There is something wrong with \texttt{Fun}\tabularnewline 65 | \hline 66 | \texttt{\{badarity, Fun\}} & A fun is applied to the wrong number of arguments. \texttt{Fun} describes 67 | it and the arguments\tabularnewline 68 | \hline 69 | \texttt{timeout\_value} & The timeout value in a \texttt{receive}$...$\texttt{after} expression is evaluated 70 | to something else than an integer or infinity\tabularnewline 71 | \hline 72 | \texttt{noproc} & Trying to link to a non-existant process\tabularnewline 73 | \hline 74 | \texttt{\{nocatch, Value\}} & Trying to evaluate a \texttt{throw} outside of a \texttt{catch}. \texttt{Value} is the thrown 75 | term\tabularnewline 76 | \hline 77 | \texttt{system\_limit} & A system limit has been reached\tabularnewline 78 | \hline 79 | \end{tabular} 80 | \end{center} 81 | 82 | \texttt{Stack} is the stack of function calls being evaluated when the error 83 | occurred, given as a list of tuples \texttt{\{Module, Name, Arity\}} 84 | with the most recent function call first. The most recent function 85 | call tuple may in some cases be \texttt{\{Module, Name, Args\}}. 86 | 87 | 88 | \section{Catch and throw} 89 | \label{errorhandling:catchthrow} 90 | \begin{erlang} 91 | catch Expr 92 | \end{erlang} 93 | 94 | This returns the value of \texttt{Expr} unless an exception occurs 95 | during its evaluation. Then the return value will be a tuple 96 | containing information about the exception. 97 | 98 | \begin{erlang} 99 | {'EXIT', {Reason, Stack}} 100 | \end{erlang} 101 | 102 | Then the exception is \textit{caught}. Otherwise it would terminate 103 | the process. If the exception is caused by a function call 104 | \texttt{exit(Term)} the tuple \texttt{\{'EXIT',Term\}} is returned. If 105 | the exception is caused by calling \texttt{throw(Term)} then 106 | \texttt{Term} will be returned. 107 | 108 | \texttt{catch 1+2} \resultingin \texttt{3}\\ 109 | \texttt{catch 1+a } \resultingin \texttt{\{'EXIT',\{badarith,[...]\}\}} 110 | 111 | \texttt{catch} has low precedence and catch subexpressions often need 112 | to be enclosed in a block expression or in parentheses. 113 | 114 | \texttt{A = (catch 1+2)} \resultingin \texttt{3} 115 | 116 | The BIF \texttt{throw(Expr)} is used for \textit{non-local} return 117 | from a function. It must be evaluated within a \texttt{catch}, which returns 118 | the result from evaluating \texttt{Expr}. 119 | 120 | \texttt{catch begin 1,2,3,throw(four),5,6 end} \resultingin \texttt{four} 121 | 122 | If \texttt{throw/1} is not evaluated within a \texttt{catch}, a 123 | \texttt{nocatch} run-time error will occur. 124 | 125 | A \texttt{catch} will not prevent a process from terminating due to an exit 126 | signal from another linked process (unless it has been set to trap 127 | exits). 128 | 129 | 130 | \section{Try} 131 | \label{errorhandling:try} 132 | The \texttt{try} expression is able to distinguish between different exception 133 | classes. The following example emulates the behaviour of \texttt{catch Expr}: 134 | 135 | \begin{erlang} 136 | try Expr 137 | catch 138 | throw:Term -> Term; 139 | exit:Reason -> {'EXIT', Reason}; 140 | error:Reason -> {'EXIT',{Reason, erlang:get_stacktrace()}} 141 | end 142 | \end{erlang} 143 | 144 | The full description of \texttt{try} is as follows: 145 | 146 | \begin{erlang} 147 | try Expr [of 148 | Pattern1 [when GuardSeq1] -> Body1; 149 | ...; 150 | PatternN [when GuardSeqN] -> BodyN] 151 | [catch 152 | [Class1:]ExceptionPattern1 [when ExceptionGuardSeq1] -> ExceptionBody1; 153 | ...; 154 | [ClassN:]ExceptionPatternN [when ExceptionGuardSeqN] -> ExceptionBodyN] 155 | [after AfterBody] 156 | end 157 | \end{erlang} 158 | 159 | There has to be at least one \texttt{catch} or an \texttt{after} 160 | clause. There may be an \texttt{of} clause following the \texttt{Expr} 161 | which adds a \texttt{case} expression on the value of \texttt{Expr}. 162 | 163 | \texttt{try} returns the value of \texttt{Expr} unless an exception 164 | occurs during its evaluation. Then the exception is \textit{caught} 165 | and the patterns \texttt{ExceptionPattern} with the right exception 166 | \texttt{Class} are sequentially matched against the caught exception. An 167 | omitted \texttt{Class} is shorthand for \texttt{throw}. If a match succeeds and the 168 | optional guard sequence \texttt{ExceptionGuardSeq} is true, the 169 | corresponding \texttt{ExceptionBody} is evaluated and becomes the return 170 | value. 171 | 172 | If there is no matching \texttt{ExceptionPattern} of the right \texttt{Class} 173 | with a true guard sequence, the exception is passed on as if 174 | \texttt{Expr} had not been enclosed in a \texttt{try} expression. An exception 175 | occurring during the evaluation of an \texttt{ExceptionBody} it is not 176 | caught. 177 | 178 | If none of the of \texttt{Patterns} match, a \texttt{try\_clause} run-time 179 | error will occur. 180 | 181 | If defined then \texttt{AfterBody} is always evaluated \textbf{last} 182 | irrespective of whether and error occurred or not. Its return value is 183 | ignored and the return value of the \texttt{try} is the same as 184 | without an \texttt{after} section. \texttt{AfterBody} is evaluated 185 | even if an exception occurs in \texttt{Body} or 186 | \texttt{ExceptionBody}, in which case the exception is passed on. 187 | 188 | %% The \texttt{AfterBody} is evaluated after either \texttt{Body} or 189 | %% \texttt{ExceptionBody} no matter which one. The evaluated value of the 190 | %% \texttt{AfterBody} is lost; the return value of the try expression is 191 | %% the same with an after section as without. Even if an exception occurs 192 | %% during evaluation of \texttt{Body} or \texttt{ExceptionBody}, the 193 | %% \texttt{AfterBody} is evaluated. In this case the exception is caught 194 | %% and passed on after the \texttt{AfterBody} has been evaluated, so the 195 | %% exception from the try expression is the same with an after section as 196 | %% without. 197 | 198 | An exception that occurs during the evaluation of \texttt{AfterBody} 199 | itself is not caught, so if the \texttt{AfterBody} is evaluated due to 200 | an exception in \texttt{Expr}, \texttt{Body} or 201 | \texttt{ExceptionBody}, that exception is lost and masked by the new 202 | exception. 203 | 204 | -------------------------------------------------------------------------------- /chapters/08-distributed-erlang.tex: -------------------------------------------------------------------------------- 1 | \chapter{Distributed Erlang} 2 | \label{distribution} 3 | 4 | A \textbf{distributed Erlang system} consists of a number of Erlang 5 | runtime systems communicating with each other. Each such runtime 6 | system is called a \textbf{node}. Nodes can reside on the same 7 | host or on different hosts connected through a network. The 8 | standard distribution mechanism is implemented using TCP/IP sockets 9 | but other mechanisms can also be implemented. 10 | 11 | Message passing between processes on different nodes, as well as links 12 | and monitors, is transparent when using \texttt{Pid}s. However, registered 13 | names are local to each node. A registered process at a particular 14 | node is referred to as \texttt{\{Name,Node\}}. 15 | 16 | The Erlang Port Mapper Daemon \textbf{epmd} is automatically started 17 | on every host where an Erlang node is started. It is responsible for 18 | mapping the symbolic node names to machine addresses. 19 | 20 | 21 | \section{Nodes} 22 | A \textbf{node} is an executing Erlang runtime system which has been 23 | given a name, using the command line flag \texttt{-name} (long name) 24 | or \texttt{-sname} (short name). 25 | 26 | The format of the node name is an atom \texttt{Name@Host} where 27 | \texttt{Name} is the name given by the user and \texttt{Host} is the 28 | full host name if long names are used, or the first part of the host 29 | name if short names are used. \texttt{node()} returns the name of the 30 | node. Nodes using long names cannot communicate with nodes using 31 | short names. 32 | 33 | 34 | \section{Node connections} 35 | The nodes in a distributed Erlang system are fully connected. The 36 | first time the name of another node is used, a connection attempt to 37 | that node will be made. If a node A connects to node B, and node B has 38 | a connection to node C, then node A will also try to connect to node 39 | C. This feature can be turned off using the command line flag: 40 | 41 | \texttt{~~~~-connect\_all false} 42 | 43 | If a node goes down, all connections to that node are removed. The 44 | BIF: 45 | 46 | \begin{erlang} 47 | erlang:disconnect(Node) 48 | \end{erlang} 49 | 50 | disconnects \texttt{Node}. The BIF \texttt{nodes()} returns the list of 51 | currently connected (visible) nodes. 52 | 53 | 54 | \section{Hidden nodes} 55 | It is sometimes useful to connect to a node without also connecting to 56 | all other nodes. For this purpose, a \textbf{hidden node} may be 57 | used. A hidden node is a node started with the command line flag 58 | \texttt{-hidden}. Connections between hidden nodes and other nodes must be set 59 | up explicitly. Hidden nodes do not show up in the list of nodes 60 | returned by \texttt{nodes()}. Instead, \texttt{nodes(hidden)} or \texttt{nodes(connected)} must 61 | be used. A hidden node will not be included in the set of nodes that 62 | the module global keeps track of. 63 | 64 | A \textbf{C node} is a C program written to act as a hidden node in a 65 | distributed Erlang system. The library \texttt{erl\_interface} 66 | contains functions for this purpose. 67 | 68 | 69 | \section{Cookies} 70 | Each node has its own \textbf{magic cookie}, which is an atom. The 71 | Erlang network authentication server (auth) reads the cookie in the 72 | file \texttt{\$HOME/.erlang.cookie}. If the file does not exist, it 73 | will be created with a random string as content. 74 | 75 | % FRMB CHECK: the implication here is that "erlang:set_cookie(node(), Cookie)" 76 | % sets *this* node's cookie, as well as the cookie that will be used to connect 77 | % to other nodes, if not explicitly set otherwise. 78 | 79 | The permissions of the file must be set to octal 400 (read-only 80 | by user). The cookie of the local node may also be set using the BIF 81 | \texttt{erlang:set\_cookie(node(), Cookie)}. 82 | 83 | The current node is only allowed to communicate with another node 84 | \texttt{Node2} if it knows its cookie. If this is different from the current node (whose cookie will 85 | be used by default) it must be explicitly set with the BIF \texttt{erlang:set\_cookie(Node2, Cookie2)}. 86 | 87 | 88 | \section{Distribution BIFs} 89 | 90 | \begin{center} 91 | \begin{tabular}{|>{\raggedright}p{156pt}|>{\raggedright}p{170pt}|} 92 | \hline 93 | \multicolumn{2}{|p{326pt}|}{Distribution BIFs}\tabularnewline 94 | \hline 95 | \texttt{node()} & Returns the name of the current node. Allowed in guards\tabularnewline 96 | \hline 97 | \texttt{is\_alive()} & Returns true if the runtime system is a node and can connect to 98 | other nodes, false otherwise\tabularnewline 99 | \hline 100 | \texttt{erlang:get\_cookie()} & Returns the magic cookie of the current node\tabularnewline 101 | \hline 102 | \texttt{set\_cookie(Node, Cookie)} & Sets the magic cookie used when connecting to \texttt{Node}. 103 | If \texttt{Node} is the current node, \texttt{Cookie} will be used when connecting to all new nodes\tabularnewline 104 | \hline 105 | \texttt{nodes()} & Returns a list of all visible nodes to which the current node is connected 106 | to\tabularnewline 107 | \hline 108 | \texttt{nodes(connected\textbar{}hidden)} & Returns a list not only of visible nodes, 109 | but also hidden nodes and previously known nodes, etc. \tabularnewline 110 | \hline 111 | \texttt{monitor\_node(Node,}\break\texttt{\phantom{xxxx}true\textbar{}false)} & Monitors the status of \texttt{Node}. A message 112 | \texttt{\{nodedown, Node\}} is received if the connection to it is lost\tabularnewline 113 | \hline 114 | \texttt{node(Pid\textbar{}Ref\textbar{}Port)} & Returns the node where the argument is 115 | located\tabularnewline 116 | \hline 117 | \texttt{erlang:disconnect\_node(Node)} & Forces the disconnection of \texttt{Node}\tabularnewline 118 | \hline 119 | \texttt{spawn[\_link\textbar{}\_opt](Node,}\break\texttt{\phantom{xxxx}Module, Function, Args)} & Creates a process 120 | at a remote node\tabularnewline 121 | \hline 122 | \texttt{spawn[\_link\textbar{}\_opt](Node, Fun)} & Creates a process at a remote node\tabularnewline 123 | \hline 124 | \end{tabular} 125 | \end{center} 126 | 127 | 128 | \section{Distribution command line flags} 129 | 130 | \begin{center} 131 | \begin{tabular}{|>{\raggedright}p{102pt}|>{\raggedright}p{224pt}|} 132 | \hline 133 | \multicolumn{2}{|p{326pt}|}{Distribution command line flags}\tabularnewline 134 | \hline 135 | \texttt{-connect\_all false} & Only explicit connection set-ups will be used\tabularnewline 136 | \hline 137 | \texttt{-hidden} & Makes a node into a hidden node\tabularnewline 138 | \hline 139 | \texttt{-name Name} & Makes a runtime system into a node, using long node names\tabularnewline 140 | \hline 141 | \texttt{-setcookie Cookie} & Same as calling \linebreak{} 142 | \texttt{erlang:set\_cookie(node(), Cookie))}\tabularnewline 143 | \hline 144 | \texttt{-sname Name} & Makes a runtime system into a node, using short node names\tabularnewline 145 | \hline 146 | \end{tabular} 147 | \end{center} 148 | 149 | 150 | \section{Distribution modules} 151 | There are several modules available which are useful for distributed programming: 152 | 153 | \begin{center} 154 | \begin{tabular}{|>{\raggedright}p{93pt}|>{\raggedright}p{233pt}|} 155 | \hline 156 | \multicolumn{2}{|p{326pt}|}{Kernel modules useful for distribution}\tabularnewline 157 | \hline 158 | \texttt{global} & A global name registration facility\tabularnewline 159 | \hline 160 | \texttt{global\_group} & Grouping nodes to global name registration groups\tabularnewline 161 | \hline 162 | \texttt{net\_adm} & Various net administration routines\tabularnewline 163 | \hline 164 | \texttt{net\_kernel} & Erlang networking kernel\tabularnewline 165 | \hline 166 | \multicolumn{2}{|p{326pt}|}{STDLIB modules useful for distribution}\tabularnewline 167 | \hline 168 | \texttt{slave} & Start and control of slave nodes\tabularnewline 169 | \hline 170 | \end{tabular} 171 | \end{center} 172 | -------------------------------------------------------------------------------- /chapters/09-ports-and-port-drivers.tex: -------------------------------------------------------------------------------- 1 | \chapter{Ports and Port Drivers} 2 | \label{ports} 3 | \textbf{Ports} provide a byte-oriented interface to external programs 4 | and communicate with Erlang processes by sending and receiving lists 5 | of bytes as messages. The Erlang process that creates a port is called 6 | the \textbf{port owner} or the \textbf{connected process} of the 7 | port. All communication to and from the port should go via the port 8 | owner. If the port owner terminates, so will the port (and the 9 | external program, if it has been programmed correctly). 10 | 11 | The external program forms another OS process. By default, it should 12 | read from standard input (file descriptor 0) and write to standard 13 | output (file descriptor 1). The external program should terminate when 14 | the port is closed. 15 | 16 | 17 | \section{Port Drivers} 18 | Drivers are normally programmed in C and are dynamically linked to the 19 | Erlang runtime system. The linked-in driver behaves like a port and is 20 | called a \textbf{port driver}. However, an erroneous port driver might 21 | cause the entire Erlang runtime system to leak memory, hang or crash. 22 | 23 | 24 | \section{Port BIFs} 25 | 26 | \begin{center} 27 | \begin{tabular}{|>{\raggedright}p{161pt}|>{\raggedright}p{165pt}|} 28 | \hline 29 | \multicolumn{2}{|p{326pt}|}{Port creation BIF}\tabularnewline 30 | \hline 31 | \texttt{open\_port(PortName, PortSettings)} & Returns a \textbf{port identifier} \texttt{Port} as the result of opening a new Erlang port. Messages can be sent to and received from a port identifier, just like a Pid. Port identifiers can also be linked to or registered under a name using \texttt{link/1} and \texttt{register/2}. \tabularnewline 32 | \hline 33 | \end{tabular} 34 | \end{center} 35 | 36 | \texttt{PortName} is usually a tuple \texttt{\{spawn,Command\}} where 37 | the string \texttt{Command} is the name of the external program. The 38 | external program runs outside the Erlang workspace unless a port 39 | driver with the name \texttt{Command} is found. If the driver is 40 | found, it will be started. 41 | 42 | \texttt{PortSettings} is a list of settings (options) for the 43 | port. The list typically contains at least a tuple 44 | \texttt{\{packet,N\}} which specifies that data sent between the port 45 | and the external program are preceded by an N-byte length 46 | indicator. Valid values for \texttt{N} are 1, 2 or 4. If binaries 47 | should be used instead of lists of bytes, the option \texttt{binary} 48 | must be included. 49 | 50 | The port owner Pid communicates with Port by sending and receiving 51 | messages. (Any process could send the messages to the port, but 52 | messages from the port will always be sent to the port owner). 53 | 54 | \begin{center} 55 | \begin{tabular}{|>{\raggedright}p{115pt}|>{\raggedright}p{211pt}|} 56 | \hline 57 | \multicolumn{2}{|p{326pt}|}{Messages sent to a port}\tabularnewline 58 | \hline 59 | \texttt{\{Pid, \{command, Data\}\}} & Sends Data to the port. \tabularnewline 60 | \hline 61 | \texttt{\{Pid, close\}} & Closes the port. Unless the port is already closed, the port replies 62 | with \texttt{\{Port, closed\}} when all buffers have been flushed and the port really closes. 63 | \tabularnewline 64 | \hline 65 | \texttt{\{Pid,\{connect,NewPid\}\}} & Sets the port owner of \texttt{Port} to \texttt{NewPid}. Unless the port is already closed, the port replies with \texttt{\{Port, connected\}} to the old port owner. Note that the old port owner is still linked to the port, but the new port 66 | owner is not. \tabularnewline 67 | \hline 68 | \end{tabular} 69 | \end{center} 70 | 71 | Data must be an I/O list. An I/O list is a binary or a (possibly deep) 72 | list of binaries or integers in the range 0..255. 73 | 74 | \begin{center} 75 | \begin{tabular}{|>{\raggedright}p{121pt}|>{\raggedright}p{204pt}|} 76 | \hline 77 | \multicolumn{2}{|p{326pt}|}{Messages received from a port}\tabularnewline 78 | \hline 79 | \texttt{\{Port, \{data, Data\}\}} & Data is received from the external program\tabularnewline 80 | \hline 81 | \texttt{\{Port, closed\}} & Reply to \texttt{Port ! \{Pid,close\}}\tabularnewline 82 | \hline 83 | \texttt{\{Port, connected\}} & Reply to \texttt{Port ! \{Pid,\{connect, NewPid\}\}} \tabularnewline 84 | \hline 85 | \texttt{\{'EXIT', Port, Reason\}} & If Port has terminated for some reason. \tabularnewline 86 | \hline 87 | \end{tabular} 88 | \end{center} 89 | 90 | Instead of sending and receiving messages, there are also a number of 91 | BIFs that can be used. These can be called by any process, not only 92 | the port owner. 93 | 94 | \begin{center} 95 | \begin{tabular}{|>{\raggedright}p{146pt}|>{\raggedright}p{180pt}|} 96 | \hline 97 | \multicolumn{2}{|p{326pt}|}{Port BIFs}\tabularnewline 98 | \hline 99 | \texttt{port\_command(Port, Data)} & Sends Data to Port\tabularnewline 100 | \hline 101 | \texttt{port\_close(Port)} & Closes Port\tabularnewline 102 | \hline 103 | \texttt{port\_connect(Port, NewPid)} & Sets the port owner of \texttt{Port} to \texttt{NewPid}. The old port owner Pid stays linked to the port and has to call \texttt{unlink(Port)} if this is not desired. \tabularnewline 104 | \hline 105 | \texttt{erlang:port\_info(Port, Item)} & Returns information as specified by \texttt{Item}\tabularnewline 106 | \hline 107 | \texttt{erlang:ports()} & Returns a list of all ports on the current node\tabularnewline 108 | \hline 109 | \end{tabular} 110 | \end{center} 111 | 112 | There are some additional BIFs that only apply to port drivers: 113 | \texttt{port\_control/3} and \texttt{erlang:port\_call/3}. -------------------------------------------------------------------------------- /chapters/10-code-loading.tex: -------------------------------------------------------------------------------- 1 | \chapter{Code loading} 2 | \label{code} 3 | 4 | Erlang supports code updating in a running system. Code replacement is 5 | performed at module level. 6 | 7 | The code of a module can exist in two versions in a system: 8 | \textbf{current} and \textbf{old}. When a module is 9 | loaded into the system for the first time, the code becomes 10 | \textit{current}. If a new instance of the module is loaded, the code 11 | of the previous instance becomes \textit{old} and the new instance 12 | becomes \textit{current}. Normally a module is automatically loaded 13 | the first time a function in it is called. If the module is already 14 | loaded then it must explicitly be loaded again to a new version. 15 | 16 | Both old and current code are valid, and may be used 17 | concurrently. Fully qualified function calls will always refer to the 18 | current code. However, the old code may still be run by other 19 | processes. 20 | 21 | If a third instance of the module is loaded, the code server will 22 | remove (\textit{purge}) the old code and any processes lingering in it 23 | are terminated. Then the third instance becomes \textit{current} and 24 | the previously current code becomes \textit{old}. 25 | 26 | To change from old code to current code, a process must make a fully 27 | qualified function call. 28 | 29 | \begin{erlang} 30 | -module(mod). 31 | -export([loop/0]). 32 | 33 | loop() -> 34 | receive 35 | code_switch -> 36 | mod:loop(); 37 | Msg -> 38 | ... 39 | loop() 40 | end. 41 | \end{erlang} 42 | 43 | To make the process change code, send the message 44 | \texttt{code\_switch} to it. The process then will make a fully 45 | qualified call to \texttt{mod:loop()} and change to the current 46 | code. Note that \texttt{mod:loop/0} must be exported. -------------------------------------------------------------------------------- /chapters/11-macros.tex: -------------------------------------------------------------------------------- 1 | \chapter{Macros} 2 | \label{macros} 3 | 4 | \section{Defining and using macros} 5 | 6 | \begin{erlang} 7 | -define(Const, Replacement). 8 | -define(Func(Var1, ..., VarN), Replacement). 9 | \end{erlang} 10 | 11 | A \textbf{macro} must be defined before it is used but a macro 12 | definition may be placed anywhere among the attributes and function 13 | declarations of a module. If a macro is used in several modules it is 14 | advisable to put the macro definition in an include file. A macro is 15 | used as follows: 16 | 17 | \begin{erlang} 18 | ?Const 19 | ?Func(Arg1,...,ArgN) 20 | \end{erlang} 21 | 22 | Macros are expanded during compilation. A macro reference 23 | \texttt{?Const} is replaced by \texttt{Replacement} like this: 24 | 25 | \begin{erlang} 26 | -define(TIMEOUT, 200). 27 | ... 28 | call(Request) -> 29 | server:call(refserver, Request, ?TIMEOUT). 30 | \end{erlang} 31 | 32 | is expanded to: 33 | 34 | \begin{erlang} 35 | call(Request) -> 36 | server:call(refserver, Request, 200). 37 | \end{erlang} 38 | 39 | A macro reference \texttt{?Func(Arg1, ..., ArgN)} will be replaced by 40 | \texttt{Replacement}, where all occurrences of a variable \texttt{VarX} 41 | from the macro definition are replaced by the corresponding argument 42 | \texttt{ArgX}. 43 | 44 | \begin{erlang} 45 | -define(MACRO1(X, Y), {a, X, b, Y}). 46 | ... 47 | bar(X) -> 48 | ?MACRO1(a, b), 49 | ?MACRO1(X, 123). 50 | \end{erlang} 51 | 52 | will be expanded to: 53 | 54 | \begin{erlang} 55 | bar(X) -> 56 | {a, a, b, b}, 57 | {a, X, b, 123}. 58 | \end{erlang} 59 | 60 | To view the result of macro expansion, a module can be compiled with 61 | the \texttt{`P'} option: 62 | 63 | \begin{erlang} 64 | compile:file(File, ['P']). 65 | \end{erlang} 66 | 67 | This produces a listing of the parsed code after preprocessing and 68 | parse transforms, in the file \texttt{File.P}. 69 | 70 | 71 | \section{Predefined macros} 72 | 73 | \begin{center} 74 | \begin{tabular}{|>{\raggedright}p{103pt}|>{\raggedright}p{223pt}|} 75 | \hline 76 | \multicolumn{2}{|p{326pt}|}{P{\large{}redefined} macros}\tabularnewline 77 | \hline 78 | \texttt{?MODULE} & The name of the current module\tabularnewline 79 | \hline 80 | \texttt{?MODULE\_STRING} & The name of the current module, as a string\tabularnewline 81 | \hline 82 | \texttt{?FILE} & The file name of the current module\tabularnewline 83 | \hline 84 | \texttt{?LINE} & The current line number\tabularnewline 85 | \hline 86 | \texttt{?MACHINE} & The machine name, 'BEAM'\tabularnewline 87 | \hline 88 | \end{tabular} 89 | \end{center} 90 | 91 | 92 | \section{Flow Control in Macros} 93 | 94 | \begin{erlang} 95 | -undef(Macro). % This inhibits the macro definition. 96 | 97 | -ifdef(Macro). 98 | %% Lines that are evaluated if Macro was defined 99 | -else. 100 | %% If the condition was false, these lines are evaluated instead. 101 | -endif. 102 | \end{erlang} 103 | 104 | \texttt{ifndef(Macro)} can be used instead of \texttt{ifdef} and means 105 | the opposite. 106 | 107 | \begin{erlang} 108 | -ifdef(debug). 109 | -define(LOG(X), io:format("{~p,~p}:~p~n",[?MODULE,?LINE,X])). 110 | -else. 111 | -define(LOG(X), true). 112 | -endif. 113 | \end{erlang} 114 | 115 | If \texttt{debug} is defined when the module is compiled, 116 | \texttt{?LOG(Arg)} will expand to a call to \texttt{io:format/2} and 117 | provide the user with some simple trace output. 118 | 119 | 120 | \section{Stringifying Macro Arguments} 121 | \texttt{??Arg}, where \texttt{Arg} is a macro argument expands to the 122 | argument in the form of a string. 123 | 124 | \begin{erlang} 125 | -define(TESTCALL(Call), io:format("Call ~s: ~w~n", [??Call, Call])). 126 | 127 | ?TESTCALL(myfunction(1,2)), 128 | ?TESTCALL(you:function(2,1)), 129 | \end{erlang} 130 | 131 | results in: 132 | 133 | \begin{erlang} 134 | io:format("Call ~s: ~w~n", ["myfunction(1,2)", m:myfunction(1,2)]), 135 | io:format("Call ~s: ~w~n", ["you:function(2,1)", you:function(2,1)]), 136 | \end{erlang} 137 | 138 | That is, a trace output with both the function called and the 139 | resulting value. 140 | -------------------------------------------------------------------------------- /chapters/12-further-reading.tex: -------------------------------------------------------------------------------- 1 | \chapter{Further Reading and Resources} 2 | 3 | Following websites provide in-depth explanation of topics and concepts briefly covered in this document: 4 | 5 | \begin{itemize} 6 | \item Official Erlang documentation: \url{http://www.erlang.org/doc/} 7 | \item Learn You Some Erlang for Great Good: \url{http://learnyousomeerlang.com/} 8 | \item Tutorials section at Erlang Central: \url{https://erlangcentral.org/wiki/index.php?title=Category:HowTo} 9 | \end{itemize} 10 | 11 | Still have questions? erlang-questions mailing list (\url{http://erlang.org/mailman/listinfo/erlang-questions}) is a good place for general discussions about Erlang/OTP, the language, implementation, usage and beginners questions. 12 | -------------------------------------------------------------------------------- /fonts/FiraMono-Bold.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/esl/erlang-handbook/0bf26c122846f89bedca9ca88b0d4e94e6648f4d/fonts/FiraMono-Bold.ttf -------------------------------------------------------------------------------- /fonts/FiraMono-Regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/esl/erlang-handbook/0bf26c122846f89bedca9ca88b0d4e94e6648f4d/fonts/FiraMono-Regular.ttf -------------------------------------------------------------------------------- /fonts/PTF55F.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/esl/erlang-handbook/0bf26c122846f89bedca9ca88b0d4e94e6648f4d/fonts/PTF55F.ttf -------------------------------------------------------------------------------- /fonts/PTF56F.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/esl/erlang-handbook/0bf26c122846f89bedca9ca88b0d4e94e6648f4d/fonts/PTF56F.ttf -------------------------------------------------------------------------------- /fonts/PTF75F.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/esl/erlang-handbook/0bf26c122846f89bedca9ca88b0d4e94e6648f4d/fonts/PTF75F.ttf -------------------------------------------------------------------------------- /fonts/PTF76F.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/esl/erlang-handbook/0bf26c122846f89bedca9ca88b0d4e94e6648f4d/fonts/PTF76F.ttf -------------------------------------------------------------------------------- /includes/cc-by-sa.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/esl/erlang-handbook/0bf26c122846f89bedca9ca88b0d4e94e6648f4d/includes/cc-by-sa.png -------------------------------------------------------------------------------- /includes/erlang-logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/esl/erlang-handbook/0bf26c122846f89bedca9ca88b0d4e94e6648f4d/includes/erlang-logo.png -------------------------------------------------------------------------------- /output/ErlangHandbook-RU.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/esl/erlang-handbook/0bf26c122846f89bedca9ca88b0d4e94e6648f4d/output/ErlangHandbook-RU.pdf -------------------------------------------------------------------------------- /output/ErlangHandbook.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/esl/erlang-handbook/0bf26c122846f89bedca9ca88b0d4e94e6648f4d/output/ErlangHandbook.pdf --------------------------------------------------------------------------------