├── .gitignore ├── .gitmodules ├── Makefile ├── README.md ├── codes ├── Makefile ├── arithmetic_operations.exs ├── bad_match.exs ├── basic_data_type.exs ├── binary_and_list.exs ├── binary_list_calc1.exs ├── binary_list_calc2.exs ├── binary_operations.exs ├── blank.ex ├── bool_operations.exs ├── case_syntax.exs ├── cond_syntax.exs ├── defmacro_plus.exs ├── defmacro_unless.exs ├── defmacro_unless_fail.exs ├── delegate.exs ├── embedd_to_literal.exs ├── enum_map_take_map.exs ├── equivalent.exs ├── fn_syntax.exs ├── function_object.exs ├── function_syntax.exs ├── hat_operator1.exs ├── hello.cmd ├── hello.exs ├── hello.sh ├── hygiene.exs ├── iex_session.sh ├── if_syntax.exs ├── in_operator.exs ├── keyword_list.exs ├── list_operations.exs ├── list_resuce_partial_app.exs ├── order_of_types.exs ├── pipeline_flatten_and_double.exs ├── pipeline_flatten_and_double2.exs ├── private_macro.exs ├── protocol_access.exs ├── protocol_blank.exs ├── protocol_blank_any.exs ├── protocol_collectable.exs ├── protocol_fib.exs ├── quote_do_plus.exs ├── quote_do_sum.exs ├── quote_literal.exs ├── rebinding.exs ├── receive_syntax.exs ├── record_access.exs ├── record_block.exs ├── record_is_tuple.exs ├── record_update.exs ├── sh_session.sh ├── stream_map_take_map.exs ├── tuple_data_type.exs └── unquote_splicing.exs ├── illustrations ├── .DS_Store ├── actor_model.dia ├── actor_model.eps ├── actor_model.pdf ├── actor_model.png ├── diagram.dia ├── diagram.eps └── diagram.png └── source ├── conf.py ├── index.rst ├── introduction.rst ├── japanesesupport.py ├── map_and_struct.rst ├── metaprogramming.rst ├── partial_application.rst ├── protocol_enumerable.rst ├── record_and_protocol.rst ├── syntax.rst └── using_std_library.rst /.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | /codes/*.tmp 3 | /codes/*.cmd 4 | /codes/*.lst 5 | /ext/* 6 | /ext/citty -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "ext/citty"] 2 | path = ext/citty 3 | url = https://github.com/k1complete/citty 4 | branch = master 5 | [submodule "ext/sphinx-contrib"] 6 | path = ext/sphinx-contrib 7 | url = https://github.com/thewtex/sphinx-contrib 8 | branch = master 9 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | # Makefile for Sphinx documentation 2 | # 3 | 4 | # You can set these variables from the command line. 5 | SPHINXOPTS = -v 6 | SPHINXBUILD = sphinx-build 7 | PAPER = 8 | BUILDDIR = build 9 | 10 | # User-friendly check for sphinx-build 11 | ifeq ($(shell which $(SPHINXBUILD) >/dev/null 2>&1; echo $$?), 1) 12 | $(error The '$(SPHINXBUILD)' command was not found. Make sure you have Sphinx installed, then set the SPHINXBUILD environment variable to point to the full path of the '$(SPHINXBUILD)' executable. Alternatively you can add the directory with the executable to your PATH. If you don't have Sphinx installed, grab it from http://sphinx-doc.org/) 13 | endif 14 | 15 | # Internal variables. 16 | PAPEROPT_a4 = -D latex_paper_size=a4 17 | PAPEROPT_letter = -D latex_paper_size=letter 18 | ALLSPHINXOPTS = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) source 19 | # the i18n builder cannot share the environment and doctrees with the others 20 | I18NSPHINXOPTS = $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) source 21 | 22 | .PHONY: help clean html dirhtml singlehtml pickle json htmlhelp qthelp devhelp epub latex latexpdf text man changes linkcheck doctest gettext 23 | 24 | help: 25 | @echo "Please use \`make ' where is one of" 26 | @echo " html to make standalone HTML files" 27 | @echo " dirhtml to make HTML files named index.html in directories" 28 | @echo " singlehtml to make a single large HTML file" 29 | @echo " pickle to make pickle files" 30 | @echo " json to make JSON files" 31 | @echo " htmlhelp to make HTML files and a HTML help project" 32 | @echo " qthelp to make HTML files and a qthelp project" 33 | @echo " devhelp to make HTML files and a Devhelp project" 34 | @echo " epub to make an epub" 35 | @echo " latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter" 36 | @echo " latexpdf to make LaTeX files and run them through pdflatex" 37 | @echo " latexpdfja to make LaTeX files and run them through platex/dvipdfmx" 38 | @echo " text to make text files" 39 | @echo " man to make manual pages" 40 | @echo " texinfo to make Texinfo files" 41 | @echo " info to make Texinfo files and run them through makeinfo" 42 | @echo " gettext to make PO message catalogs" 43 | @echo " changes to make an overview of all changed/added/deprecated items" 44 | @echo " xml to make Docutils-native XML files" 45 | @echo " pseudoxml to make pseudoxml-XML files for display purposes" 46 | @echo " linkcheck to check all external links for integrity" 47 | @echo " doctest to run all doctests embedded in the documentation (if enabled)" 48 | 49 | clean: 50 | rm -rf $(BUILDDIR)/* 51 | rm *.beam 52 | # (cd codes; $(MAKE) clean ) 53 | 54 | CITTY = ext/citty 55 | 56 | $(CITTY)/configure: 57 | (cd $(CITTY); sh ./autogen.sh; ) 58 | 59 | $(CITTY)/Makefile: $(CITTY)/configure 60 | (cd $(CITTY); ./configure;) 61 | 62 | $(CITTY)/src/citty: 63 | (cd $(CITTY); $(MAKE);) 64 | 65 | prep: 66 | echo ok 67 | rm *.beam 68 | # (cd codes; $(MAKE)) 69 | 70 | html: $(CITTY)/Makefile $(CITTY)/src/citty 71 | $(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html 72 | @echo 73 | @echo "Build finished. The HTML pages are in $(BUILDDIR)/html." 74 | 75 | dirhtml: 76 | $(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) $(BUILDDIR)/dirhtml 77 | @echo 78 | @echo "Build finished. The HTML pages are in $(BUILDDIR)/dirhtml." 79 | 80 | singlehtml: 81 | $(SPHINXBUILD) -b singlehtml $(ALLSPHINXOPTS) $(BUILDDIR)/singlehtml 82 | @echo 83 | @echo "Build finished. The HTML page is in $(BUILDDIR)/singlehtml." 84 | 85 | pickle: 86 | $(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) $(BUILDDIR)/pickle 87 | @echo 88 | @echo "Build finished; now you can process the pickle files." 89 | 90 | json: 91 | $(SPHINXBUILD) -b json $(ALLSPHINXOPTS) $(BUILDDIR)/json 92 | @echo 93 | @echo "Build finished; now you can process the JSON files." 94 | 95 | htmlhelp: 96 | $(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) $(BUILDDIR)/htmlhelp 97 | @echo 98 | @echo "Build finished; now you can run HTML Help Workshop with the" \ 99 | ".hhp project file in $(BUILDDIR)/htmlhelp." 100 | 101 | qthelp: 102 | $(SPHINXBUILD) -b qthelp $(ALLSPHINXOPTS) $(BUILDDIR)/qthelp 103 | @echo 104 | @echo "Build finished; now you can run "qcollectiongenerator" with the" \ 105 | ".qhcp project file in $(BUILDDIR)/qthelp, like this:" 106 | @echo "# qcollectiongenerator $(BUILDDIR)/qthelp/elixiprimer.qhcp" 107 | @echo "To view the help file:" 108 | @echo "# assistant -collectionFile $(BUILDDIR)/qthelp/elixiprimer.qhc" 109 | 110 | devhelp: 111 | $(SPHINXBUILD) -b devhelp $(ALLSPHINXOPTS) $(BUILDDIR)/devhelp 112 | @echo 113 | @echo "Build finished." 114 | @echo "To view the help file:" 115 | @echo "# mkdir -p $$HOME/.local/share/devhelp/elixiprimer" 116 | @echo "# ln -s $(BUILDDIR)/devhelp $$HOME/.local/share/devhelp/elixiprimer" 117 | @echo "# devhelp" 118 | 119 | epub: 120 | $(SPHINXBUILD) -b epub $(ALLSPHINXOPTS) $(BUILDDIR)/epub 121 | @echo 122 | @echo "Build finished. The epub file is in $(BUILDDIR)/epub." 123 | 124 | latex: 125 | $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex 126 | @echo 127 | @echo "Build finished; the LaTeX files are in $(BUILDDIR)/latex." 128 | @echo "Run \`make' in that directory to run these through (pdf)latex" \ 129 | "(use \`make latexpdf' here to do that automatically)." 130 | 131 | latexpdf: 132 | $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex 133 | @echo "Running LaTeX files through pdflatex..." 134 | $(MAKE) -C $(BUILDDIR)/latex all-pdf 135 | @echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex." 136 | 137 | latexpdfja: 138 | $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex 139 | @echo "Running LaTeX files through platex and dvipdfmx..." 140 | $(MAKE) -C $(BUILDDIR)/latex all-pdf-ja 141 | @echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex." 142 | 143 | text: 144 | $(SPHINXBUILD) -b text $(ALLSPHINXOPTS) $(BUILDDIR)/text 145 | @echo 146 | @echo "Build finished. The text files are in $(BUILDDIR)/text." 147 | 148 | man: 149 | $(SPHINXBUILD) -b man $(ALLSPHINXOPTS) $(BUILDDIR)/man 150 | @echo 151 | @echo "Build finished. The manual pages are in $(BUILDDIR)/man." 152 | 153 | texinfo: 154 | $(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo 155 | @echo 156 | @echo "Build finished. The Texinfo files are in $(BUILDDIR)/texinfo." 157 | @echo "Run \`make' in that directory to run these through makeinfo" \ 158 | "(use \`make info' here to do that automatically)." 159 | 160 | info: 161 | $(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo 162 | @echo "Running Texinfo files through makeinfo..." 163 | make -C $(BUILDDIR)/texinfo info 164 | @echo "makeinfo finished; the Info files are in $(BUILDDIR)/texinfo." 165 | 166 | gettext: 167 | $(SPHINXBUILD) -b gettext $(I18NSPHINXOPTS) $(BUILDDIR)/locale 168 | @echo 169 | @echo "Build finished. The message catalogs are in $(BUILDDIR)/locale." 170 | 171 | changes: 172 | $(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) $(BUILDDIR)/changes 173 | @echo 174 | @echo "The overview file is in $(BUILDDIR)/changes." 175 | 176 | linkcheck: 177 | $(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) $(BUILDDIR)/linkcheck 178 | @echo 179 | @echo "Link check complete; look for any errors in the above output " \ 180 | "or in $(BUILDDIR)/linkcheck/output.txt." 181 | 182 | doctest: 183 | $(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) $(BUILDDIR)/doctest 184 | @echo "Testing of doctests in the sources finished, look at the " \ 185 | "results in $(BUILDDIR)/doctest/output.txt." 186 | 187 | xml: 188 | $(SPHINXBUILD) -b xml $(ALLSPHINXOPTS) $(BUILDDIR)/xml 189 | @echo 190 | @echo "Build finished. The XML files are in $(BUILDDIR)/xml." 191 | 192 | pseudoxml: 193 | $(SPHINXBUILD) -b pseudoxml $(ALLSPHINXOPTS) $(BUILDDIR)/pseudoxml 194 | @echo 195 | @echo "Build finished. The pseudo-XML files are in $(BUILDDIR)/pseudoxml." 196 | 197 | publish: 198 | scp -r build/html/* ns.maqcsa.org:/var/www/html/elixir_primer 199 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | elixir_primer 2 | ============= 3 | 4 | eixirの入門書をsphinxで買いてみています。 5 | もともとはdev.0.5.0から0.7.0頃のgetting startedを翻訳していたのですが、 6 | 本家の更新が早過ぎてついていけなくなったのと、OTPとの連携とかを 7 | 書き加えているうちに別物になってきました。 8 | 9 | 当初はlyxというワープロ(笑)で作業していましたがsphinxに乗り換え 10 | ることにして今に至ります。 11 | 12 | ビルド方法 13 | ---------- 14 | 15 | elixirが必要ですので事前にインストールしておきます。 16 | 17 | また、sphinx-contrib/autorunとk1complete/cittyが依存しています。 18 | autorunはsphinxビルド時にrunblockを任意のプログラムの標準入力として 19 | 実行した結果に置き換える拡張で、cittyは標準入力を疑似端末として 20 | 任意の対話型プログラムに送り、自動で対話するプログラムです。 21 | 22 | % make html 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /codes/Makefile: -------------------------------------------------------------------------------- 1 | SHSRC=hello.sh 2 | 3 | IEXSRC = arithmetic_operations.exs \ 4 | bad_match.exs \ 5 | basic_data_type.exs \ 6 | binary_and_list.exs \ 7 | binary_list_calc1.exs \ 8 | binary_list_calc2.exs \ 9 | binary_operations.exs \ 10 | bool_operations.exs \ 11 | case_syntax.exs \ 12 | cond_syntax.exs \ 13 | equivalent.exs \ 14 | embedd_to_literal.exs \ 15 | fn_syntax.exs \ 16 | function_object.exs \ 17 | function_syntax.exs \ 18 | hat_operator1.exs \ 19 | if_syntax.exs \ 20 | in_operator.exs \ 21 | keyword_list.exs \ 22 | list_operations.exs \ 23 | list_resuce_partial_app.exs \ 24 | order_of_types.exs \ 25 | pipeline_flatten_and_double.exs \ 26 | pipeline_flatten_and_double2.exs \ 27 | rebinding.exs \ 28 | receive_syntax.exs \ 29 | tuple_data_type.exs \ 30 | record_is_tuple.exs \ 31 | record_update.exs \ 32 | record_block.exs \ 33 | record_access.exs \ 34 | protocol_blank.exs \ 35 | protocol_blank_any.exs \ 36 | stream_map_take_map.exs \ 37 | enum_map_take_map.exs \ 38 | quote_do_sum.exs \ 39 | quote_do_plus.exs \ 40 | quote_literal.exs \ 41 | defmacro_unless.exs \ 42 | defmacro_unless_fail.exs \ 43 | unquote_splicing.exs \ 44 | hygiene.exs \ 45 | defmacro_plus.exs \ 46 | private_macro.exs \ 47 | delegate.exs 48 | 49 | 50 | 51 | 52 | TARGET=$(IEXSRC:.exs=.lst) $(SHSRC:.sh=.lst) 53 | 54 | %.lst:%.sh 55 | sh sh_session.sh $< 56 | 57 | %.lst:%.exs 58 | sh iex_session.sh $< 59 | 60 | all: $(TARGET) 61 | 62 | clean-tmp: 63 | -rm -f $(IEXSRC:.exs=.cmd) $(TARGET:.lst=.tmp) *~ 64 | 65 | clean: 66 | -rm -f $(TARGET) $(IEXSRC:.exs=.cmd) $(TARGET:.lst=.tmp) *~ 67 | -------------------------------------------------------------------------------- /codes/arithmetic_operations.exs: -------------------------------------------------------------------------------- 1 | 1+2 2 | 1-2 3 | 1.0+1.0 4 | 2*3 5 | 12/4 6 | 12/5 7 | div(11,5) 8 | rem(11,5) 9 | -------------------------------------------------------------------------------- /codes/bad_match.exs: -------------------------------------------------------------------------------- 1 | [x, x] = [1, 2] 2 | -------------------------------------------------------------------------------- /codes/basic_data_type.exs: -------------------------------------------------------------------------------- 1 | 1 # integer 2 | 0x10 3 | 0b10 4 | 1.0 5 | :atom 6 | {1,2,3} 7 | [1,2,3] 8 | -------------------------------------------------------------------------------- /codes/binary_and_list.exs: -------------------------------------------------------------------------------- 1 | list='abc' 2 | bin="abc" 3 | [h|t]=list 4 | t 5 | h 6 | list==bin 7 | list2='あいうえお' 8 | bin2="あいうえお" 9 | :binary.bin_to_list(bin2) 10 | String.to_char_list(bin2) 11 | 12 | -------------------------------------------------------------------------------- /codes/binary_list_calc1.exs: -------------------------------------------------------------------------------- 1 | list = ["foo", "bar", "baz"] 2 | Enum.map list, fn(x) -> size(x) end 3 | -------------------------------------------------------------------------------- /codes/binary_list_calc2.exs: -------------------------------------------------------------------------------- 1 | list = ["foo", "bar", "baz"] 2 | Enum.map list, &size(&1) 3 | -------------------------------------------------------------------------------- /codes/binary_operations.exs: -------------------------------------------------------------------------------- 1 | "binary" ++ "bin" 2 | "binary" <> "bin" 3 | -------------------------------------------------------------------------------- /codes/blank.ex: -------------------------------------------------------------------------------- 1 | defprotocol Blank do 2 | def blank?(data) 3 | end 4 | ## implstart 5 | defimpl Blank, for: List do 6 | def blank?([]), do: true 7 | def blank?(_), do: false 8 | end 9 | -------------------------------------------------------------------------------- /codes/bool_operations.exs: -------------------------------------------------------------------------------- 1 | true or false 2 | false and is_binary("abc") 3 | 1 and 2 4 | 1 and false 5 | true or error("This error will never be raised") 6 | false and error("This error will never be raised") 7 | -------------------------------------------------------------------------------- /codes/case_syntax.exs: -------------------------------------------------------------------------------- 1 | x = 1 2 | case [1,2,3] do 3 | [1,2,x] -> x 4 | x -> x 5 | _ -> 0 6 | end 7 | case [1,2,3] do 8 | x -> x 9 | [1,x,3] -> x 10 | _ -> 0 11 | end 12 | -------------------------------------------------------------------------------- /codes/cond_syntax.exs: -------------------------------------------------------------------------------- 1 | x = 4 2 | cond do 3 | 2 + x == 5 -> 4 | "x is 3" 5 | 2 * x == 8 -> 6 | "x is 4" 7 | 1 * x == x -> 8 | "x == any" 9 | end 10 | -------------------------------------------------------------------------------- /codes/defmacro_plus.exs: -------------------------------------------------------------------------------- 1 | defmodule MyMacro do 2 | defmacro plus(x) do 3 | {:"+", [], [x, x]} 4 | end 5 | end 6 | require MyMacro 7 | MyMacro.plus(4) 8 | IO.puts Macro.to_string(Macro.expand(quote do 9 | MyMacro.plus(4) 10 | end, __ENV__)) 11 | -------------------------------------------------------------------------------- /codes/defmacro_unless.exs: -------------------------------------------------------------------------------- 1 | defmodule MyMacro do 2 | defmacro unless(clause, options) do 3 | quote do 4 | if !unquote(clause), unquote(options) 5 | end 6 | end 7 | end 8 | -------------------------------------------------------------------------------- /codes/defmacro_unless_fail.exs: -------------------------------------------------------------------------------- 1 | defmodule UnlessFail do 2 | defmacro unless(clause, options) do 3 | quote do 4 | if !clause, options 5 | end 6 | end 7 | end 8 | -------------------------------------------------------------------------------- /codes/delegate.exs: -------------------------------------------------------------------------------- 1 | defmodule Delegate do 2 | defp makeargs(arity) do 3 | 1..arity |> 4 | Enum.map(fn(x) -> 5 | arg = String.to_atom("arg#{x}") 6 | {arg, [], Elixir} 7 | end) 8 | end 9 | defp delegate_1m([{fname, arity} | t], to: module) do 10 | args = makeargs(arity) 11 | e = quote do 12 | def unquote(fname)(unquote_splicing(args)) do 13 | apply unquote(module), unquote(fname), [unquote_splicing(args)] 14 | end 15 | end 16 | case t do 17 | [] -> [e] 18 | t -> [e | delegate_1m(t, to: module)] 19 | end 20 | end 21 | defmacro delegate_1(t, to: module) do 22 | delegate_1m(t, to: module) 23 | end 24 | defmacro delegate_2(tuplelist, to: module) when is_list(tuplelist) do 25 | tuplelist |> 26 | Enum.map(fn({fname, arity}) -> 27 | args = makeargs(arity) 28 | quote do 29 | def unquote(fname)(unquote_splicing(args)) do 30 | apply unquote(module), unquote(fname), [unquote_splicing(args)] 31 | end 32 | end 33 | end) 34 | end 35 | end 36 | defmodule MyList do 37 | require Delegate 38 | Delegate.delegate_1 [member?: 2, reverse: 1], to: Enum 39 | end 40 | -------------------------------------------------------------------------------- /codes/embedd_to_literal.exs: -------------------------------------------------------------------------------- 1 | bin="abc" 2 | list='abc' 3 | "embedd #{bin}" 4 | 'embedd #{list}' 5 | 'embedd binary into list #{bin}' 6 | "embedd list into binary #{list}" 7 | is_binary(bin) 8 | is_binary(list) 9 | is_list(bin) 10 | is_list(list) 11 | -------------------------------------------------------------------------------- /codes/enum_map_take_map.exs: -------------------------------------------------------------------------------- 1 | Enum.map([1,2,3,4,5], 2 | fn(x) -> IO.puts("step1 #{x}+1"); x + 1 end) |> 3 | Enum.take(3) |> 4 | Enum.map fn(x) -> IO.puts("step3 #{x} + 1"); x + 1 end 5 | 6 | -------------------------------------------------------------------------------- /codes/equivalent.exs: -------------------------------------------------------------------------------- 1 | 1.0 == 1 2 | 1.0 === 1 3 | -------------------------------------------------------------------------------- /codes/fn_syntax.exs: -------------------------------------------------------------------------------- 1 | m = Macro.expand(quote do 2 | fn(x) -> x + 1 end 3 | end, __ENV__) 4 | -------------------------------------------------------------------------------- /codes/function_object.exs: -------------------------------------------------------------------------------- 1 | x = fn(y,z) -> y + z end 2 | x(1,2) 3 | x.(1,2) 4 | -------------------------------------------------------------------------------- /codes/function_syntax.exs: -------------------------------------------------------------------------------- 1 | f = function do 2 | x, y when x > 0 -> x + y 3 | x, y -> x * y 4 | end 5 | f.(1, 3) 6 | f.(-1, 3) 7 | g = fn 8 | x, y when x > 0 -> x + y 9 | x, y -> x * y 10 | end 11 | g.(1,3) 12 | g.(-1,3) 13 | -------------------------------------------------------------------------------- /codes/hat_operator1.exs: -------------------------------------------------------------------------------- 1 | t = [2,3,4] 2 | [1|^t|5]=[1,2,3,4,5] 3 | [1|^t]=[1,2,3,4] 4 | -------------------------------------------------------------------------------- /codes/hello.cmd: -------------------------------------------------------------------------------- 1 | spawn bash -i 2 | expect "\$ " 3 | send "iex \n" 4 | expect "iex*\> " 5 | log_file hello.tmp 6 | send {defmodule ModuleName do 7 | } 8 | expect "*> " 9 | 10 | send { def method_name(arg1) do 11 | } 12 | expect "*> " 13 | 14 | send { {:body, arg1} 15 | } 16 | expect "*> " 17 | 18 | send { end 19 | } 20 | expect "*> " 21 | 22 | send { def short_method(arg1), do: {:body, arg1} 23 | } 24 | expect "*> " 25 | 26 | send {end 27 | } 28 | expect "*> " 29 | 30 | send {defmodule Hello do 31 | } 32 | expect "*> " 33 | 34 | send { def world do 35 | } 36 | expect "*> " 37 | 38 | send { IO.puts("Hello, world.") 39 | } 40 | expect "*> " 41 | 42 | send { end 43 | } 44 | expect "*> " 45 | 46 | send {end 47 | } 48 | expect "*> " 49 | 50 | send {Hello.world 51 | } 52 | expect "*> " 53 | 54 | -------------------------------------------------------------------------------- /codes/hello.exs: -------------------------------------------------------------------------------- 1 | defmodule ModuleName do 2 | def method_name(arg1) do 3 | {:body, arg1} 4 | end 5 | def short_method(arg1), do: {:body, arg1} 6 | end 7 | defmodule Hello do 8 | def world do 9 | IO.puts("Hello, world.") 10 | end 11 | end 12 | Hello.world 13 | -------------------------------------------------------------------------------- /codes/hello.sh: -------------------------------------------------------------------------------- 1 | elixir hello.exs 2 | -------------------------------------------------------------------------------- /codes/hygiene.exs: -------------------------------------------------------------------------------- 1 | defmodule Hygiene do 2 | defmacro testmacro do 3 | quote do: a = 1 4 | end 5 | end 6 | a = 10 7 | require Hygiene; Hygiene.testmacro 8 | a 9 | defmodule Hygiene2 do 10 | defmacro testmacro do 11 | quote do: var!(a) = 1 12 | end 13 | end 14 | a = 10 15 | require Hygiene2; Hygiene2.testmacro 16 | a 17 | Macro.expand_once(quote do 18 | Hygiene.testmacro 19 | end, __ENV__) 20 | Macro.expand_once(quote do 21 | Hygiene2.testmacro 22 | end, __ENV__) 23 | -------------------------------------------------------------------------------- /codes/iex_session.sh: -------------------------------------------------------------------------------- 1 | OUT=`basename -s exs $1`cmd 2 | OUT2=`basename -s exs $1`tmp 3 | OUT3=`basename -s exs $1`lst 4 | PS1='$ ' 5 | touch $OUT 6 | rm $OUT 7 | cat > $OUT < " 13 | EOF 14 | sed 's/[][\"]/\\&/g' $1 | awk '{printf " send \"%s\\n\"\n", $0; print " expect {\n*(*)> }\n" }' >> $OUT 15 | cat >> $OUT2 < $OUT3 23 | -------------------------------------------------------------------------------- /codes/if_syntax.exs: -------------------------------------------------------------------------------- 1 | x = 1 2 | if x == 1, do: :one, else: :not_one 3 | if x == 1 do 4 | :one 5 | else 6 | :not_one 7 | end 8 | x = 2 9 | if x == 1, do: :one, else: :not_one 10 | if x == 1 do 11 | :one 12 | else 13 | :not_one 14 | end 15 | -------------------------------------------------------------------------------- /codes/in_operator.exs: -------------------------------------------------------------------------------- 1 | y = 3 2 | y in [1,2,3] 3 | 4 | :lists.member(y, [1,2,3]) 5 | Enum.any?([1,2,3], fn(x) -> x == y end) 6 | -------------------------------------------------------------------------------- /codes/keyword_list.exs: -------------------------------------------------------------------------------- 1 | x = [a: 1, b: 2] 2 | Keyword.get x, :a 3 | Keyword.get x, :b 4 | Keyword.get x, :c 5 | -------------------------------------------------------------------------------- /codes/list_operations.exs: -------------------------------------------------------------------------------- 1 | [1,2,3] ++ [4,5,6] 2 | [1,2,3] -- [2,3] 3 | [1,2,3] -- [4] 4 | [1,2,3] -- [3,1] 5 | -------------------------------------------------------------------------------- /codes/list_resuce_partial_app.exs: -------------------------------------------------------------------------------- 1 | Enum.reduce [1,2,3], 1, &(&1 * &2) 2 | -------------------------------------------------------------------------------- /codes/order_of_types.exs: -------------------------------------------------------------------------------- 1 | 1 < :a < fn() -> :a end < {1,2} < 'abc' < "abc" 2 | -------------------------------------------------------------------------------- /codes/pipeline_flatten_and_double.exs: -------------------------------------------------------------------------------- 1 | [1, [2], 3] |> List.flatten |> Enum.map(&(&1 * 2)) 2 | -------------------------------------------------------------------------------- /codes/pipeline_flatten_and_double2.exs: -------------------------------------------------------------------------------- 1 | Enum.map(List.flatten([1, [2], 3]), &(&1 * 2)) 2 | -------------------------------------------------------------------------------- /codes/private_macro.exs: -------------------------------------------------------------------------------- 1 | defmodule MyMacro do 2 | defmacrop is_even(x) do 3 | quote do 4 | rem(unquote(x), 2) == 0 5 | end 6 | end 7 | def add_even(a, b) when is_even(a) and is_even(b) do 8 | a + b 9 | end 10 | end 11 | 12 | defmodule MyMacro2 do 13 | def add_even(a, b) when is_even(a) and is_even(b) do 14 | a + b 15 | end 16 | defmacrop is_even(x) do 17 | quote do 18 | rem(unquote(x), 2) == 0 19 | end 20 | end 21 | end 22 | -------------------------------------------------------------------------------- /codes/protocol_access.exs: -------------------------------------------------------------------------------- 1 | defimpl Access, for: Fib do 2 | def get(a, :f0), do: a.f0 3 | def get(a, :f1), do: a.f1 4 | def get(a, :count), do: a.count 5 | def get_and_update(a, key, f) do 6 | {:ok, value} = :maps.find(key, a) 7 | {get, update} = f.(value) 8 | {get, :maps.put(key, update, a)} 9 | end 10 | end 11 | 12 | 13 | -------------------------------------------------------------------------------- /codes/protocol_blank.exs: -------------------------------------------------------------------------------- 1 | defprotocol Blank do 2 | def blank?(data) 3 | end 4 | defimpl Blank, for: List do 5 | def blank?([]), do: true 6 | def blank?(_), do: false 7 | end 8 | Blank.blank?([]) 9 | Blank.blank?([1]) 10 | Blank.blank?(1) 11 | defimpl Blank, for: Integer do 12 | def blank?(_), do: true 13 | end 14 | Blank.blank?(0) 15 | Blank.blank?(1) 16 | -------------------------------------------------------------------------------- /codes/protocol_blank_any.exs: -------------------------------------------------------------------------------- 1 | defprotocol Blank do 2 | @fallback_to_any true 3 | def blank?(data) 4 | end 5 | defimpl Blank, for: Any do 6 | def blank?(_), do: false 7 | end 8 | -------------------------------------------------------------------------------- /codes/protocol_collectable.exs: -------------------------------------------------------------------------------- 1 | defmodule FileAppender do 2 | defstruct file: nil 3 | 4 | def empty(file) do 5 | File.rm(file) 6 | %FileAppender{file: file} 7 | end 8 | end 9 | defimpl Collectable, for: FileAppender do 10 | def into(collectable) do 11 | {collectable, 12 | fn 13 | fa, {:cont, term} -> 14 | File.write(fa.file, "#{inspect term}\n", [:append]) 15 | fa 16 | fa, :done -> fa 17 | _, :halt -> :ok 18 | end} 19 | end 20 | end 21 | -------------------------------------------------------------------------------- /codes/protocol_fib.exs: -------------------------------------------------------------------------------- 1 | defmodule Fib do 2 | defstruct f0: 1, f1: 1, count: :infinity 3 | def new() do 4 | %Fib{} 5 | end 6 | def new(count) do 7 | %Fib{count: count} 8 | end 9 | end 10 | defimpl Enumerable, for: Fib do 11 | def count(%Fib{count: :infinity}) do 12 | {:error, __MODULE__} 13 | end 14 | def count(e) do 15 | {:ok, e.count} 16 | end 17 | def reduce(e, acc, fun) do 18 | reduce(e.f0, e.f1, e.count, acc, fun) 19 | end 20 | def reduce(_f0, _f1, 0, {:cont, acc}, _fun) do 21 | {:done, acc} 22 | end 23 | def reduce(f0, f1, :infinity, {:cont, acc}, fun) do 24 | reduce(f1, f0+f1, :infinity, fun.(f0, acc), fun) 25 | end 26 | def reduce(f0, f1, n, {:cont, acc}, fun) do 27 | reduce(f1, f0+f1, n-1, fun.(f0, acc), fun) 28 | end 29 | def reduce(_, _, _, {:halt, acc}, _fun) do 30 | {:halted, acc} 31 | end 32 | def reduce(f0, f1, n, {:suspend, acc}, fun) do 33 | {:suspended, acc, &reduce(f0, f1, n, &1, fun)} 34 | end 35 | def member?(_e, _i) do 36 | {:error, __MODULE__} 37 | end 38 | end 39 | 40 | -------------------------------------------------------------------------------- /codes/quote_do_plus.exs: -------------------------------------------------------------------------------- 1 | quote do: 1 + 2 2 | quote do: { 1, 2} 3 | quote do: { 1, 2, 3} -------------------------------------------------------------------------------- /codes/quote_do_sum.exs: -------------------------------------------------------------------------------- 1 | quote do: sum(1,2,3) 2 | quote do 3 | sum(1,2,3) 4 | end 5 | -------------------------------------------------------------------------------- /codes/quote_literal.exs: -------------------------------------------------------------------------------- 1 | quote do: :atom # atom 2 | quote do: 2.0 # number 3 | quote do: [1, 2, 3] # list 4 | quote do: "binary" # binary 5 | quote do: {:key, :value} # 2 element tuple 6 | x=1 7 | quote do: x 8 | quote do 9 | 1 10 | 2 11 | end 12 | -------------------------------------------------------------------------------- /codes/rebinding.exs: -------------------------------------------------------------------------------- 1 | t = [2,3] 2 | t 3 | [1|t] = [1,2,3,4] 4 | t 5 | -------------------------------------------------------------------------------- /codes/receive_syntax.exs: -------------------------------------------------------------------------------- 1 | # Get the current process id 2 | current_pid = self 3 | # Spawn another process that will send a message 4 | spawn fn -> 5 | self current_pid, { :hello, self } 6 | end 7 | # Collect the message 8 | receive do 9 | { :hello, pid } -> 10 | IO.puts "Hello from #{inspect(pid)}" 11 | end 12 | -------------------------------------------------------------------------------- /codes/record_access.exs: -------------------------------------------------------------------------------- 1 | defrecord Record1, attribute1: nil, attribute2: nil 2 | 3 | m = Record1[attribute1: 1, attribute2: 2] 4 | Record1[attribute1: a, attribute2: b] = m 5 | a 6 | b 7 | Record1[attribute1: c] = m 8 | c -------------------------------------------------------------------------------- /codes/record_block.exs: -------------------------------------------------------------------------------- 1 | defrecord FileInfo, atime: nil, mtime: nil, access: 0 do 2 | def access_increment(m) when is_record(m, FileInfo) do 3 | m.update_access(fn(x) -> x+1 end) 4 | end 5 | end 6 | r1 = FileInfo[] 7 | r2 = r1.access_increment 8 | r2 9 | FileInfo.access_increment(r2) 10 | -------------------------------------------------------------------------------- /codes/record_is_tuple.exs: -------------------------------------------------------------------------------- 1 | defrecord FileInfo, atime: nil, mtime: nil, access: 0 2 | a = {FileInfo, nil, nil, 0} 3 | bad = {:"FileInfo", nil, nil, 0} 4 | defrecord :"user.info", user: nil, group: nil 5 | u = :"user.info".new() 6 | u2 = {:"user.info", nil, nil} 7 | -------------------------------------------------------------------------------- /codes/record_update.exs: -------------------------------------------------------------------------------- 1 | r = defrecord FileInfo, atime: nil, mtime: nil, access: 0 2 | m1 = FileInfo.new 3 | m1.access 4 | m2 = m1.update_access(fn(x) -> x+1 end) 5 | m2.access 6 | m3 = m1.update(access: m1.access+1) 7 | m3.access 8 | 9 | defrecord FileInfo2, FileInfo: nil, update: nil 10 | -------------------------------------------------------------------------------- /codes/sh_session.sh: -------------------------------------------------------------------------------- 1 | OUT=`basename $1 sh`tmp 2 | OUT2=`basename $1 sh`lst 3 | echo $OUT 4 | echo $OUT2 5 | export IN=$1 6 | export PS1='$ ' 7 | cat > $OUT <> $OUT 13 | cat >> $OUT < IO.puts("step1 #{x}+1"); x + 1 end) |> 3 | Stream.take(3) |> 4 | Stream.map(fn(x) -> IO.puts("step3 #{x} + 1"); x + 1 end) |> 5 | Enum.to_list 6 | 7 | m = Stream.map([1,2,3,4,5], 8 | fn(x) -> IO.puts("step1 #{x}+1"); x + 1 end) 9 | m2 = Stream.take(m, 3) 10 | m3 = Stream.map(m2, fn(x) -> IO.puts("step3 #{x} + 1"); x + 1 end) 11 | m3 |> Enum.to_list 12 | -------------------------------------------------------------------------------- /codes/tuple_data_type.exs: -------------------------------------------------------------------------------- 1 | {:item1, :item2} 2 | {} 3 | a = {:uname, "netbsd", "i386", "smp"} 4 | elem a, 1 5 | set_elem a, 1, "freebsd" 6 | -------------------------------------------------------------------------------- /codes/unquote_splicing.exs: -------------------------------------------------------------------------------- 1 | quote do: [1, unquote_splicing([2,3,4]), 5] 2 | -------------------------------------------------------------------------------- /illustrations/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/k1complete/elixir_primer/c74b3f1d47d8b3c43bc3d852379d5cdc6de7ff5c/illustrations/.DS_Store -------------------------------------------------------------------------------- /illustrations/actor_model.dia: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/k1complete/elixir_primer/c74b3f1d47d8b3c43bc3d852379d5cdc6de7ff5c/illustrations/actor_model.dia -------------------------------------------------------------------------------- /illustrations/actor_model.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/k1complete/elixir_primer/c74b3f1d47d8b3c43bc3d852379d5cdc6de7ff5c/illustrations/actor_model.pdf -------------------------------------------------------------------------------- /illustrations/actor_model.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/k1complete/elixir_primer/c74b3f1d47d8b3c43bc3d852379d5cdc6de7ff5c/illustrations/actor_model.png -------------------------------------------------------------------------------- /illustrations/diagram.dia: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/k1complete/elixir_primer/c74b3f1d47d8b3c43bc3d852379d5cdc6de7ff5c/illustrations/diagram.dia -------------------------------------------------------------------------------- /illustrations/diagram.eps: -------------------------------------------------------------------------------- 1 | %!PS-Adobe-2.0 EPSF-2.0 2 | %%Title: /Users/k-1/Dropbox/elixir_doc_lyx/illustrations/diagram.dia 3 | %%Creator: Dia v0.97.2 4 | %%CreationDate: Mon Jan 14 21:32:05 2013 5 | %%For: k-1 6 | %%Orientation: Portrait 7 | %%Magnification: 1.0000 8 | %%BoundingBox: 0 0 128 128 9 | %%BeginSetup 10 | %%EndSetup 11 | %%EndComments 12 | %%BeginProlog 13 | [ /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef 14 | /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef 15 | /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef 16 | /.notdef /.notdef /space /exclam /quotedbl /numbersign /dollar /percent /ampersand /quoteright 17 | /parenleft /parenright /asterisk /plus /comma /hyphen /period /slash /zero /one 18 | /two /three /four /five /six /seven /eight /nine /colon /semicolon 19 | /less /equal /greater /question /at /A /B /C /D /E 20 | /F /G /H /I /J /K /L /M /N /O 21 | /P /Q /R /S /T /U /V /W /X /Y 22 | /Z /bracketleft /backslash /bracketright /asciicircum /underscore /quoteleft /a /b /c 23 | /d /e /f /g /h /i /j /k /l /m 24 | /n /o /p /q /r /s /t /u /v /w 25 | /x /y /z /braceleft /bar /braceright /asciitilde /.notdef /.notdef /.notdef 26 | /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef 27 | /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef 28 | /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef 29 | /space /exclamdown /cent /sterling /currency /yen /brokenbar /section /dieresis /copyright 30 | /ordfeminine /guillemotleft /logicalnot /hyphen /registered /macron /degree /plusminus /twosuperior /threesuperior 31 | /acute /mu /paragraph /periodcentered /cedilla /onesuperior /ordmasculine /guillemotright /onequarter /onehalf 32 | /threequarters /questiondown /Agrave /Aacute /Acircumflex /Atilde /Adieresis /Aring /AE /Ccedilla 33 | /Egrave /Eacute /Ecircumflex /Edieresis /Igrave /Iacute /Icircumflex /Idieresis /Eth /Ntilde 34 | /Ograve /Oacute /Ocircumflex /Otilde /Odieresis /multiply /Oslash /Ugrave /Uacute /Ucircumflex 35 | /Udieresis /Yacute /Thorn /germandbls /agrave /aacute /acircumflex /atilde /adieresis /aring 36 | /ae /ccedilla /egrave /eacute /ecircumflex /edieresis /igrave /iacute /icircumflex /idieresis 37 | /eth /ntilde /ograve /oacute /ocircumflex /otilde /odieresis /divide /oslash /ugrave 38 | /uacute /ucircumflex /udieresis /yacute /thorn /ydieresis] /isolatin1encoding exch def 39 | /cp {closepath} bind def 40 | /c {curveto} bind def 41 | /f {fill} bind def 42 | /a {arc} bind def 43 | /ef {eofill} bind def 44 | /ex {exch} bind def 45 | /gr {grestore} bind def 46 | /gs {gsave} bind def 47 | /sa {save} bind def 48 | /rs {restore} bind def 49 | /l {lineto} bind def 50 | /m {moveto} bind def 51 | /rm {rmoveto} bind def 52 | /n {newpath} bind def 53 | /s {stroke} bind def 54 | /sh {show} bind def 55 | /slc {setlinecap} bind def 56 | /slj {setlinejoin} bind def 57 | /slw {setlinewidth} bind def 58 | /srgb {setrgbcolor} bind def 59 | /rot {rotate} bind def 60 | /sc {scale} bind def 61 | /sd {setdash} bind def 62 | /ff {findfont} bind def 63 | /sf {setfont} bind def 64 | /scf {scalefont} bind def 65 | /sw {stringwidth pop} bind def 66 | /tr {translate} bind def 67 | 68 | /ellipsedict 8 dict def 69 | ellipsedict /mtrx matrix put 70 | /ellipse 71 | { ellipsedict begin 72 | /endangle exch def 73 | /startangle exch def 74 | /yrad exch def 75 | /xrad exch def 76 | /y exch def 77 | /x exch def /savematrix mtrx currentmatrix def 78 | x y tr xrad yrad sc 79 | 0 0 1 startangle endangle arc 80 | savematrix setmatrix 81 | end 82 | } def 83 | 84 | /mergeprocs { 85 | dup length 86 | 3 -1 roll 87 | dup 88 | length 89 | dup 90 | 5 1 roll 91 | 3 -1 roll 92 | add 93 | array cvx 94 | dup 95 | 3 -1 roll 96 | 0 exch 97 | putinterval 98 | dup 99 | 4 2 roll 100 | putinterval 101 | } bind def 102 | /dpi_x 300 def 103 | /dpi_y 300 def 104 | /conicto { 105 | /to_y exch def 106 | /to_x exch def 107 | /conic_cntrl_y exch def 108 | /conic_cntrl_x exch def 109 | currentpoint 110 | /p0_y exch def 111 | /p0_x exch def 112 | /p1_x p0_x conic_cntrl_x p0_x sub 2 3 div mul add def 113 | /p1_y p0_y conic_cntrl_y p0_y sub 2 3 div mul add def 114 | /p2_x p1_x to_x p0_x sub 1 3 div mul add def 115 | /p2_y p1_y to_y p0_y sub 1 3 div mul add def 116 | p1_x p1_y p2_x p2_y to_x to_y curveto 117 | } bind def 118 | /start_ol { gsave 1.1 dpi_x div dup scale} bind def 119 | /end_ol { closepath fill grestore } bind def 120 | 28.346000 -28.346000 scale 121 | -1.995000 1.495000 translate 122 | %%EndProlog 123 | 124 | 125 | 0.010000 slw 126 | [] 0 sd 127 | [] 0 sd 128 | 0 slj 129 | 1.000000 1.000000 1.000000 srgb 130 | n 2.000000 -4.500000 m 2.000000 -2.950000 l 6.500000 -2.950000 l 6.500000 -4.500000 l f 131 | 0.000000 0.000000 0.000000 srgb 132 | n 2.000000 -4.500000 m 2.000000 -2.950000 l 6.500000 -2.950000 l 6.500000 -4.500000 l cp s 133 | gsave 3.738750 -3.608750 translate 0.035278 -0.035278 scale 134 | start_ol 135 | 256 1856 moveto 136 | 701 1856 lineto 137 | 1120 767 lineto 138 | 1539 1856 lineto 139 | 1984 1856 lineto 140 | 1984 0 lineto 141 | 1728 0 lineto 142 | 1728 1634 lineto 143 | 1247 384 lineto 144 | 993 384 lineto 145 | 512 1634 lineto 146 | 512 0 lineto 147 | 256 0 lineto 148 | 256 1856 lineto 149 | end_ol grestore 150 | gsave 4.028477 -3.608750 translate 0.035278 -0.035278 scale 151 | start_ol 152 | 821 704 moveto 153 | 574 704 479 644 conicto 154 | 384 585 384 441 conicto 155 | 384 326 455 259 conicto 156 | 527 192 650 192 conicto 157 | 819 192 921 319 conicto 158 | 1024 446 1024 657 conicto 159 | 1024 704 lineto 160 | 821 704 lineto 161 | 1280 805 moveto 162 | 1280 0 lineto 163 | 1024 0 lineto 164 | 1024 256 lineto 165 | 950 125 839 62 conicto 166 | 729 0 569 0 conicto 167 | 367 0 247 117 conicto 168 | 128 235 128 432 conicto 169 | 128 662 281 779 conicto 170 | 434 896 738 896 conicto 171 | 1024 896 lineto 172 | 1024 920 lineto 173 | 1024 1092 929 1186 conicto 174 | 835 1280 665 1280 conicto 175 | 556 1280 453 1248 conicto 176 | 351 1216 256 1152 conicto 177 | 256 1344 lineto 178 | 376 1408 488 1440 conicto 179 | 601 1472 708 1472 conicto 180 | 996 1472 1138 1306 conicto 181 | 1280 1141 1280 805 conicto 182 | end_ol grestore 183 | gsave 4.235778 -3.608750 translate 0.035278 -0.035278 scale 184 | start_ol 185 | 1216 1344 moveto 186 | 1216 1152 lineto 187 | 1122 1216 1027 1248 conicto 188 | 933 1280 837 1280 conicto 189 | 622 1280 503 1137 conicto 190 | 384 994 384 736 conicto 191 | 384 478 503 335 conicto 192 | 622 192 837 192 conicto 193 | 933 192 1027 224 conicto 194 | 1122 256 1216 320 conicto 195 | 1216 128 lineto 196 | 1121 64 1020 32 conicto 197 | 919 0 805 0 conicto 198 | 494 0 311 199 conicto 199 | 128 398 128 736 conicto 200 | 128 1079 313 1275 conicto 201 | 498 1472 819 1472 conicto 202 | 924 1472 1023 1440 conicto 203 | 1123 1408 1216 1344 conicto 204 | end_ol grestore 205 | gsave 4.420598 -3.608750 translate 0.035278 -0.035278 scale 206 | start_ol 207 | 1088 1216 moveto 208 | 1050 1249 1005 1264 conicto 209 | 961 1280 907 1280 conicto 210 | 716 1280 614 1145 conicto 211 | 512 1010 512 758 conicto 212 | 512 0 lineto 213 | 256 0 lineto 214 | 256 1408 lineto 215 | 512 1408 lineto 216 | 512 1216 lineto 217 | 583 1346 696 1409 conicto 218 | 810 1472 973 1472 conicto 219 | 996 1472 1024 1472 conicto 220 | 1053 1472 1087 1472 conicto 221 | 1088 1216 lineto 222 | end_ol grestore 223 | gsave 4.552972 -3.608750 translate 0.035278 -0.035278 scale 224 | start_ol 225 | 769 1280 moveto 226 | 591 1280 487 1134 conicto 227 | 384 989 384 736 conicto 228 | 384 483 487 337 conicto 229 | 590 192 769 192 conicto 230 | 945 192 1048 338 conicto 231 | 1152 484 1152 736 conicto 232 | 1152 987 1048 1133 conicto 233 | 945 1280 769 1280 conicto 234 | 768 1472 moveto 235 | 1067 1472 1237 1276 conicto 236 | 1408 1081 1408 736 conicto 237 | 1408 392 1237 196 conicto 238 | 1067 0 768 0 conicto 239 | 468 0 298 196 conicto 240 | 128 392 128 736 conicto 241 | 128 1081 298 1276 conicto 242 | 468 1472 768 1472 conicto 243 | end_ol grestore 244 | 0.010000 slw 245 | [] 0 sd 246 | [] 0 sd 247 | 0 slj 248 | 1.000000 1.000000 1.000000 srgb 249 | n 2.000000 -3.000000 m 2.000000 -1.500000 l 6.500000 -1.500000 l 6.500000 -3.000000 l f 250 | 0.000000 0.000000 0.000000 srgb 251 | n 2.000000 -3.000000 m 2.000000 -1.500000 l 6.500000 -1.500000 l 6.500000 -3.000000 l cp s 252 | gsave 2.872500 -2.133750 translate 0.035278 -0.035278 scale 253 | start_ol 254 | 1664 1728 moveto 255 | 1664 1472 lineto 256 | 1532 1601 1383 1664 conicto 257 | 1234 1728 1066 1728 conicto 258 | 735 1728 559 1530 conicto 259 | 384 1333 384 959 conicto 260 | 384 587 559 389 conicto 261 | 735 192 1066 192 conicto 262 | 1234 192 1383 255 conicto 263 | 1532 319 1664 448 conicto 264 | 1664 192 lineto 265 | 1529 96 1377 48 conicto 266 | 1226 0 1058 0 conicto 267 | 626 0 377 257 conicto 268 | 128 514 128 959 conicto 269 | 128 1406 377 1663 conicto 270 | 626 1920 1058 1920 conicto 271 | 1229 1920 1380 1872 conicto 272 | 1531 1824 1664 1728 conicto 273 | end_ol grestore 274 | gsave 3.107276 -2.133750 translate 0.035278 -0.035278 scale 275 | start_ol 276 | 769 1280 moveto 277 | 591 1280 487 1134 conicto 278 | 384 989 384 736 conicto 279 | 384 483 487 337 conicto 280 | 590 192 769 192 conicto 281 | 945 192 1048 338 conicto 282 | 1152 484 1152 736 conicto 283 | 1152 987 1048 1133 conicto 284 | 945 1280 769 1280 conicto 285 | 768 1472 moveto 286 | 1067 1472 1237 1276 conicto 287 | 1408 1081 1408 736 conicto 288 | 1408 392 1237 196 conicto 289 | 1067 0 768 0 conicto 290 | 468 0 298 196 conicto 291 | 128 392 128 736 conicto 292 | 128 1081 298 1276 conicto 293 | 468 1472 768 1472 conicto 294 | end_ol grestore 295 | gsave 3.314577 -2.133750 translate 0.035278 -0.035278 scale 296 | start_ol 297 | 1152 1216 moveto 298 | 1152 1920 lineto 299 | 1408 1920 lineto 300 | 1408 0 lineto 301 | 1152 0 lineto 302 | 1152 256 lineto 303 | 1079 126 968 63 conicto 304 | 857 0 702 0 conicto 305 | 448 0 288 203 conicto 306 | 128 406 128 736 conicto 307 | 128 1066 288 1269 conicto 308 | 448 1472 702 1472 conicto 309 | 857 1472 968 1409 conicto 310 | 1079 1346 1152 1216 conicto 311 | 384 736 moveto 312 | 384 482 486 337 conicto 313 | 589 192 767 192 conicto 314 | 946 192 1049 337 conicto 315 | 1152 482 1152 736 conicto 316 | 1152 990 1049 1135 conicto 317 | 946 1280 767 1280 conicto 318 | 589 1280 486 1135 conicto 319 | 384 990 384 736 conicto 320 | end_ol grestore 321 | gsave 3.529369 -2.133750 translate 0.035278 -0.035278 scale 322 | start_ol 323 | 1408 824 moveto 324 | 1408 704 lineto 325 | 384 704 lineto 326 | 398 454 520 323 conicto 327 | 643 192 862 192 conicto 328 | 989 192 1108 224 conicto 329 | 1227 256 1344 320 conicto 330 | 1344 128 lineto 331 | 1223 65 1096 32 conicto 332 | 969 0 838 0 conicto 333 | 511 0 319 195 conicto 334 | 128 391 128 723 conicto 335 | 128 1068 311 1270 conicto 336 | 494 1472 805 1472 conicto 337 | 1084 1472 1246 1297 conicto 338 | 1408 1123 1408 824 conicto 339 | 1152 896 moveto 340 | 1150 1071 1054 1175 conicto 341 | 958 1280 801 1280 conicto 342 | 622 1280 514 1179 conicto 343 | 407 1078 391 895 conicto 344 | 1152 896 lineto 345 | end_ol grestore 346 | gsave 3.736671 -2.133750 translate 0.035278 -0.035278 scale 347 | start_ol 348 | 1472 294 moveto 349 | 1472 832 lineto 350 | 1088 832 lineto 351 | 1088 1024 lineto 352 | 1728 1024 lineto 353 | 1728 195 lineto 354 | 1584 99 1411 49 conicto 355 | 1238 0 1042 0 conicto 356 | 613 0 370 253 conicto 357 | 128 507 128 959 conicto 358 | 128 1413 368 1666 conicto 359 | 608 1920 1033 1920 conicto 360 | 1210 1920 1369 1871 conicto 361 | 1529 1823 1664 1728 conicto 362 | 1664 1472 lineto 363 | 1528 1599 1374 1663 conicto 364 | 1221 1728 1052 1728 conicto 365 | 719 1728 551 1535 conicto 366 | 384 1342 384 959 conicto 367 | 384 578 552 385 conicto 368 | 720 192 1054 192 conicto 369 | 1185 192 1287 217 conicto 370 | 1390 242 1472 294 conicto 371 | end_ol grestore 372 | gsave 3.998922 -2.133750 translate 0.035278 -0.035278 scale 373 | start_ol 374 | 1408 824 moveto 375 | 1408 704 lineto 376 | 384 704 lineto 377 | 398 454 520 323 conicto 378 | 643 192 862 192 conicto 379 | 989 192 1108 224 conicto 380 | 1227 256 1344 320 conicto 381 | 1344 128 lineto 382 | 1223 65 1096 32 conicto 383 | 969 0 838 0 conicto 384 | 511 0 319 195 conicto 385 | 128 391 128 723 conicto 386 | 128 1068 311 1270 conicto 387 | 494 1472 805 1472 conicto 388 | 1084 1472 1246 1297 conicto 389 | 1408 1123 1408 824 conicto 390 | 1152 896 moveto 391 | 1150 1071 1054 1175 conicto 392 | 958 1280 801 1280 conicto 393 | 622 1280 514 1179 conicto 394 | 407 1078 391 895 conicto 395 | 1152 896 lineto 396 | end_ol grestore 397 | gsave 4.206223 -2.133750 translate 0.035278 -0.035278 scale 398 | start_ol 399 | 1408 869 moveto 400 | 1408 0 lineto 401 | 1152 0 lineto 402 | 1152 861 lineto 403 | 1152 1071 1082 1175 conicto 404 | 1013 1280 873 1280 conicto 405 | 705 1280 608 1155 conicto 406 | 512 1030 512 814 conicto 407 | 512 0 lineto 408 | 256 0 lineto 409 | 256 1408 lineto 410 | 512 1408 lineto 411 | 512 1216 lineto 412 | 591 1345 697 1408 conicto 413 | 804 1472 943 1472 conicto 414 | 1172 1472 1290 1319 conicto 415 | 1408 1166 1408 869 conicto 416 | end_ol grestore 417 | gsave 4.421015 -2.133750 translate 0.035278 -0.035278 scale 418 | start_ol 419 | 1408 824 moveto 420 | 1408 704 lineto 421 | 384 704 lineto 422 | 398 454 520 323 conicto 423 | 643 192 862 192 conicto 424 | 989 192 1108 224 conicto 425 | 1227 256 1344 320 conicto 426 | 1344 128 lineto 427 | 1223 65 1096 32 conicto 428 | 969 0 838 0 conicto 429 | 511 0 319 195 conicto 430 | 128 391 128 723 conicto 431 | 128 1068 311 1270 conicto 432 | 494 1472 805 1472 conicto 433 | 1084 1472 1246 1297 conicto 434 | 1408 1123 1408 824 conicto 435 | 1152 896 moveto 436 | 1150 1071 1054 1175 conicto 437 | 958 1280 801 1280 conicto 438 | 622 1280 514 1179 conicto 439 | 407 1078 391 895 conicto 440 | 1152 896 lineto 441 | end_ol grestore 442 | gsave 4.628316 -2.133750 translate 0.035278 -0.035278 scale 443 | start_ol 444 | 1088 1216 moveto 445 | 1050 1249 1005 1264 conicto 446 | 961 1280 907 1280 conicto 447 | 716 1280 614 1145 conicto 448 | 512 1010 512 758 conicto 449 | 512 0 lineto 450 | 256 0 lineto 451 | 256 1408 lineto 452 | 512 1408 lineto 453 | 512 1216 lineto 454 | 583 1346 696 1409 conicto 455 | 810 1472 973 1472 conicto 456 | 996 1472 1024 1472 conicto 457 | 1053 1472 1087 1472 conicto 458 | 1088 1216 lineto 459 | end_ol grestore 460 | gsave 4.768182 -2.133750 translate 0.035278 -0.035278 scale 461 | start_ol 462 | 821 704 moveto 463 | 574 704 479 644 conicto 464 | 384 585 384 441 conicto 465 | 384 326 455 259 conicto 466 | 527 192 650 192 conicto 467 | 819 192 921 319 conicto 468 | 1024 446 1024 657 conicto 469 | 1024 704 lineto 470 | 821 704 lineto 471 | 1280 805 moveto 472 | 1280 0 lineto 473 | 1024 0 lineto 474 | 1024 256 lineto 475 | 950 125 839 62 conicto 476 | 729 0 569 0 conicto 477 | 367 0 247 117 conicto 478 | 128 235 128 432 conicto 479 | 128 662 281 779 conicto 480 | 434 896 738 896 conicto 481 | 1024 896 lineto 482 | 1024 920 lineto 483 | 1024 1092 929 1186 conicto 484 | 835 1280 665 1280 conicto 485 | 556 1280 453 1248 conicto 486 | 351 1216 256 1152 conicto 487 | 256 1344 lineto 488 | 376 1408 488 1440 conicto 489 | 601 1472 708 1472 conicto 490 | 996 1472 1138 1306 conicto 491 | 1280 1141 1280 805 conicto 492 | end_ol grestore 493 | gsave 4.975483 -2.133750 translate 0.035278 -0.035278 scale 494 | start_ol 495 | 512 1792 moveto 496 | 512 1408 lineto 497 | 960 1408 lineto 498 | 960 1216 lineto 499 | 512 1216 lineto 500 | 512 460 lineto 501 | 512 289 556 240 conicto 502 | 601 192 737 192 conicto 503 | 960 192 lineto 504 | 960 0 lineto 505 | 737 0 lineto 506 | 464 0 360 99 conicto 507 | 256 198 256 460 conicto 508 | 256 1216 lineto 509 | 64 1216 lineto 510 | 64 1408 lineto 511 | 256 1408 lineto 512 | 256 1792 lineto 513 | 512 1792 lineto 514 | end_ol grestore 515 | gsave 5.107857 -2.133750 translate 0.035278 -0.035278 scale 516 | start_ol 517 | 256 1408 moveto 518 | 512 1408 lineto 519 | 512 0 lineto 520 | 256 0 lineto 521 | 256 1408 lineto 522 | 256 1920 moveto 523 | 512 1920 lineto 524 | 512 1600 lineto 525 | 256 1600 lineto 526 | 256 1920 lineto 527 | end_ol grestore 528 | gsave 5.202768 -2.133750 translate 0.035278 -0.035278 scale 529 | start_ol 530 | 769 1280 moveto 531 | 591 1280 487 1134 conicto 532 | 384 989 384 736 conicto 533 | 384 483 487 337 conicto 534 | 590 192 769 192 conicto 535 | 945 192 1048 338 conicto 536 | 1152 484 1152 736 conicto 537 | 1152 987 1048 1133 conicto 538 | 945 1280 769 1280 conicto 539 | 768 1472 moveto 540 | 1067 1472 1237 1276 conicto 541 | 1408 1081 1408 736 conicto 542 | 1408 392 1237 196 conicto 543 | 1067 0 768 0 conicto 544 | 468 0 298 196 conicto 545 | 128 392 128 736 conicto 546 | 128 1081 298 1276 conicto 547 | 468 1472 768 1472 conicto 548 | end_ol grestore 549 | gsave 5.410069 -2.133750 translate 0.035278 -0.035278 scale 550 | start_ol 551 | 1408 869 moveto 552 | 1408 0 lineto 553 | 1152 0 lineto 554 | 1152 861 lineto 555 | 1152 1071 1082 1175 conicto 556 | 1013 1280 873 1280 conicto 557 | 705 1280 608 1155 conicto 558 | 512 1030 512 814 conicto 559 | 512 0 lineto 560 | 256 0 lineto 561 | 256 1408 lineto 562 | 512 1408 lineto 563 | 512 1216 lineto 564 | 591 1345 697 1408 conicto 565 | 804 1472 943 1472 conicto 566 | 1172 1472 1290 1319 conicto 567 | 1408 1166 1408 869 conicto 568 | end_ol grestore 569 | 0.010000 slw 570 | [] 0 sd 571 | [] 0 sd 572 | 0 slj 573 | 1.000000 1.000000 1.000000 srgb 574 | n 2.000000 -6.000000 m 2.000000 -4.500000 l 6.500000 -4.500000 l 6.500000 -6.000000 l f 575 | 0.000000 0.000000 0.000000 srgb 576 | n 2.000000 -6.000000 m 2.000000 -4.500000 l 6.500000 -4.500000 l 6.500000 -6.000000 l cp s 577 | gsave 3.791250 -5.133750 translate 0.035278 -0.035278 scale 578 | start_ol 579 | 512 1664 moveto 580 | 512 960 lineto 581 | 838 960 lineto 582 | 1019 960 1117 1051 conicto 583 | 1216 1143 1216 1313 conicto 584 | 1216 1481 1117 1572 conicto 585 | 1019 1664 838 1664 conicto 586 | 512 1664 lineto 587 | 256 1856 moveto 588 | 838 1856 lineto 589 | 1151 1856 1311 1717 conicto 590 | 1472 1579 1472 1313 conicto 591 | 1472 1043 1311 905 conicto 592 | 1151 768 838 768 conicto 593 | 512 768 lineto 594 | 512 0 lineto 595 | 256 0 lineto 596 | 256 1856 lineto 597 | end_ol grestore 598 | gsave 3.978575 -5.133750 translate 0.035278 -0.035278 scale 599 | start_ol 600 | 821 704 moveto 601 | 574 704 479 644 conicto 602 | 384 585 384 441 conicto 603 | 384 326 455 259 conicto 604 | 527 192 650 192 conicto 605 | 819 192 921 319 conicto 606 | 1024 446 1024 657 conicto 607 | 1024 704 lineto 608 | 821 704 lineto 609 | 1280 805 moveto 610 | 1280 0 lineto 611 | 1024 0 lineto 612 | 1024 256 lineto 613 | 950 125 839 62 conicto 614 | 729 0 569 0 conicto 615 | 367 0 247 117 conicto 616 | 128 235 128 432 conicto 617 | 128 662 281 779 conicto 618 | 434 896 738 896 conicto 619 | 1024 896 lineto 620 | 1024 920 lineto 621 | 1024 1092 929 1186 conicto 622 | 835 1280 665 1280 conicto 623 | 556 1280 453 1248 conicto 624 | 351 1216 256 1152 conicto 625 | 256 1344 lineto 626 | 376 1408 488 1440 conicto 627 | 601 1472 708 1472 conicto 628 | 996 1472 1138 1306 conicto 629 | 1280 1141 1280 805 conicto 630 | end_ol grestore 631 | gsave 4.185876 -5.133750 translate 0.035278 -0.035278 scale 632 | start_ol 633 | 1088 1216 moveto 634 | 1050 1249 1005 1264 conicto 635 | 961 1280 907 1280 conicto 636 | 716 1280 614 1145 conicto 637 | 512 1010 512 758 conicto 638 | 512 0 lineto 639 | 256 0 lineto 640 | 256 1408 lineto 641 | 512 1408 lineto 642 | 512 1216 lineto 643 | 583 1346 696 1409 conicto 644 | 810 1472 973 1472 conicto 645 | 996 1472 1024 1472 conicto 646 | 1053 1472 1087 1472 conicto 647 | 1088 1216 lineto 648 | end_ol grestore 649 | gsave 4.325741 -5.133750 translate 0.035278 -0.035278 scale 650 | start_ol 651 | 1152 1344 moveto 652 | 1152 1152 lineto 653 | 1054 1216 948 1248 conicto 654 | 842 1280 729 1280 conicto 655 | 556 1280 470 1225 conicto 656 | 384 1170 384 1060 conicto 657 | 380 961 438 910 conicto 658 | 497 859 675 820 conicto 659 | 749 802 lineto 660 | 999 747 1106 657 conicto 661 | 1213 568 1216 414 conicto 662 | 1216 223 1059 111 conicto 663 | 902 0 628 0 conicto 664 | 513 0 389 16 conicto 665 | 265 32 128 64 conicto 666 | 128 320 lineto 667 | 255 256 378 224 conicto 668 | 502 192 623 192 conicto 669 | 785 192 872 246 conicto 670 | 960 300 960 399 conicto 671 | 960 490 899 538 conicto 672 | 839 587 634 632 conicto 673 | 558 651 lineto 674 | 330 697 229 791 conicto 675 | 128 886 128 1052 conicto 676 | 128 1253 273 1362 conicto 677 | 419 1472 687 1472 conicto 678 | 819 1472 936 1440 conicto 679 | 1053 1408 1152 1344 conicto 680 | end_ol grestore 681 | gsave 4.500573 -5.133750 translate 0.035278 -0.035278 scale 682 | start_ol 683 | 1408 824 moveto 684 | 1408 704 lineto 685 | 384 704 lineto 686 | 398 454 520 323 conicto 687 | 643 192 862 192 conicto 688 | 989 192 1108 224 conicto 689 | 1227 256 1344 320 conicto 690 | 1344 128 lineto 691 | 1223 65 1096 32 conicto 692 | 969 0 838 0 conicto 693 | 511 0 319 195 conicto 694 | 128 391 128 723 conicto 695 | 128 1068 311 1270 conicto 696 | 494 1472 805 1472 conicto 697 | 1084 1472 1246 1297 conicto 698 | 1408 1123 1408 824 conicto 699 | 1152 896 moveto 700 | 1150 1071 1054 1175 conicto 701 | 958 1280 801 1280 conicto 702 | 622 1280 514 1179 conicto 703 | 407 1078 391 895 conicto 704 | 1152 896 lineto 705 | end_ol grestore 706 | showpage 707 | -------------------------------------------------------------------------------- /illustrations/diagram.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/k1complete/elixir_primer/c74b3f1d47d8b3c43bc3d852379d5cdc6de7ff5c/illustrations/diagram.png -------------------------------------------------------------------------------- /source/conf.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # 3 | # elixi primer documentation build configuration file, created by 4 | # sphinx-quickstart on Sat Jun 29 10:39:51 2013. 5 | # 6 | # This file is execfile()d with the current directory set to its containing dir. 7 | # 8 | # Note that not all possible configuration values are present in this 9 | # autogenerated file. 10 | # 11 | # All configuration values have a default; values that are commented out 12 | # serve to show the default. 13 | 14 | import sys, os 15 | 16 | # If extensions (or modules to document with autodoc) are in another directory, 17 | # add these directories to sys.path here. If the directory is relative to the 18 | # documentation root, use os.path.abspath to make it absolute, like shown here. 19 | #sys.path.insert(0, os.path.abspath('.')) 20 | sys.path.insert(0, os.path.abspath('.')) 21 | extensions = ['japanesesupport', 'ext', 'その他の拡張'] 22 | # -- General configuration ----------------------------------------------------- 23 | 24 | # If your documentation needs a minimal Sphinx version, state it here. 25 | #needs_sphinx = '1.0' 26 | 27 | # Add any Sphinx extension module names here, as strings. They can be extensions 28 | # coming with Sphinx (named 'sphinx.ext.*') or your custom ones. 29 | extensions = ['sphinx.ext.autodoc', 'sphinx.ext.doctest', 'sphinx.ext.todo', 'sphinx.ext.mathjax', 'sphinx.ext.graphviz', 'sphinxcontrib.autorun'] 30 | 31 | autorun_languages = {} 32 | autorun_languages['gnuplot'] = 'gnuplot' 33 | autorun_languages['bash'] = "ext/citty/src/citty -f3 bash -i" 34 | autorun_languages['bash_input_encoding'] = 'utf-8' 35 | autorun_languages['bash_output_encoding'] = 'utf-8' 36 | autorun_languages['bash_prefix_chars'] = 0 37 | autorun_languages['bash_show_source'] = False 38 | 39 | #autorun_languages['iex'] = "ext/citty/src/citty -b3 -f3 iex -e citty.exs" 40 | autorun_languages['iex'] = "ext/citty/src/citty -b3 -f3 iex -r mm.exs" 41 | autorun_languages['iex_input_encoding'] = 'utf-8' 42 | autorun_languages['iex_output_encoding'] = 'utf-8' 43 | autorun_languages['iex_prefix_chars'] = 0 44 | autorun_languages['iex_show_source'] = False 45 | 46 | 47 | # Add any paths that contain templates here, relative to this directory. 48 | templates_path = ['_templates'] 49 | 50 | # The suffix of source filenames. 51 | source_suffix = '.rst' 52 | 53 | # The encoding of source files. 54 | #source_encoding = 'utf-8-sig' 55 | source_encoding = 'utf-8-sig' 56 | 57 | # The master toctree document. 58 | master_doc = 'index' 59 | 60 | # General information about the project. 61 | project = u'elixi primer' 62 | copyright = u'2013, @k1complete' 63 | 64 | # The version info for the project you're documenting, acts as replacement for 65 | # |version| and |release|, also used in various other places throughout the 66 | # built documents. 67 | # 68 | # The short X.Y version. 69 | version = '0.1.0.13.3' 70 | # The full version, including alpha/beta/rc tags. 71 | release = '0.1.0.13.3-alpha' 72 | 73 | # The language for content autogenerated by Sphinx. Refer to documentation 74 | # for a list of supported languages. 75 | #language = None 76 | 77 | # There are two options for replacing |today|: either, you set today to some 78 | # non-false value, then it is used: 79 | #today = '' 80 | # Else, today_fmt is used as the format for a strftime call. 81 | #today_fmt = '%B %d, %Y' 82 | 83 | # List of patterns, relative to source directory, that match files and 84 | # directories to ignore when looking for source files. 85 | exclude_patterns = [] 86 | 87 | # The reST default role (used for this markup: `text`) to use for all documents. 88 | #default_role = None 89 | 90 | # If true, '()' will be appended to :func: etc. cross-reference text. 91 | #add_function_parentheses = True 92 | 93 | # If true, the current module name will be prepended to all description 94 | # unit titles (such as .. function::). 95 | #add_module_names = True 96 | 97 | # If true, sectionauthor and moduleauthor directives will be shown in the 98 | # output. They are ignored by default. 99 | #show_authors = False 100 | 101 | # The name of the Pygments (syntax highlighting) style to use. 102 | pygments_style = 'sphinx' 103 | 104 | # A list of ignored prefixes for module index sorting. 105 | #modindex_common_prefix = [] 106 | 107 | # If true, keep warnings as "system message" paragraphs in the built documents. 108 | #keep_warnings = False 109 | 110 | 111 | # -- Options for HTML output --------------------------------------------------- 112 | 113 | # The theme to use for HTML and HTML Help pages. See the documentation for 114 | # a list of builtin themes. 115 | html_theme = 'default' 116 | 117 | # Theme options are theme-specific and customize the look and feel of a theme 118 | # further. For a list of options available for each theme, see the 119 | # documentation. 120 | #html_theme_options = {} 121 | 122 | # Add any paths that contain custom themes here, relative to this directory. 123 | #html_theme_path = [] 124 | 125 | # The name for this set of Sphinx documents. If None, it defaults to 126 | # " v documentation". 127 | #html_title = None 128 | 129 | # A shorter title for the navigation bar. Default is the same as html_title. 130 | #html_short_title = None 131 | 132 | # The name of an image file (relative to this directory) to place at the top 133 | # of the sidebar. 134 | #html_logo = None 135 | 136 | # The name of an image file (within the static path) to use as favicon of the 137 | # docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32 138 | # pixels large. 139 | #html_favicon = None 140 | 141 | # Add any paths that contain custom static files (such as style sheets) here, 142 | # relative to this directory. They are copied after the builtin static files, 143 | # so a file named "default.css" will overwrite the builtin "default.css". 144 | html_static_path = ['_static'] 145 | 146 | # If not '', a 'Last updated on:' timestamp is inserted at every page bottom, 147 | # using the given strftime format. 148 | #html_last_updated_fmt = '%b %d, %Y' 149 | 150 | # If true, SmartyPants will be used to convert quotes and dashes to 151 | # typographically correct entities. 152 | #html_use_smartypants = True 153 | 154 | # Custom sidebar templates, maps document names to template names. 155 | #html_sidebars = {} 156 | 157 | # Additional templates that should be rendered to pages, maps page names to 158 | # template names. 159 | #html_additional_pages = {} 160 | 161 | # If false, no module index is generated. 162 | #html_domain_indices = True 163 | 164 | # If false, no index is generated. 165 | #html_use_index = True 166 | 167 | # If true, the index is split into individual pages for each letter. 168 | #html_split_index = False 169 | 170 | # If true, links to the reST sources are added to the pages. 171 | #html_show_sourcelink = True 172 | 173 | # If true, "Created using Sphinx" is shown in the HTML footer. Default is True. 174 | #html_show_sphinx = True 175 | 176 | # If true, "(C) Copyright ..." is shown in the HTML footer. Default is True. 177 | #html_show_copyright = True 178 | 179 | # If true, an OpenSearch description file will be output, and all pages will 180 | # contain a tag referring to it. The value of this option must be the 181 | # base URL from which the finished HTML is served. 182 | #html_use_opensearch = '' 183 | 184 | # This is the file name suffix for HTML files (e.g. ".xhtml"). 185 | #html_file_suffix = None 186 | 187 | # Output file base name for HTML help builder. 188 | htmlhelp_basename = 'elixiprimerdoc' 189 | 190 | 191 | # -- Options for LaTeX output -------------------------------------------------- 192 | 193 | latex_elements = { 194 | # The paper size ('letterpaper' or 'a4paper'). 195 | #'papersize': 'letterpaper', 196 | 197 | # The font size ('10pt', '11pt' or '12pt'). 198 | #'pointsize': '10pt', 199 | 200 | # Additional stuff for the LaTeX preamble. 201 | #'preamble': '', 202 | } 203 | 204 | # Grouping the document tree into LaTeX files. List of tuples 205 | # (source start file, target name, title, author, documentclass [howto/manual]). 206 | latex_documents = [ 207 | ('index', 'elixiprimer.tex', u'elixi primer Documentation', 208 | u'@k1complete', 'manual'), 209 | ] 210 | 211 | # The name of an image file (relative to this directory) to place at the top of 212 | # the title page. 213 | #latex_logo = None 214 | 215 | # For "manual" documents, if this is true, then toplevel headings are parts, 216 | # not chapters. 217 | #latex_use_parts = False 218 | 219 | # If true, show page references after internal links. 220 | #latex_show_pagerefs = False 221 | 222 | # If true, show URL addresses after external links. 223 | #latex_show_urls = False 224 | 225 | # Documents to append as an appendix to all manuals. 226 | #latex_appendices = [] 227 | 228 | # If false, no module index is generated. 229 | #latex_domain_indices = True 230 | 231 | 232 | # -- Options for manual page output -------------------------------------------- 233 | 234 | # One entry per manual page. List of tuples 235 | # (source start file, name, description, authors, manual section). 236 | man_pages = [ 237 | ('index', 'elixiprimer', u'elixi primer Documentation', 238 | [u'@k1complete'], 1) 239 | ] 240 | 241 | # If true, show URL addresses after external links. 242 | #man_show_urls = False 243 | 244 | 245 | # -- Options for Texinfo output ------------------------------------------------ 246 | 247 | # Grouping the document tree into Texinfo files. List of tuples 248 | # (source start file, target name, title, author, 249 | # dir menu entry, description, category) 250 | texinfo_documents = [ 251 | ('index', 'elixiprimer', u'elixi primer Documentation', 252 | u'@k1complete', 'elixiprimer', 'One line description of project.', 253 | 'Miscellaneous'), 254 | ] 255 | 256 | # Documents to append as an appendix to all manuals. 257 | #texinfo_appendices = [] 258 | 259 | # If false, no module index is generated. 260 | #texinfo_domain_indices = True 261 | 262 | # How to display URL addresses: 'footnote', 'no', or 'inline'. 263 | #texinfo_show_urls = 'footnote' 264 | 265 | # If true, do not generate a @detailmenu in the "Top" node's menu. 266 | #texinfo_no_detailmenu = False 267 | 268 | 269 | # -- Options for Epub output --------------------------------------------------- 270 | 271 | # Bibliographic Dublin Core info. 272 | epub_title = u'elixi primer' 273 | epub_author = u'@k1complete' 274 | epub_publisher = u'@k1complete' 275 | epub_copyright = u'2013, @k1complete' 276 | 277 | # The language of the text. It defaults to the language option 278 | # or en if the language is not set. 279 | #epub_language = '' 280 | 281 | # The scheme of the identifier. Typical schemes are ISBN or URL. 282 | #epub_scheme = '' 283 | 284 | # The unique identifier of the text. This can be a ISBN number 285 | # or the project homepage. 286 | #epub_identifier = '' 287 | 288 | # A unique identification for the text. 289 | #epub_uid = '' 290 | 291 | # A tuple containing the cover image and cover page html template filenames. 292 | #epub_cover = () 293 | 294 | # A sequence of (type, uri, title) tuples for the guide element of content.opf. 295 | #epub_guide = () 296 | 297 | # HTML files that should be inserted before the pages created by sphinx. 298 | # The format is a list of tuples containing the path and title. 299 | #epub_pre_files = [] 300 | 301 | # HTML files shat should be inserted after the pages created by sphinx. 302 | # The format is a list of tuples containing the path and title. 303 | #epub_post_files = [] 304 | 305 | # A list of files that should not be packed into the epub file. 306 | #epub_exclude_files = [] 307 | 308 | # The depth of the table of contents in toc.ncx. 309 | #epub_tocdepth = 3 310 | 311 | # Allow duplicate toc entries. 312 | #epub_tocdup = True 313 | 314 | # Fix unsupported image types using the PIL. 315 | #epub_fix_images = False 316 | 317 | # Scale large images. 318 | #epub_max_image_width = 0 319 | 320 | # If 'no', URL addresses will not be shown. 321 | #epub_show_urls = 'inline' 322 | 323 | # If false, no index is generated. 324 | #epub_use_index = True 325 | -------------------------------------------------------------------------------- /source/index.rst: -------------------------------------------------------------------------------- 1 | .. elixi primer documentation master file, created by 2 | sphinx-quickstart on Sat Jun 29 10:39:51 2013. 3 | You can adapt this file completely to your liking, but it should at least 4 | contain the root `toctree` directive. 5 | 6 | Elixir Primer 7 | ======================================== 8 | 9 | 目次: 10 | 11 | .. toctree:: 12 | :maxdepth: 2 13 | 14 | introduction 15 | 16 | 17 | syntax 18 | map_and_struct 19 | record_and_protocol 20 | protocol_enumerable 21 | partial_application 22 | metaprogramming 23 | using_std_library 24 | using_exunit 25 | using_mix 26 | otp_programming 27 | 28 | 29 | .. Indices and tables 30 | 索引 31 | ================== 32 | 33 | * :ref:`genindex` 34 | * :ref:`modindex` 35 | * :ref:`search` 36 | 37 | -------------------------------------------------------------------------------- /source/introduction.rst: -------------------------------------------------------------------------------- 1 | 2 | ==================================== 3 | Elixirとは 4 | ==================================== 5 | 6 | erlang VM の上で動作する、関数型、メタプログラミング指向のプログラミン 7 | グ言語です。erlang上で動作する同様の言語としては、reia 8 | (http://reia-lang.org/) がありますが、elixirはreiaの後継になります。わ 9 | ざわざ、erlangという、高信頼並列プログラミング言語の上で動作するだけあっ 10 | て、それなりの特徴があります。 11 | 12 | 近代的なシンタックス 13 | 14 | ruby風味なので、Prologチックなerlangに比べて取っ付きやすくなっていま 15 | す。 16 | 17 | 全てが式 18 | 19 | モジュール定義や関数定義、各種ディレクティブなど全てが式です。 20 | 21 | 強力なメタプログラミング機能 22 | 23 | homoiconic 構文を持つため、elixriプログラムはelixirのデータ構造として 24 | 表現されます。lispのような強力なマクロ機構により、コンパイル後の構文 25 | 木をコード生成の前にプログラムからいじることができます。ここがerlang 26 | はじめ他の関数型言語と一線を画するところです。 27 | 28 | 第一級オブジェクトしてのドキュメント 29 | 30 | elixirではドキュメントがファーストクラスオブジェクトして取り扱うこと 31 | ができます。従って、ソースコード上にコメントを書く必要が著しく低減さ 32 | れています。ドキュメントは動的に追加、削除でき、iexのようなシェルから 33 | 参照できます。 34 | 35 | erlang/OTPランタイムとの相互運用 36 | 37 | erlang/OTPの膨大なライブラリ資産をそのまま呼び出すことができます。も 38 | ちろんelixirで記述したモジュールをerlangから呼び出すこともできます。 39 | Java VM上で動作するscalaがjavaのクラスライブラリを呼び出すことができ 40 | るのと似ています。 41 | 42 | ひとことでまとめると、erlangの並列/高信頼フレームワークが利用できる 43 | rubyライクの構文を持つlispです。 44 | 45 | ビルドとインストール 46 | -------------------- 47 | 48 | elixirはerlang/OTPのバージョン17かそれ以降が必要ですので、 49 | www.erlang.orgからダウンロードしてインストールしておきます。erlang/OTP 50 | のインストール後、elixirをビルド・インストールします。elixirは、 51 | https://github.com/josevalim/elixir から入手できます。2014年10月時点の最 52 | 新版は1.0.1で2011年12月にリリースされた0.4.0から強力なマクロを備えた言 53 | 語に生まれ変わりました。それ以前のelixirはreiaと同様にerlang上で動作す 54 | るruby類似のオブジェクト指向言語でした。 55 | 56 | .. code-block:: bash 57 | 58 | $ elixir --version 59 | 60 | 61 | インストールはスーパーユーザになりmake install後、パスを通します。 62 | 63 | .. code-block:: bash 64 | :linenos: 65 | 66 | $ sudo make install 67 | 68 | Hello, world. 69 | ------------- 70 | 71 | elixirのプログラムの構造は以下のとおりです。 72 | 73 | .. code-block:: elixir 74 | :linenos: 75 | 76 | defmodule ModuleName do 77 | def MethodName(arg1, arg2,...) do 78 | body 79 | end 80 | def ShortMethod(arg1), do: body 81 | end 82 | ModuleName.MethodName(arg1, arg2,...) ## start point 83 | 84 | rubyなどを知っていれば受け入れやすい文法と構造になっています。では最初 85 | のプログラムを書いてみましょう。 86 | 87 | .. literalinclude:: ../codes/hello.exs 88 | :language: elixir 89 | :linenos: 90 | 91 | これをhello.exsとして保存し、elixirへ渡すと実行されます。 92 | 93 | .. runblock:: bash 94 | 95 | $ elixir hello.exs 96 | 97 | 98 | -------------------------------------------------------------------------------- /source/japanesesupport.py: -------------------------------------------------------------------------------- 1 | def trunc_whitespace(app, doctree, docname): 2 | from docutils.nodes import Text, paragraph 3 | if not app.config.japanesesupport_trunc_whitespace: 4 | return 5 | for node in doctree.traverse(Text): 6 | if isinstance(node.parent, paragraph): 7 | newtext = node.astext() 8 | for c in "\n\r\t": 9 | newtext = newtext.replace(c, "") 10 | newtext = newtext.strip() 11 | node.parent.replace(node, Text(newtext)) 12 | 13 | def setup(app): 14 | app.add_config_value('japanesesupport_trunc_whitespace', True, True) 15 | app.connect("doctree-resolved", trunc_whitespace) 16 | -------------------------------------------------------------------------------- /source/map_and_struct.rst: -------------------------------------------------------------------------------- 1 | ===================================== 2 | 複雑なデータ構造 3 | ===================================== 4 | 5 | elixirは情報を纏めるための構造をマップやタプル以外に幾つか提供していま 6 | す。この章では主な機能とサンプルを紹介します。 7 | 8 | 構造体 9 | -------------------------------------- 10 | 11 | マップに名前を付けて構造体を定義することができます。構造体は 12 | デフォルト値とコンパイル時の型を保証するマップの拡張です。 13 | 14 | .. runblock:: iex 15 | 16 | > person = %{name: 'curumi', age: 17} 17 | > defmodule Person do 18 | > defstruct name: 'unknown', age: 0 19 | > end 20 | > %Person{} 21 | > p = %Person{name: 'curumi', age: 17} 22 | > is_map(p) 23 | 24 | 構造体では、作成時に勝手にキーを追加することはできない 25 | ため、開発作業が捗りますが、無理やりMap.put/3でキーを追加すると 26 | 構造体として認識されず__struct__というキーが入ったマップとして 27 | 扱われます。 28 | 29 | .. runblock:: iex 30 | 31 | > person = %{name: 'curumi', age: 17} 32 | > defmodule Person do 33 | > defstruct name: 'unknown', age: 0 34 | > end 35 | > %Person{} 36 | > p = %Person{name: 'curumi', age: 17} 37 | > q = Map.put(p, :sex, :female) ## 無理やりputするとただのMapになる 38 | > p = %Person{name: 'curumi', age: 17, sex: :female} ## エラー 39 | > q = %{:name => 'curumi', :age => 17} 40 | > Person.__struct__ 41 | > struct(Person, q) ## 既存のマップから構造体を作成する 42 | > struct(Person, [name: 'curumi', age: 17]) ## キーワードリストから作成 43 | 44 | -------------------------------------------------------------------------------- /source/metaprogramming.rst: -------------------------------------------------------------------------------- 1 | ===================================== 2 | メタプログラミング 3 | ===================================== 4 | 5 | 6 | Elixirマクロ入門 7 | ------------------------------------- 8 | 9 | Elixirのマクロはコンパイルプロセス中において、構文解析後のツリーを入力 10 | として、別のツリーを返すフックとして機能します。そして、そのフックは 11 | Elixir自身を用いて記述することができます。この記述のしやすさと、Elixir 12 | のクロージャサポートによりLispなみの拡張性を持っています。 13 | 14 | .. image:: ../illustrations/diagram.png 15 | 16 | Elixirプログラムのデータ構造としてのツリー表現 17 | ---------------------------------------------- 18 | 19 | elixirはhomoiconic言語です。つまりプログラムをプログラム中でデータ構造 20 | として扱うことができるという事です。どんなelixirプログラムでもそれ自身 21 | のデータ構造を使用して表現することができます。このセクションは、そのよ 22 | うなデータ構造としてのelixir言語の仕様を記述します。elixirの 23 | homoiconicityの構築ブロックは3要素のタプルです。例えば: 24 | 25 | .. code-block:: elixir 26 | :linenos: 27 | 28 | { :sum, [], [1, 2, 3] } 29 | 30 | 上のタプルは1,2,3を引数にして関数sum/3の呼び出しを表現しています。 31 | このタプルの要そは以下のとおりです: 32 | 33 | .. code-block:: elixir 34 | :linenos: 35 | 36 | { Tuple | Atom, List, List | Atom } 37 | 38 | * タプルの最初の要素は、アトムあるいは他のタプル表現です。 39 | 40 | * タプルの第2の要素は、コンテキスト情報を表すリストです。 41 | 42 | * タプルの第3の要素は、関数呼び出しの引数です。第3引数は(nilあるい 43 | は:quoted)アトムである場合もあります。そして、それが関数呼び出しでは 44 | なく、変数である事を意味します。 45 | 46 | quote do: 式 マクロを用いて任意の式のデータ構造表現を得ることができます: 47 | 48 | .. literalinclude:: ../codes/quote_do_sum.lst 49 | :language: elixir 50 | :linenos: 51 | 52 | .. runblock:: iex 53 | 54 | > quote do: sum(1,2,3) 55 | > quote do 56 | > sum(1,2,3) 57 | > end 58 | 59 | 60 | elixirでは全ては関数呼び出しで、それは前述のタプルで表現できます。例えば、以下の様な演算子を含む式は以下の様になります。 61 | 62 | .. runblock:: iex 63 | 64 | > quote do: 1 + 2 65 | 66 | 3要素以上のタプルも"{}"関数になります。 67 | 68 | .. runblock:: iex 69 | 70 | > quote do: { 1, 2} 71 | > quote do: { 1, 2, 3} 72 | 73 | 74 | このルールの例外はたった五つのElixirリテラルだけです。リテラルはquoteさ 75 | れるとそれ自身を返すデータ型で、それらは以下のとおりです: 76 | 77 | .. runblock:: iex 78 | 79 | > quote do: :atom # atom 80 | > quote do: 2.0 # number 81 | > quote do: [1, 2, 3] # list 82 | > quote do: "binary" # binary 83 | > quote do: {:key, :value} # 2 element tuple 84 | 85 | また、変数は、Elixirという印がついたアトムのタプルになります。 86 | 87 | .. runblock:: iex 88 | 89 | > x=1 90 | > quote do: x 91 | 92 | doブロックは:__block__関数になります。 93 | 94 | .. runblock:: iex 95 | 96 | > quote do 97 | > 1 98 | > 2 99 | > end 100 | 101 | 102 | これでユーザ定義のマクロを定義する準備ができました。Doug HoyteはLet 103 | Over Lambdaで「他のすべての言語が単にLispに薄い皮をかぶせたにすぎないと 104 | いうことが分かるだろう」と書いています。その通りなのですが、他の言語と 105 | 違い、Elixirはいつでもその薄い皮を剥がすことができるということです。 106 | 107 | マクロ定義 108 | ---------------------------------------------- 109 | 110 | ユーザ定義のマクロを定義する 111 | `````````````````````````````````````````````` 112 | 113 | “defmacro”を使用してマクロを定義することができます。例えば、unlessと 114 | 呼ばれるマクロを定義することができます。それはちょっとしたコードでちょ 115 | うどRubyのunlessと同じように働きます。 116 | 117 | .. literalinclude:: ../codes/defmacro_unless.exs 118 | :language: elixir 119 | :linenos: 120 | :lines: 1-7 121 | 122 | 上の例では、unlessは二つの引数を受けて呼ばれます。 123 | “clause”と”options”です。しかし、unlessはそれらの値を受け取る訳では 124 | なく、式を受け取る点に注意してください。例えば、次の呼び出しでは、 125 | 2 + 2 == 5 という式が評価されずに渡されています。 126 | 127 | .. runblock:: iex 128 | 129 | > c("codes/defmacro_unless.exs") 130 | > require MyMacro 131 | > MyMacro.unless 2 + 2 == 5, do: IO.puts("unless") 132 | > IO.puts Macro.to_string Macro.expand_once(quote do 133 | > MyMacro.unless 2 + 2 == 5, do: IO.puts("unless") 134 | > end, __ENV__) 135 | 136 | MyMacro.unless側では、ifのツリー構造を返す為に"quote"を呼びます。 137 | これは"if"で我々の"unless"をトランスレートしていることを意味します。 138 | しかしながら、開発者が通常"quote"された式の要素を"unquote"し忘れるのは 139 | 共通のミスです。"unquote"が何をするかを理解するために取り除いてみましょう。 140 | 141 | .. literalinclude:: ../codes/defmacro_unless_fail.exs 142 | :language: elixir 143 | :linenos: 144 | :lines: 1-7 145 | 146 | これをコンパイルして呼び出すとこのようになります。 147 | 148 | .. runblock:: iex 149 | 150 | > c("codes/defmacro_unless_fail.exs") 151 | > require UnlessFail; 152 | > IO.puts Macro.to_string Macro.expand_once(quote do 153 | > UnlessFail.unless 2 + 2 == 5, do: IO.puts("unless") 154 | > end, __ENV__) 155 | 156 | unquoteが無いバージョンではclauseとoptionsという関数を呼び出すようになっ 157 | ていることに注意してください。 158 | 言い替えると、"unquote"は"quote"されたツリーに式を組込むメカニズムで、 159 | メタプログラミングメカニズムの本質です。 160 | 161 | elixiではリストをunquoteして、もとの式のリスト中に差し込むことを一度にする 162 | unquote_splicing/1も提供しています。 163 | 164 | .. runblock:: iex 165 | 166 | > quote do: [1, unquote_splicing([2,3,4]), 5] 167 | 168 | elixirで提供されているビルトインマクロのオーバーライドを含めて、欲しい 169 | と思う任意のマクロを定義することができます。elixirスペシャルフォームの 170 | オーバーライドができないと言う事だけが例外です。Kernel.SpecialFormsにそ 171 | の例外となるスペシャルフォームがリストされています。 172 | 173 | 健全なマクロ 174 | `````````````````````````````````````````````` 175 | 176 | elixirマクロはScheme協定に従っていて、健全(hygienic)です。これはマクロ 177 | の内側で定義された変数はマクロが使われたコンテキストで定義された変数と 178 | 衝突しないという事を意味します。例えば 179 | 180 | .. runblock:: iex 181 | 182 | > defmodule Hygiene do 183 | > defmacro testmacro do 184 | > quote do: a = 1 185 | > end 186 | > end 187 | > a = 10 188 | > require Hygiene; Hygiene.testmacro 189 | > a ## マクロによって変更されない 190 | 191 | 192 | このように、testmacroの内部でaに1を束縛しても、それは外部に影響を及ぼし 193 | ません。マクロでコンテキストに影響を与えたい場合は、 var!()を使うことが 194 | できます: 195 | 196 | .. runblock:: iex 197 | 198 | > defmodule Hygiene2 do 199 | > defmacro testmacro do 200 | > quote do: var!(a) = 1 201 | > end 202 | > end 203 | > a = 10 204 | > require Hygiene2; Hygiene2.testmacro 205 | > a ## 今度は変更される 206 | 207 | var!()によってマクロが展開された場所のコンテキストで変数が 208 | 評価されることが分ります。 209 | 210 | マクロの展開過程を確認するために、Macro.expand/2, Macro.expand_once/2が 211 | あります。Macro.expand/2はマクロを全て展開してしまうため却って分かり難く 212 | なります。これらがASTを返しますが、これらをelixirのシンタックスに 213 | 文字列として変換する、Macro.to_string/1もあります。 214 | 215 | .. runblock:: iex 216 | 217 | > require MyMacro; 218 | > MyMacro.unless 2 + 2 == 5, do: IO.puts("unless") 219 | > m = Macro.expand_once(quote do 220 | > MyMacro.unless 2 + 2 == 5, do: IO.puts("unless") 221 | > end, __ENV__) 222 | > IO.puts Macro.to_string(m) 223 | > m = Macro.expand(quote do 224 | > MyMacro.unless 2 + 2 == 5, do: IO.puts("unless") 225 | > end, __ENV__) 226 | > IO.puts Macro.to_string(m) 227 | 228 | 229 | これまでquoteを使ってきましたが、直接ASTを構成するタプルを返して 230 | マクロを作ることもできます。たとえば、引数を2倍するマクロを作ってみます。 231 | :"+" 関数に引数を渡すplus/1マクロを書いてみます。 232 | 233 | .. runblock:: iex 234 | 235 | > defmodule Plus do 236 | > defmacro plus(x) do 237 | > {:"+", [], [x, x]} 238 | > end 239 | > end 240 | > require Plus 241 | > Plus.plus(4) 242 | > IO.puts Macro.to_string(Macro.expand(quote do 243 | > Plus.plus(4) 244 | > end, __ENV__)) 245 | 246 | 一見上手く動いているように見えますが、微妙なバグがあります。 247 | 248 | quoteを使っていないので、unquoteも使う必要はありません。このような単純 249 | な場合にはquoteを使うほうが遥かに楽ですが、複雑な式の変換を行う際には 250 | 直接ASTをハンドルする必要が出て来ます。 251 | 252 | 253 | プライベートマクロ 254 | `````````````````````````````````````````````` 255 | あるモジュールで定義されたマクロはそのモジュールの中では呼び出すことは 256 | 出来ません。defmacropで定義されたプライベートマクロは逆でモジュール 257 | 内でのみ呼び出しが可能です。プライベートマクロはガード式など 258 | 関数呼びだしが許されない場所で良く使われます。 259 | 260 | .. runblock:: iex 261 | 262 | > defmodule IsEven do 263 | > defmacrop is_even(x) do 264 | > quote do 265 | > rem(unquote(x), 2) == 0 266 | > end 267 | > end 268 | > def add_even(a, b) when is_even(a) and is_even(b) do 269 | > a + b 270 | > end 271 | > end 272 | 273 | プライベートマクロは前方参照を許していませんので、定義するまえに使うと 274 | エラーとなります。 275 | 276 | .. runblock:: iex 277 | 278 | > defmodule IsEven do 279 | > def add_even(a, b) when is_even(a) and is_even(b) do 280 | > a + b 281 | > end 282 | > defmacrop is_even(x) do 283 | > quote do 284 | > rem(unquote(x), 2) == 0 285 | > end 286 | > end 287 | > end 288 | 289 | 290 | マクロの実際 291 | ------------------------------------- 292 | 293 | マクロ delegate [{name, arity} | t], do: target を考えてみます。これは、 294 | あるモジュールの関数群を他のモジュールに委譲したい場合に使う事を目的と 295 | しています。例えば、MyListという独自リストモジュールを定義していて 296 | reverse/1とmember/2をEnumモジュールをそのまま使いたい場合です。 297 | 298 | .. code-block:: elixir 299 | :linenos: 300 | 301 | defmodule MyList do 302 | delegate [reverse: 1, member: 2], to: Enum 303 | end 304 | 305 | これをこんなふうに展開されたいわけです。 306 | 307 | .. code-block:: elixir 308 | :linenos: 309 | 310 | defmodule MyList do 311 | ## delegate [reverse: 1, member: 2], to: :lists 312 | def reverse(arg1) do 313 | apply :lists, reverse, [arg1] 314 | end 315 | def member(arg1, arg2) do 316 | apply :lists, member, [arg1, arg2] 317 | end 318 | end 319 | 320 | ではdelegateマクロを実装していきましょう。 321 | コアはこんな感じです。 322 | 323 | 324 | .. code-block:: elixir 325 | :linenos: 326 | 327 | defmodule MyMacro do 328 | defmacro delegate1([{fname, arity}| t], to: module) do 329 | args = makeargs(arity) 330 | quote do 331 | def unquote(fname).(unquote_splicing(args)) do 332 | apply unquote(module), unquote(fname), [unquote_splicing(args)] 333 | end 334 | end 335 | end 336 | end 337 | 338 | makeargs/1は指定された数だけの仮引数として使用できるアトムリストを返す 339 | 関数であり、このように作ることができます。 340 | 341 | .. literalinclude:: ../codes/delegate.exs 342 | :language: elixir 343 | :linenos: 344 | :lines: 2-8 345 | 346 | delegate1は渡された最初の{fname, arity}のみ処理しているので、残りの部分 347 | を処理するよう書き換えます。 348 | 349 | .. literalinclude:: ../codes/delegate.exs 350 | :language: elixir 351 | :linenos: 352 | :lines: 9-23 353 | 354 | このようにマクロのなかから関数を呼ぶことが出来ますが、マクロが自分自身 355 | を呼び出すことは出来ません。 356 | 末尾再帰の形をEnum.map/2で書き直すと以下のようになり、幾分すっきりします。 357 | 358 | .. literalinclude:: ../codes/delegate.exs 359 | :language: elixir 360 | :linenos: 361 | :lines: 24-34 362 | 363 | 実行結果は以下のとおりです。 364 | 365 | .. runblock:: iex 366 | 367 | > c("codes/delegate.exs") 368 | > MyList.member?([1,2,3], 3) 369 | > MyList.reverse([1,2,3]) 370 | -------------------------------------------------------------------------------- /source/partial_application.rst: -------------------------------------------------------------------------------- 1 | ===================================== 2 | 部分適用と遅延評価 3 | ===================================== 4 | 5 | 部分適用 6 | ------------------------------------- 7 | 8 | elixirは関数を便利に使うための構文をサポートしています。バイナリのリス 9 | トを持っていて、それぞれのサイズを計算したいとします。そのとき、通常は 10 | 以下のように書きます。 11 | 12 | .. runblock:: iex 13 | 14 | > list = ["foo", "bar", "baz"] 15 | > Enum.map list, fn(x) -> byte_size(x) end 16 | 17 | 18 | このようにも書くことができます。 19 | 20 | .. runblock:: iex 21 | 22 | > list = ["foo", "bar", "baz"] 23 | > Enum.map list, &byte_size(&1) 24 | 25 | 26 | 上の例の&size(&1)はfn(x) -> size(x) endに直接変換されます。演算子もまた 27 | 関数呼び出しですので、同じシンタックスを使うことができます。 28 | 29 | .. runblock:: iex 30 | 31 | > Enum.reduce [1,2,3], 1, &(&1 * &2) 32 | 33 | 34 | このケースでは、&(&1 * &2) はその順番の引数として自動生成された関数にマッピ 35 | ングされます。つまりは fn(x1, x2) -> x1 * x2 end と同じです。 36 | 37 | この部分適用シンタックスはElixirではSpecialform以外の任意の関数、マクロ、 38 | 演算子で使用することができます。 39 | 40 | 41 | 42 | パイプライン 43 | ------------------------------------- 44 | 45 | パイプライン演算子|>を使ってさらに部分適用を便利に使うことができます。 46 | リストを平準化(List.flatten)して、各要素を2倍する(Enum.map(&(&1 * 2)))し 47 | たい場合は以下のように書くことができます。 48 | 49 | 50 | .. runblock:: iex 51 | 52 | > [1, [2], 3] |> List.flatten |> Enum.map(&(&1 * 2)) 53 | 54 | 55 | 左辺 |> 右辺は、コンパイル時に右辺(左辺,右辺の引数の残り)のように変換さ 56 | れます。また左結合性ですので、上記は以下と等価です。 57 | 58 | 59 | .. runblock:: iex 60 | 61 | > Enum.map(List.flatten([1, [2], 3]), &(&1 * 2)) 62 | 63 | 64 | 遅延評価 65 | ------------------------------------- 66 | 67 | StreamモジュールはEnumerableを引数にしてStream.Lazy遅延評価レコードを返 68 | します。Stream.Lazyレコードに対してEnumerableプロトコルが実装されていま 69 | すので任意のEnumモジュールの関数を使うことができます。Streamと|>演算子 70 | の相性は最高で、unixのパイプ演算子と同じように使うことができます。 71 | 72 | Enumモジュールによる|>演算子は所詮は関数の呼出でしたので、内側の関数が 73 | 一旦完全なEnumオブジェクトを返してから、それを引数にして外側の関数が呼 74 | ばれていました。 75 | 76 | .. literalinclude:: ../codes/enum_map_take_map.lst 77 | :language: elixir 78 | :linenos: 79 | 80 | .. runblock:: iex 81 | 82 | > Enum.map([1,2,3,4,5], 83 | > fn(x) -> IO.puts("step1 #{x}+1"); x + 1 end) |> 84 | > Enum.take(3) |> 85 | > Enum.map fn(x) -> IO.puts("step3 #{x} + 1"); x + 1 end 86 | 87 | 88 | Enum.mapを使ったパイプラインでは、step1が5回出力されてからstep3が3回出 89 | 力されていることから、中間のオブジェクトが作成されていることがわかりま 90 | す。 91 | 92 | Streamではアクセスされた場合に計算される関数を登録したStream.Lazyオブジェ 93 | クトが返り、次の関数に渡され、最終的にEnum.to_list/1などでアクセスした 94 | 場合に実際の処理が行なわれます。 95 | 96 | 97 | .. runblock:: iex 98 | 99 | > Stream.map([1,2,3,4,5], 100 | > fn(x) -> IO.puts("step1 #{x}+1"); x + 1 end) |> 101 | > Stream.take(3) |> 102 | > Stream.map(fn(x) -> IO.puts("step3 #{x} + 1"); x + 1 end) |> 103 | > Enum.to_list 104 | 105 | 106 | 107 | Enum.mapに比べてstep1での余分なリストへの処理がされていないことに 108 | 注意してください。 109 | これを一ステップづつ行ってみます。 110 | 111 | .. runblock:: iex 112 | 113 | > m = Stream.map([1,2,3,4,5], 114 | > fn(x) -> IO.puts("step1 #{x}+1"); x + 1 end) 115 | > m2 = Stream.take(m, 3) 116 | > m3 = Stream.map(m2, fn(x) -> IO.puts("step3 #{x} + 1"); x + 1 end) 117 | > m3 |> Enum.to_list 118 | 119 | Stream.Lazyレコードがネストしているさまがわかります。最後に 120 | Enum.to_listするまで、IO.putsが呼ばれていないことから、遅延評価されてい 121 | ることもわかります。 122 | 123 | 124 | -------------------------------------------------------------------------------- /source/protocol_enumerable.rst: -------------------------------------------------------------------------------- 1 | ===================================== 2 | 重要なプロトコル 3 | ===================================== 4 | 5 | elixirでは標準でいくつかのプロトコルを提供しています。 6 | ここでは、それらのプロトコルの使いかたを説明します。 7 | 8 | Enumerable 9 | ------------------------------------- 10 | 11 | Enumerableとは、「数え上げることができる」という意味で、主にEnum、 12 | StreamモジュールがEnumerableを対象とした操作を行っています。 13 | 14 | Enumerableが実装を要求する関数は、count/1, member?/2, reduce/3の3個で、 15 | それらを実装したモジュールはEnumerableになり、Enum, Streamモジュール 16 | の恩恵をうけることができます。 17 | 18 | Rangeに習って、フィボナッチ数を生成するモジュールFibを作りながら 19 | Enumerableを学んでいきます。 20 | 21 | まず、構造体と初期化子を作ります。これはプロトコルでは要請されて 22 | いません。デフォルトでは無限に生成するようcountは:infinityに 23 | してみます。 24 | 25 | .. literalinclude:: ../codes/protocol_fib.exs 26 | :language: elixir 27 | :linenos: 28 | :lines: 1-6 29 | 30 | 次に、Enumerableを実装していきます。以下の3つの関数の 31 | 実装が求められています。 32 | 33 | .. code-block:: elixir 34 | 35 | def count(collection) :: {:ok, non_neg_integer} | {:error, module} 36 | def member?(collection, value) :: {:ok, boolean} | {:error, module} 37 | def reduce(collection, acc, fun) :: {:done, term} | 38 | {:halted, term} | 39 | {:suspended, term, continuation} 40 | 41 | このうち、count/1, member?/2はデフォルトの実装が提供されていて、デフォ 42 | ルトの実装を使う場合、{:error, module}を返します。デフォルトの実装は、 43 | reduce/3を使い、線形時間がかかるので、データ構造上、それよりも高速に求 44 | められることがわかっている場合にのみ、カスタム実装を行います。 45 | 46 | 例えば、フィボナッチ数列のcountは、:infinityでない場合なら、 47 | 構造体のフィールドから直接求めることが可能です。:infinityの 48 | 場合はデフォルト実装にお任せします。 49 | 50 | .. code-block:: elixir 51 | 52 | def count(%Fib{count: :infinity}), do: {:error, __MODULE__} 53 | def count(fib), do: {:ok, fib.count} 54 | 55 | 56 | 一方、member?/2は、結局1つひとつ比較するしかないので、デフォルト 57 | 実装にお任せします。 58 | 59 | .. code-block:: elixir 60 | 61 | def member?(_fib, _value), do: {:error, __MODULE__} 62 | 63 | 残りはreduce/3ですが、アキュムレータにタグが付けられている 64 | ことに注意します。タグは以下のとおりです。 65 | 66 | * :cont - 数え上げを継続します。 {:cont, acc}か{:done, acc}を返します。 67 | * :halt - 直ちに数え上げを停止します。 {:halted, acc}を返します。 68 | * :suspend - 直ちに数え上げをサスペンドします。 69 | {:suspended, acc, 70 | fn(x) -> reduce(enum, x, fun) end}を返します。 71 | 72 | .. code-block:: elixir 73 | 74 | def reduce(e, acc, fun) do 75 | reduce(e.f0, e.f1, e.count, acc, fun) 76 | end 77 | def reduce(_f0, _f1, 0, {:cont, acc}, _fun) do 78 | {:done, acc} 79 | end 80 | def reduce(f0, f1, n, {:cont, acc}, fun) do 81 | reduce(f1, f0 + f1, n-1, fun.(f0, acc), fun) 82 | end 83 | def reduce(_, _, _, {:halt, acc}, _fun) do 84 | {:halted, acc} 85 | end 86 | def reduce(f0, f1, n, {:suspend, acc}, fun) do 87 | {:suspended, acc, &reduce(f0, f1, n, &1, fun)} 88 | end 89 | 90 | このように、reduceではフィボナッチ数を計算しながらカウントが 91 | 0になったら`{:done, acc}`を返すことになります。 92 | そしてナイスなことに、この状態でStreamにも対応出来ています。 93 | 94 | さて、使ってみましょう。お題として、10から100までのフィボナッチ数列の、 95 | 最初の二つを出力するというものにしてみます。範囲はRangeを使います。 96 | 97 | .. runblock:: iex 98 | 99 | > import_file ("codes/protocol_fib.exs") 100 | > Fib.new |> Stream.filter(&Enum.member?(10..100, &1)) |> 101 | > Stream.take(2) |> Enum.to_list 102 | 103 | Fib.newとして、無限数列としているにも拘わらず、きちんと計算されて 104 | いるのは、Streamのお陰です。Enumerableプロトコルを実装するだけで 105 | 遅延評価の恩恵を受けられるのは素晴しいことです。 106 | 107 | Collectable 108 | ------------------------------------- 109 | 110 | Collectableプロトコルは、「集めることができる」 111 | という意味のプロトコルで、Enumモジュールで実装され 112 | ています。集めたあと「数え上げることができる」ことは 113 | 要求していないので注意してください。 114 | 115 | Collectableが実装を要求する関数はinto/1で、 116 | それらを実装したモジュールはCollectableになり、Enumerableも 117 | 実装していると、Enumモジュールの恩恵を受けることができます。 118 | 119 | 発生したイベントをファイルへ書き込むCollectableである 120 | FileAppenderを作ってみましょう。構造体と初期化のための 121 | empty(path)を作ります。 122 | 123 | .. code-block:: elixir 124 | 125 | defmodule FileAppender do 126 | defstruct file: nil 127 | 128 | def empty(file) do 129 | File.rm(file) 130 | %FileAppender{file: file} 131 | end 132 | end 133 | 134 | 続いて、唯一の関数であるinto/1を実装します。 135 | 136 | .. code-block:: elixir 137 | 138 | defimpl Collectable, for: FileAppender do 139 | def into(collectable) do 140 | {collectable, 141 | fn 142 | fa, {:cont, term} -> 143 | File.write(fa.file, "#{inspect term}\n", [:append]) 144 | fa 145 | fa, :done -> fa 146 | _, :halt -> :ok 147 | end} 148 | end 149 | end 150 | 151 | さて、試してみましょう。 152 | 153 | .. runblock:: iex 154 | 155 | > import_file "codes/protocol_collectable.exs" 156 | > m = FileAppender.empty("test.log") 157 | > Enum.into([1,2,3], m) 158 | > File.read("test.log") 159 | > Enum.to_list(m) ## Enumerableプロトコルは実装していない 160 | 161 | このようにCollectableとEnumerableは密接に関係していますが、 162 | 別のものとして分離されています。 163 | なお、今回、FileAppenderを作成しましたが、File.stream!/3 164 | により生成されるFile.Streamを利用したほうが便利です。 165 | 166 | 167 | Access 168 | ------------------------------------- 169 | 170 | Accessプロトコルは、`[]` によるアクセスを可能にします。 171 | また、`.` によるアクセスも可能にします。 172 | 実装すべき関数は get/2 と、 get_and_update/3 です。 173 | 174 | 取り敢えず、Fibの属性を[]で取り出せるようにしてみます。 175 | 176 | .. literalinclude:: ../codes/protocol_access.exs 177 | :language: elixir 178 | :linenos: 179 | 180 | get/2は単に取得した値を返すので簡単ですが、 181 | get_and_update/3は、{取得した値, 更新後の構造体}を返します。 182 | 定義できたので使ってみましょう。 183 | 184 | .. runblock:: iex 185 | 186 | > import_file ("codes/protocol_fib.exs") 187 | > import_file ("codes/protocol_access.exs") 188 | > r = Fib.new 189 | > r[:f0] 190 | > get_and_update_in(r[:f0], &{&1, &1 + 1}) 191 | 192 | なお、わざわざ[]でのアクセスが出来るように実装しましたが、 193 | 構造体の場合、 `.` でも同様のことが出来ます。 194 | 195 | .. runblock:: iex 196 | 197 | > import_file ("codes/protocol_fib.exs") 198 | > r = Fib.new 199 | > r.f0 200 | > get_and_update_in(r.f0, &{&1, &1 + 1}) 201 | 202 | -------------------------------------------------------------------------------- /source/record_and_protocol.rst: -------------------------------------------------------------------------------- 1 | ===================================== 2 | プロトコル 3 | ===================================== 4 | 5 | elixirはプロトコルを提供します。この章では主な機能とサンプルを紹介しま 6 | す。defprotocolとdefimplの使い方を学びます。 7 | 8 | プロトコルは契約を定義します。それがプロトタイプを実装する限り、任意の 9 | データタイプが利用可能です。実際的な例を挙げてみましょう。 10 | 11 | 12 | Elixirではfalseとnilだけが偽の値であると考慮されています。それ以外の任 13 | 意の値は真と評価されます。アプリケーションに依存しますが、空白を指定す 14 | る事が重要である場合がある事から、データ型に対して空白かどうかをブーリ 15 | アンで返すblank?プロトコルを設計してみます。例えば、空のリストや空のバ 16 | イナリは空白であると考えることができます。 17 | 18 | プロトコルは以下のように定義できます。 19 | 20 | .. literalinclude:: ../codes/blank.ex 21 | :linenos: 22 | :end-before: implstart 23 | 24 | Blankプロトコルで、blank?/1関数をサポートする事を要求するものとなります。 25 | これの実装は、 26 | 27 | .. literalinclude:: ../codes/blank.ex 28 | :language: elixir 29 | :linenos: 30 | :start-after: implstart 31 | 32 | のように行います。使用例は、 33 | 34 | .. runblock:: iex 35 | 36 | > c("codes/blank.ex") 37 | > Blank.blank?([]) 38 | > Blank.blank?([1]) 39 | > Blank.blank?(1) # これはエラー 40 | 41 | のようになり、Listについてはblank?が機能していますが、blank?(1)は 42 | 怒られました。しかたないのでInteger型についても実装を定義してみます。 43 | 44 | .. runblock:: iex 45 | 46 | > defimpl Blank, for: Integer do 47 | > def blank?(_), do: true 48 | > end 49 | > Blank.blank?(0) 50 | > Blank.blank?(1) 51 | 52 | このように整数についてもblank?/1が機能するようになりました。:forに使え 53 | る型は以下のとおりです。 54 | 55 | 56 | • Tuple 57 | 58 | • Atom 59 | 60 | • List 61 | 62 | • BitString 63 | 64 | • Integer 65 | 66 | • Float 67 | 68 | • Function 69 | 70 | • PID 71 | 72 | • Port 73 | 74 | • Reference 75 | 76 | • Any 77 | 78 | 79 | デフォルトの実装を与えたい場合は、@fallback_to_anyにtrueをセットしAny型について実装しましょう。 80 | 81 | .. literalinclude:: ../codes/protocol_blank_any.lst 82 | :language: elixir 83 | :linenos: 84 | 85 | -------------------------------------------------------------------------------- /source/syntax.rst: -------------------------------------------------------------------------------- 1 | ===================================== 2 | 簡単な構文説明 3 | ===================================== 4 | 5 | データタイプ 6 | ------------------------------------- 7 | 8 | 基本データタイプ 9 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 10 | 11 | 基本データタイプは以下のとおりです。 12 | 13 | .. runblock:: iex 14 | 15 | > 1 # 整数 16 | > 0x10 # 16進数 17 | > 0b10 # 2進数 18 | > 1.0 # 実数 19 | > :atom # アトム 20 | > {1,2,3} # タプル 21 | > [1,2,3] # リスト 22 | > %{key1: 1, key2: 2} # マップ 23 | 24 | .. _関数: 25 | 26 | 関数 27 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 28 | 29 | 関数オブジェクト(無名関数)もありますが、変数に格納された関数を呼び出す 30 | ときには、変数と引数をドットで区切ります。無名関数の定義方法は、fn() 31 | -> body endになります。 32 | 33 | .. runblock:: iex 34 | 35 | > add = fn(a,b) -> a + b end # 無名関数をaddという名前の変数に束縛 36 | > add(1, 2) # addという名前の関数は存在しないのでエラー 37 | > add.(1, 2) # 変数addに束縛されている関数に引数を与えて実行 38 | 39 | 40 | 関数に渡す引数の数をアリティと呼びます。 41 | 42 | 関数は所属するモジュールやアリティが異なると全く違う関数として認識され 43 | ます。従って関数は、モジュール名.関数名/アリティのような書式で記述する 44 | 事で識別します。 45 | 46 | タプル 47 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 48 | 49 | タプルとは、項目の集まりを格納するために使う、複合的な型です。タプルは 50 | {}で囲み、個々の要素は任意の値をとることができ、カンマで区切ります。タ 51 | プルは複雑な構造を記述する際の中心となる構造です。タプルの最初の要素を 52 | そのタプルの内容を表すアトムにする方法はよくとられます。 53 | 54 | .. runblock:: iex 55 | 56 | > {:item1, :item2} 57 | > {} 58 | > a = {:uname, "netbsd", "i386", "smp"} 59 | > elem a, 1 60 | > put_elem a, 1, "freebsd" 61 | 62 | elem/2により内部の要素を取得できます。また、put_elem/3により一部の要素 63 | を変更した新しいタプルを作成することができます。要素の位置は0始まりです。 64 | 65 | 66 | リスト 67 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 68 | 69 | リストもタプルと同様に項目の集まりを格納するために使う、複合的な型です。 70 | リストは[]で囲み、個々の要素は任意の値をとることができ、カンマで区切り 71 | ます。タプルとは処理のされ方が違います。0要素のリストは[]で表すことがで 72 | きます。 [#nil_is_not_nul_list]_ 要素の数に意味がある時はタプルで、要素の 73 | 数が決められない場合にはリストを使います。タプルとリストを組み合わせる 74 | 事で任意のデータ構造を記述できます。 75 | 76 | キーワードリスト 77 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 78 | 79 | キーワードリストとはタプルのリストの一種で基本の型ではありませんが、 80 | 極めてよく登場します。タプルは2要素で最初の要素はアトムでなくては 81 | なりません。 82 | 83 | .. runblock:: iex 84 | 85 | > a = [{:a, 1}, {:b, 2}] 86 | > a[:a] 87 | > Keyword.put(a, :b, 3) 88 | 89 | 90 | マップ 91 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 92 | 93 | マップは他の言語ではハッシュと呼ばれることが多い型で、V0.13から導入され 94 | た新しい型です。 [#map_since_erlang_r17]_ マップの値の取り出しはブラケッ 95 | ト[]またはドット.で行い、値の設定はMap.put/3で行いますが、既存のキーに 96 | 対する更新については%{変数 | キー => 値}という記法も使えます。 97 | 98 | 現在のところはキーは任意の型が使えますが、%{}記法ではキーに変数を 99 | 使うことができません。キーに変数を使う場合にはMap.put/3を使います。 100 | 101 | .. runblock:: iex 102 | 103 | > a = %{:key1 => 1, :key2 => 2} 104 | > b = Map.put(a, :key3, 3) 105 | > %{a | :key2 => 5} # 既存のキーに対してカジュアルな変更が出来る 106 | > %{a | :key3 => 3} # 存在しないキーはエラーになる 107 | > a[:key1] # 取り出しは[]で可能 108 | > a.key1 # キーがアトムなら取り出しは.キーでも可能 109 | > c = "key4" 110 | > a = %{:key1 => 1, "key4" => 0} 111 | > %{a | c => 4} # 変数のキーはエラーになる 112 | > Map.put(a, c, 4) # Map.put/3を使えば変数のキーも大丈夫 113 | 114 | 115 | 116 | 二種類の文字列 117 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 118 | 119 | 二重引用符はUTF-8の文字列 [#erlang_binary]_ になります。単一引用符の文字列 120 | はunicode文字(ucs2)のリスト [#erlang_string]_ になり、両者は全く違います。 121 | :binary.bin_to_list/1 により文字列をリストに変換するとUTF-8のバイトのリストとな 122 | るため、違いが明らかになります。UTF-8のバイナリをunicode文字のリストに 123 | 変換するためには、List.from_char_data/1を使います。 124 | 125 | .. runblock:: iex 126 | 127 | > list='abc' 128 | > bin="abc" 129 | > [h|t]=list 130 | > t 131 | > h 132 | > list==bin 133 | > list2='あいうえお' 134 | > bin2="あいうえお" 135 | > :binary.bin_to_list(bin2) 136 | > List.from_char_data(bin2) 137 | 138 | 139 | これらのバイナリやリストの文字列を他の文字列に埋め込む事もできます。ど 140 | ちらのタイプかはis_binary/1やis_list/1を使用して調べることができます。 141 | 142 | .. runblock:: iex 143 | 144 | > bin="abc" 145 | > list='abc' 146 | > "embedd #{bin}" 147 | > 'embedd #{list}' 148 | > 'embedd binary into list #{bin}' 149 | > "embedd list into binary #{list}" 150 | > is_binary(bin) 151 | > is_binary(list) 152 | > is_list(bin) 153 | > is_list(list) 154 | 155 | 既に登場していますが、trueとfalseも存在します。is_boolean/1で判定できま 156 | す。 157 | 158 | 159 | 演算子 160 | ------------------------------------- 161 | 162 | 数値への演算子 163 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 164 | 165 | 数値に関しては、通常の四則演算子が利用できます。 166 | 167 | 168 | .. runblock:: iex 169 | 170 | > 1+2 171 | > 1-2 172 | > 1.0+1.0 173 | > 2*3 174 | > 12/4 175 | > 12/5 176 | > div(11,5) 177 | > rem(11,5) 178 | 179 | 180 | リスト演算子 181 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 182 | 183 | リストに対して、++と--が用意されていて、リストの結合と差分をとることができます。[#erlang_list_operation]_ 184 | 185 | .. runblock:: iex 186 | 187 | > [1,2,3] ++ [4,5,6] 188 | > [1,2,3] -- [2,3] 189 | > [1,2,3] -- [4] 190 | > [1,2,3] -- [3,1] 191 | 192 | 193 | バイナリ(文字列)演算子 194 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 195 | 196 | 単一引用符の文字列はリストなので、結合と差分をとることができますが、二重引用符の文字列(バイナリ)ではそんなことは出来ません。そのかわり'<> 197 | 'という結合演算子が使えます。 198 | 199 | .. runblock:: iex 200 | 201 | > "binary" ++ "bin" # '++'は使えない 202 | > "binary" <> "bin" 203 | 204 | .. _論理演算子: 205 | 206 | 論理演算子 207 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 208 | 209 | 論理演算子の or と and も提供しています。当然ですが、boolean型について 210 | のみ利用できます。その他の型についての論理演算子の使用はエラーになりま 211 | す。 212 | 213 | .. literalinclude:: ../codes/bool_operations.lst 214 | :language: elixir 215 | :linenos: 216 | 217 | .. runblock:: iex 218 | 219 | > true or false 220 | > false and is_binary("abc") 221 | > 1 and 2 # 整数型にはandは使えないのでエラー 222 | > 1 and false # andはショートカット演算子なのでこれもエラーとなる 223 | 224 | or や and はショートカット演算子ですので、全体を評価しなくても値が決ま 225 | る場合には、評価されないことがあります。[#erlang_andalso_orelse]_ 226 | 227 | .. runblock:: iex 228 | 229 | > true or error("This error will never be raised") 230 | > false and error("This error will never be raised") 231 | 232 | 233 | 比較演算子 234 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 235 | 236 | 通常の比較演算子==, !=, ===, !===, <=, >=, <, >も用意されています。==と 237 | ===は整数と浮動小数点数をより厳密に区別することが異なります。 238 | 239 | 240 | .. runblock:: iex 241 | 242 | > 1.0 == 1 # => true 243 | > 1.0 === 1 # => false 244 | 245 | 246 | 比較に関しては、異なる型でも順序関係が定義されています。 247 | 248 | .. runblock:: iex 249 | 250 | > 1 < :a < fn() -> :a end < {1,2} < 'abc' < "abc" 251 | 252 | 253 | リファレンス(一意のシンボル)やポート(elixirと外部プログラムのインタフェー 254 | ス)、pid(elixirプロセスの識別子)を含めてすべての型の順序は以下のとおり 255 | です。 256 | 257 | .. code-block:: elixir 258 | :linenos: 259 | 260 | number < atom < reference < functions < port < pid < tuple < list < bit string 261 | 262 | 263 | もう一つの論理演算子(|| , &&, !) 264 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 265 | 266 | :ref:`論理演算子` で説明した or, and, not は引数がbool型である必要があ 267 | りました。その制限を外して任意の型の引数が使用できる同様の論理演算子 268 | || , &&, ! を用意しています。それらの演算子は falseとnil以外のすべての 269 | 値をtrueに評価します。 270 | 271 | .. runblock:: iex 272 | 273 | > 0 || 1 274 | > nil || 1 275 | > false || 1 276 | > 0 && 1 277 | > 2 && 1 278 | > 2 && nil 279 | > 2 && false 280 | 281 | 282 | cons演算子 283 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 284 | 285 | cons("|")は二つの値からリストを作成する(constructor)演算子です。通常は 286 | 287 | .. runblock:: iex 288 | 289 | > newlist = [:a | [:b, :c]] 290 | 291 | のように使います。 292 | 293 | in演算子 294 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 295 | 296 | ある値がリストに含まれているかどうかを検査するための演算子がinです。同 297 | じ事は Enum.any?/2 などを使用すれば記述できますが、こちらの方がすっき 298 | りと記述することができます。 299 | 300 | .. runblock:: iex 301 | 302 | > y = 3 303 | > y in [1,2,3] 304 | > Enum.any?([1,2,3], fn(x) -> x == y end) 305 | 306 | 307 | 関数呼び出し 308 | ------------------------------------- 309 | 310 | 関数は引数の数(アリティ)で区別されています。アリティの異なる関数はまっ 311 | たく別の関数として扱われます。関数を呼び出すための括弧は省略できます。 312 | 313 | elixirでは入出力や基本的なデータタイプを操作するための小さな標準ライブ 314 | ラリを用意しています。これはつまり、複雑なアプリケーションを開発するた 315 | めにはErlangのライブラリも必要になることを意味しています。 316 | 317 | ErlangはOTP(Open Telecom Platform)と呼ばれるライブラリ群とともに公開さ 318 | れています。OTPは監視ツリーや分散アプリケーションや耐障害性といった機能 319 | を提供しています。elixirからErlangの関数を呼び出すのは簡単です。erlang 320 | モジュール名はアトムとしてelixirでは扱っているので、例えばErlangの 321 | listsモジュールの関数reverse/1を呼び出すためには以下のようにします。 322 | 323 | .. runblock:: iex 324 | 325 | > :lists.reverse([1,2,3]) 326 | 327 | 328 | パターンマッチ 329 | ------------------------------------- 330 | 331 | 関数型言語ではおなじみのパターンマッチも使えます。 332 | 333 | .. runblock:: iex 334 | 335 | > [h | t] = [1,2,3] 336 | > h 337 | > t 338 | 339 | elixirでは=は代入ではなく、パターンマッチ演算子になります。パターンに変 340 | 数がある場合には、できる限りマッチさせるように変数に値が束縛されます。 341 | どうやっても無理の場合には、エラーになります。 342 | 343 | .. runblock:: iex 344 | 345 | > [x, x] = [1,2] 346 | 347 | 束縛された変数は、再度束縛することができます。[#reassign]_ 348 | 349 | .. runblock:: iex 350 | 351 | > t = [2,3] 352 | > t 353 | > [1 | t] = [1,2,3,4] 354 | > t 355 | 356 | 357 | 変数の値を固定したままでパターンマッチをしたい場合も多々あります。そう 358 | いうときには、^演算子を使って変数の束縛を固定します。 359 | 360 | .. runblock:: iex 361 | 362 | > t = [2,3,4] 363 | > [1|^t]=[1,2,3,4,5] 364 | > [1|^t]=[1,2,3,4] 365 | 366 | elixirではアンダースコア変数(_)を代入しても使用しない変数として使います。 367 | [#under_score_variable]_ アンダースコア変数は必ずマッチしますが、参照す 368 | ることはできません。 369 | 370 | .. runblock:: iex 371 | 372 | > [1,_,3|_]=[1,2,3,4] 373 | > _ 374 | 375 | キーワードリスト 376 | ------------------------------------- 377 | 378 | シンタックスシュガーとして、頻繁に使うアトムをキートしたタプルのリスト 379 | である[{:key1, value1}, {:key2, value2}]は[key1: value1, key2: value2] 380 | と書けます。これらへはKeywordモジュールでアクセスできます。 381 | 382 | .. runblock:: iex 383 | 384 | > x = [a: 1, b: 2] 385 | > Keyword.get x, :a 386 | > Keyword.get x, :b 387 | > Keyword.get x, :c 388 | 389 | 390 | キーワード引数と括弧の省略 391 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 392 | 393 | 例えば、よく知られたif式は以下のように書きます。 394 | 395 | .. runblock:: iex 396 | 397 | > if(true, [do: 1+1]) 398 | > if(false, [do: 1+1]) 399 | 400 | すなわち、do:キーリストを引数とした2変数関数で、第一引数がtrueの場合に、 401 | do:キーの値を評価して返すということになります。そして、関数呼び出しは括 402 | 弧を省略できます。 403 | 404 | .. runblock:: iex 405 | 406 | > if true, [do: 1+2] 407 | 408 | 409 | さらに、最後の引数がキーワードリストの場合、カギ括弧も省略できます。 410 | 411 | .. runblock:: iex 412 | 413 | > if true, do: 1+2 414 | 415 | 416 | if関数は第一引数がfalseの場合はelse:キーがあれば、それを評価します。 417 | 418 | .. runblock:: iex 419 | 420 | > if( true, [do: 1, else: 2 ] ) 421 | > if( false, [do: 1, else: 2 ] ) 422 | 423 | do:やelse:の中が複数行とする場合、ブロック記法が使えます。 424 | 425 | .. runblock:: iex 426 | 427 | > if true do 428 | > 1 429 | > else 430 | > 2 431 | > end 432 | 433 | 実は、ifはプリミティブではなく、マクロでelixirのKernelモジュールで実装 434 | されています。 435 | 436 | 制御構造 437 | ------------------------------------- 438 | 439 | elixirには制御構造は分岐のみが存在します。繰り返しは再帰呼び出しによっ 440 | て行います。 441 | 442 | 節とガード式 443 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 444 | 445 | 節とは 446 | ````````````````````````````````````` 447 | 節とは 448 | 449 | .. code-block:: elixir 450 | 451 | match_pattern -> expression 452 | 453 | の形のものです。match_patternはマッチパターンを書くことができ、さらにガー 454 | ド式を書くことができます。match_patternがマッチするとexpressionが実行さ 455 | れる仕組みです。この仕組みはcase式やcond式、fnなど様々なところで現れま 456 | す。複数の節を書くことができますが、実行時システムは上からパターンを操 457 | 作して最初にマッチした節を実行しますので、順序は大事です。 458 | 459 | ガード式とは 460 | ````````````````````````````````````` 461 | 462 | ガード式はmatch_patternを修飾する物で、whenキーワードによって記述します。 463 | match_patternにマッチしてかつ、when句がtrueの場合にマッチしたことになり 464 | ます。パターンに対して複数のwhen句を記述した場合には、いずれかのwhen句 465 | がtrueとなればマッチしたことになります。ガードつきの節は 466 | 467 | 468 | 1) 単一のガードの場合 469 | 470 | .. code-block:: elixir 471 | 472 | match_pattern when bool_expression -> expression 473 | 474 | 2) 複数のガードの場合 475 | 476 | .. code-block:: elixir 477 | 478 | match_pattern when bool_expression1 479 | when bool_expression2 480 | ... 481 | when bool_expressionn -> expression 482 | 483 | の形をしています。ガード式はブール式でありtrueかfalseを返す必要がありま 484 | す。また、ガード式に記述できる演算子や関数は副作用が無い一部の関数に限 485 | られており、副作用がない関数ならどれでも使用可能と言う訳ではありません。 486 | また、自作の関数を呼ぶ事も出来ません。 487 | 488 | 比較演算子 489 | ==, !=, ===, !==, >, <, <=, >= 490 | 491 | ブール演算子 492 | and, or, not [#amp_amp_not_allowed]_ 493 | 494 | 算術演算子 495 | +, -, *, / 496 | 497 | リストとバイナリ演算子 498 | <>, ++ ただし、左辺値(演算結果)がリテラルとなる場合のみ 499 | 500 | 内包演算子 501 | in 502 | 503 | 検査関数(型を検査する以下の関数) 504 | * is_atom/1 505 | * is_binary/1 506 | * is_bitstring/1 507 | * is_boolean/1 508 | * is_float/1 509 | * is_function/1 510 | * is_function/2 511 | * is_integer/1 512 | * is_list/1 513 | * is_map/1 514 | * is_number/1 515 | * is_pid/1 516 | * is_port/1 517 | * is_reference/1 518 | * is_tuple/1 519 | 520 | その他の関数 基本的な物を中心に利用可能な関数がいくつかあります。 521 | 522 | * abs(number) 523 | * bit_size(bitstring) 524 | * byte_size(bitstring) 525 | * div(integer, integer) 526 | * elem(tuple, n) 527 | * hd(list) 528 | * length(list) 529 | * map_size(map) 530 | * node() 531 | * node(pid|ref|port) 532 | * rem(integer, integer) 533 | * round(number) 534 | * self() 535 | * size(tuple|bitstring) 536 | * tl(list) 537 | * trunc(number) 538 | * tuple_size(tuple) 539 | 540 | ガード式を複数記述することが出来ますがその場合は、いずれかのガード式が 541 | trueだった場合にマッチパターンを評価します。 542 | 543 | if 544 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 545 | 546 | ifは最大2分岐の時に使用します。doブロックとキーワードリストの書き方があります。いわゆるelsifはありません。 547 | 548 | 549 | .. runblock:: iex 550 | 551 | > x = 1 552 | > if x == 1, do: :one, else: :not_one 553 | > if x == 1 do 554 | > :one 555 | > else 556 | > :not_one 557 | > end 558 | > x = 2 559 | > if x == 1, do: :one, else: :not_one 560 | > if x == 1 do 561 | > :one 562 | > else 563 | > :not_one 564 | > end 565 | 566 | case 567 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 568 | 569 | パターンマッチ演算子=を導入しましたが、いくつかのパターンにマッチさせた 570 | い場合にはcaseを使います。変数がパターン中に現れると、マッチさせるよう 571 | に値を調整可能な場合には、その値に束縛され直します。ここは=と同様ですが、 572 | 関数型言語の多くが単一代入であることと異なっています。 573 | 574 | .. runblock:: iex 575 | 576 | > x = 1 577 | > case [1,2,3] do 578 | > [1,2,x] -> x 579 | > x -> x 580 | > _ -> 0 581 | > end 582 | > case [1,2,3] do 583 | > x -> x 584 | > [1,x,3] -> x 585 | > _ -> 0 586 | > end 587 | 588 | 再束縛をしてほしくない場合には、=の時と同様に^演算子を用います。 589 | 590 | .. runblock:: iex 591 | 592 | > x = 4 593 | > case [1,2,3] do 594 | > [1,x,3] -> 595 | > x 596 | > x -> 597 | > x 598 | > _ -> 599 | > x 600 | > end 601 | > x 602 | > x = 4 603 | > case [1,2,3] do 604 | > [1,^x,3] -> 605 | > x 606 | > x -> 607 | > x 608 | > _ -> 609 | > 0 610 | > end 611 | 612 | パターンにはガード式を使う事もできます。 613 | 614 | .. runblock:: iex 615 | 616 | > case [1,2,3] do 617 | > [1,x,3] when x > 0 -> 618 | > x 619 | > x -> 620 | > x 621 | > end 622 | 623 | ガード式は、型チェックや論理演算子など、組み込み演算子と関数のみが使え 624 | ます。 [#erlang_guard]_ 625 | 626 | cond 627 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 628 | 629 | condは記述された順序で複数の式の検査を行い、最初にtrueと評価された節が 630 | 実行されます。 631 | 632 | .. runblock:: iex 633 | 634 | > x = 4 635 | > cond do 636 | > 2 + x == 5 -> 637 | > "x is 3" 638 | > 2 * x == 8 -> 639 | > "x is 4" 640 | > 1 * x == x -> 641 | > "x == any" 642 | > end 643 | 644 | 例外 645 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 646 | 647 | 例外については後で書く。 648 | 649 | 例外はモジュールである。 650 | 651 | 652 | 653 | 無名関数の定義 654 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 655 | 656 | 関数は第一級のオブジェクトです。elixirでは関数の定義も複数の節で定義で 657 | きます。 658 | 659 | :ref:`関数` で説明したように、定義はfn()->...endで行い、 =などで変数へ束 660 | 縛するか、直接.演算子で使用することができます。 661 | 662 | .. runblock:: iex 663 | 664 | > (fn(x) -> x * 2 end).(3) 665 | 666 | 667 | 複雑な関数は改行を入れてもかまいません。 668 | 669 | .. runblock:: iex 670 | 671 | > (fn(x) -> 672 | > x * 2 673 | > end).(3) 674 | 675 | また、&構文を使って定義することもできます。&()がfn...endのかわりで、 676 | &nが仮引数になります。 677 | 678 | 679 | .. runblock:: iex 680 | 681 | > (&(&1 * 2)).(3) 682 | 683 | 関数内で使用される自由変数に対する変更はシャドウされます。 684 | 685 | .. runblock:: iex 686 | 687 | > x = 1 688 | > (fn()-> 689 | > x = 2 690 | > [x,x=3] 691 | > end).() 692 | > x 693 | 694 | 695 | receive 696 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 697 | 698 | アクターメカニズムのエッセンスについて議論します。Elixirではプログラム 699 | は互いに分離されたプロセスの中で動作し、それらの間でメッセージを交換し 700 | ます。それらのプロセスはオペレーティングシステムのプロセスではありませ 701 | んが(非常に軽量です)、お互いに状態を全く共有しません。 702 | 703 | .. figure:: ../illustrations/actor_model.png 704 | 705 | アクターモデル 706 | 707 | メッセージを交換するためにそれぞれのプロセスは受信したメッセージを保存 708 | するmailboxを持っています。receiveはこのmailboxからパターンにマッチする 709 | メッセージを検索します。カレントプロセスにメッセージを送信するために 710 | send/2を使用し、receiveを使ってmailboxからメッセージを取得する例を示し 711 | ます。 712 | 713 | 714 | .. runblock:: iex 715 | 716 | > current_pid = self # 現在のプロセスのpidを取得 717 | > spawn fn -> # プロセスを起動して、メッセージを送信する 718 | > send current_pid, { :hello, self } 719 | > :ok 720 | > end 721 | > receive do # メッセージを受信する 722 | > { :hello, pid } -> 723 | > IO.puts "Hello from #{inspect(pid)}" 724 | > end 725 | 726 | モジュール 727 | ------------------------------------- 728 | 729 | elixirで新しいモジュールを作成するためには、”defmodule”マクロに内容を渡すことで行います。 730 | 731 | .. code-block:: elixir 732 | :linenos: 733 | 734 | defmodule Math do 735 | def sum(a,b) do 736 | a + b 737 | end 738 | end 739 | 740 | iexから対話的に実行するとこうなります。 741 | 742 | .. runblock:: iex 743 | 744 | > defmodule Math do 745 | > def sum(a,b) do 746 | > a + b 747 | > end 748 | > end 749 | > Math.sum(1,2) 750 | 751 | モジュールの中では以下の定義が可能です。 752 | 753 | def 754 | 公開関数の定義 755 | 756 | defp 757 | プライベート関数の定義 758 | 759 | defmacro 760 | マクロの定義 761 | 762 | defmacrop 763 | プライベートマクロの定義 764 | 765 | defstruct 766 | 構造体の定義 767 | 768 | defprotocol 769 | プロトコルの定義 770 | 771 | defimpl 772 | プロトコルの実装の定義 773 | 774 | これらの定義については以下に詳細が記述されます。 775 | 776 | ディレクティブ 777 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 778 | 779 | ソフトウェア再利用をサポートする為に、elixirは4つのディレクティブをサポー 780 | トします。 781 | 782 | import 783 | ````````````````````````````````````` 784 | 785 | 修飾された名前を使用する事なく他モジュールから簡単に関数にアクセスした 786 | いときにはいつでも、”import”を使わなければなりません。 787 | 788 | たとえば、あなたのモジュールで何回か”Orddict”モジュールの”values”関 789 | 数を”Orddict.values”とタイプする事なく使いたいとき、単にそれをインポー 790 | トする事ができます。 791 | 792 | .. code-block:: elixir 793 | :linenos: 794 | 795 | defmodule Math do 796 | import Orddict, only:[values: 1] 797 | def some_function do 798 | # call values(orddict) 799 | end 800 | end 801 | 802 | この場合、”Orddict”から(アリティ1の)関数”values”だけをインポートし 803 | ています。”only”はオプションですが、このオプションの仕様は推奨されて 804 | います。”except”オプションも使うことができます。このメカニズムはマク 805 | ロをインポートすることは出来ません。関数だけです。 806 | 807 | alias 808 | ````````````````````````````````````` 809 | 810 | aliasは与えられたモジュールを参照する為の別名をセットアップします。 811 | 例えば、以下をすることができます: 812 | 813 | .. code-block:: elixir 814 | :linenos: 815 | 816 | defmodule Math do 817 | alias MyOrddict, as: Orddict 818 | end 819 | 820 | これで任意の”Orddict”への参照が自動的に”MyOrddict”に置き換わります。 821 | オリジナルの”Orddict”への参照をするにモジュールの前Elixir.をつけま 822 | す: 823 | 824 | .. code-block:: elixir 825 | :linenos: 826 | 827 | Orddict.values #=> uses Elixir.MyOrddixt.values 828 | Elixir.Orddict.values #=> uses Elixir.Orddict.values 829 | 830 | (実際はelixirの全てのモジュールはElixirというモジュールのサブモジュール 831 | になっています) 832 | 833 | aliasはレキシカルスコープですので特定の関数の内側でだけaliasをセットアップ 834 | することができます。 835 | 836 | .. runblock:: iex 837 | 838 | > defmodule Group do 839 | > def direct_product(a, b) do 840 | > alias :lists, as: MyList 841 | > for x <- MyList.seq(1, a), 842 | > y <- MyList.seq(1, b) do 843 | > {x, y} 844 | > end 845 | > end 846 | > def product(a, b) do # MyListはここではaliasから外れている 847 | > for x <- MyList.seq(1, a), 848 | > y <- MyList.seq(1, b) do 849 | > {x, y} 850 | > end 851 | > end 852 | > end 853 | > Group.direct_product(3, 4) 854 | > Group.product(3, 4) # エラーとなる 855 | 856 | require 857 | ````````````````````````````````````` 858 | 859 | "require”はカレントモジュールに所定のモジュールマクロを有効にする事で 860 | す。例えば、”MyMacro”もジュルの中に独自の”if”実装を作成したとします。 861 | それを呼び出したいときには最初に明示的に”MyMacro”を”require”する必 862 | 要があります: 863 | 864 | .. code-block:: elixir 865 | :linenos: 866 | 867 | defmodule Math do 868 | require MyMacro 869 | MyMacro.if do_something, it_works 870 | end 871 | 872 | ロードされていないマクロを呼び出す試みはエラーを起こします。”require” 873 | が唯一のレキシカルなディレクティブであることは重要です。これは特定の関 874 | 数の内部で特定のマクロを必要とする事を可能にするという事を意味します: 875 | 876 | .. code-block:: elixir 877 | :linenos: 878 | 879 | defmodule Math do 880 | def some_function do 881 | require MyMacro, import: true 882 | if do_something, it_works 883 | end 884 | end 885 | 886 | 上記の例では、”MyMacro”からマクロを”require”して”import”し、 887 | some_functionの内部での、”if”の実装をオリジナルから独自のものに取り 888 | 替えました。そのモジュールの他のすべての関数は、オリジナルを使うことが 889 | できます。 890 | 891 | 最後に、”require”もimportするマクロを選択する為に”only”と”except” 892 | オプションを受け入れます。 893 | 894 | 連続的な“require”により前の定義オーバーライドします。 895 | 896 | .. code-block:: elixir 897 | :linenos: 898 | 899 | defmodule MyIo 900 | # import bit-or and bit-and from Bitwise 901 | require Bitwise, only: [bor: 2, band: 2] 902 | def some_func(x, y, z), do: x bor y band z 903 | 904 | # import all, except bxor, overriding previous 905 | require Bitwise, except: [bxor: 2] 906 | end 907 | 908 | 909 | use 910 | ````````````````````````````````````` 911 | 912 | “use”は単に拡張の為の共通API3つのうちで最も単純なメカニズムです。例え 913 | ば、”ExUnit”テスト・フレームワークを使う為には、モジュール中 914 | で”ExUnit::Case”を”use”すればいいです: 915 | 916 | .. code-block:: elixir 917 | :linenos: 918 | 919 | defmodule AssertionTest do 920 | use ExUnit::Case 921 | 922 | def test_always_pass do 923 | true = true 924 | end 925 | end 926 | 927 | “use”を呼ぶ事により、”ExUnit::Case”中の”__using__”と呼ばれるフッ 928 | クが起動され、それから元々のセットアップが実行されます。言い換える 929 | と、”use”は単に以下のように翻訳されます: 930 | 931 | .. code-block:: elixir 932 | :linenos: 933 | 934 | defmodule AssertionTest do 935 | require ExUnit::Case 936 | ExUnit::Case.__using__(:"::AssertionTest") 937 | 938 | def test_always_pass do 939 | true = true 940 | end 941 | end 942 | 943 | .. rubric:: 脚注 944 | .. [#map_since_erlang_r17] Erlang/OTP R17で導入され、Elixirでも利用 945 | できるようになりました。 946 | .. [#nil_is_not_nul_list] Lispと異なり、nilと[]は異なります 947 | .. [#erlang_binary] Erlangのバイナリ 948 | .. [#erlang_string] Erlangの文字列 949 | .. [#erlang_list_operation] この辺はErlangと全く同じです。 950 | .. [#erlang_andalso_orelse] この振る舞いは、Erlangのandalsoとorelseにマッ 951 | プされると考えると良いです。 952 | .. [#reassign] ここはErlangと違うところですが、javaやRuby使いはほっとす 953 | るところでしょう。 954 | .. [#under_score_variable] ここもErlangと同じです。 955 | .. [#amp_amp_not_allowed] ||, &&は許可されていません 956 | .. [#erlang_guard] Erlangのガード式と同様です。 957 | -------------------------------------------------------------------------------- /source/using_std_library.rst: -------------------------------------------------------------------------------- 1 | ===================================== 2 | 標準ライブラリ 3 | ===================================== 4 | 5 | 6 | Elixir標準ライブラリ 7 | ------------------------------------- 8 | 9 | 10 | http://elixir-lang.org/docs/master/ 11 | 12 | --------------------------------------------------------------------------------