From b0248e8eca14dd0ec90ea147ae3667e1804d55c0 Mon Sep 17 00:00:00 2001 From: eksperimental Date: Sat, 7 Feb 2015 01:48:20 +0700 Subject: [PATCH] Shell highlighting, MD Table support, Crash Course Tables converted and improvments --- README.md | 24 +++--- _config.yml | 2 +- _includes/bottom.html | 2 +- ...2013-05-23-elixir-v0-9-0-released.markdown | 4 +- ...014-04-21-elixir-v0-13-0-released.markdown | 2 +- crash-course.markdown | 79 ++++++++----------- css/style.css | 27 +++++++ getting-started/meta/macros.markdown | 4 +- getting-started/mix-otp/agent.markdown | 4 +- .../dependencies-and-umbrella-apps.markdown | 42 ++++++---- ...stributed-tasks-and-configuration.markdown | 44 +++++++---- .../mix-otp/docs-tests-and-pipelines.markdown | 18 +++-- getting-started/mix-otp/ets.markdown | 4 +- .../mix-otp/introduction-to-mix.markdown | 34 +++++--- .../mix-otp/task-and-gen-tcp.markdown | 56 +++++++------ getting-started/module-attributes.markdown | 17 ++-- getting-started/modules.markdown | 16 +++- install.markdown | 28 ++++--- 18 files changed, 248 insertions(+), 159 deletions(-) diff --git a/README.md b/README.md index cbadad977..2344b9c44 100644 --- a/README.md +++ b/README.md @@ -4,7 +4,7 @@ It is automatically transformed by [Jekyll](http://github.com/mojombo/jekyll) in ### Contributing to the blog - Create a new file inside `_posts/YYYY-MM-DD-post-title.markdown` following the template: +Create a new file inside `_posts/YYYY-MM-DD-post-title.markdown` following the template: --- layout: post @@ -16,24 +16,28 @@ It is automatically transformed by [Jekyll](http://github.com/mojombo/jekyll) in Body text goes here... - Or use `_bin/newpost` to bootstrap a new post file: +Or use `_bin/newpost` to bootstrap a new post file: - export EDITOR=vim; _bin/newpost 'Post title' +```bash +export EDITOR=vim; _bin/newpost 'Post title' +``` ### Contributing improvements or bug fixes -1. Fork elixir-lang.github.com +1. [Fork elixir-lang.github.com](https://github.com/elixir-lang/elixir-lang.github.com/fork). -2. Make your changes +2. Make your changes. 3. Test it locally, you need to install the gems `jekyll` and `redcarpet`: - ```shell - $ gem install jekyll redcarpet - $ jekyll serve # check localhost:4000 - ``` +```bash +$ gem install jekyll redcarpet +$ jekyll serve # check localhost:4000 +``` -4. Send a pull-request for your changes +4. Push to your forked repository. + +5. Submit a pull-request for your changes. `jekyll` requires a javascript processor to be available too. Many OS provide such functionality but others do not. If you have an error related to ExecJS, you can work around it by either running `gem install therubyracer` or by ensuring node.js is available in your path. diff --git a/_config.yml b/_config.yml index 881626ea1..ccdbbf3b3 100644 --- a/_config.yml +++ b/_config.yml @@ -2,6 +2,6 @@ markdown: redcarpet highlighter: pygments permalink: /blog/:year/:month/:day/:title/ redcarpet: - extensions: ['with_toc_data'] + extensions: ['with_toc_data', 'tables'] gems: - jekyll-redirect-from \ No newline at end of file diff --git a/_includes/bottom.html b/_includes/bottom.html index 38ff0a2f7..f1316cd0e 100644 --- a/_includes/bottom.html +++ b/_includes/bottom.html @@ -3,7 +3,7 @@
diff --git a/_posts/2013-05-23-elixir-v0-9-0-released.markdown b/_posts/2013-05-23-elixir-v0-9-0-released.markdown index 762b9db25..fbded71e5 100644 --- a/_posts/2013-05-23-elixir-v0-9-0-released.markdown +++ b/_posts/2013-05-23-elixir-v0-9-0-released.markdown @@ -36,7 +36,9 @@ As a project grows, it is recommended to break it apart into smaller, isolated a Elixir v0.9.0 now supports umbrella projects which can work with many applications at the same time. You can create a new umbrella project with: - $ mix new my_project --umbrella +```bash +$ mix new my_project --umbrella +``` The generated project will have the following structure: diff --git a/_posts/2014-04-21-elixir-v0-13-0-released.markdown b/_posts/2014-04-21-elixir-v0-13-0-released.markdown index 2288bae91..5293b094e 100644 --- a/_posts/2014-04-21-elixir-v0-13-0-released.markdown +++ b/_posts/2014-04-21-elixir-v0-13-0-released.markdown @@ -241,7 +241,7 @@ The last big change we want to discuss in this release are the improvements done In previous releases, Mix was used to download and compile dependencies per environment. That meant the usual workflow was less than ideal: every time a dependency was updated, developers had to explicitly fetch and compile the dependencies for each environment. The workflow would be something like: -``` +```bash $ mix deps.get $ mix compile $ MIX_ENV=test mix deps.get diff --git a/crash-course.markdown b/crash-course.markdown index b022dabd1..d44cd4e85 100644 --- a/crash-course.markdown +++ b/crash-course.markdown @@ -8,20 +8,10 @@ layout: default This is a quick introduction to the Elixir syntax for Erlang developers and vice-versa. It is the absolute minimum amount of knowledge you need in order to understand Elixir/Erlang code, support interoperability, read the docs, sample code, etc. -This page is divided into sections: +
-1. [Running Code](#running_code) -2. [Notable Differences](#notable_differences) -3. [Data Types](#data_types) -4. [Modules](#modules) -5. [Function Syntax](#function_syntax) -6. [Control Flow](#control_flow) -7. [Adding Elixir to existing Erlang programs](#interop) -8. [Further reading](#further_reading) -
- -## 1 Running Code +## Running code ### Erlang @@ -82,26 +72,25 @@ defmodule MyModule do end ``` -
-## 2 Notable Differences +## Notable differences This section goes over some of the syntactic differences between the two languages. -### Operator Names +### Operator names Some operators are spelled differently. - | Erlang | Elixir | Meaning | - ----------------------------------------------------------------------------- - | and | NOT AVAILABLE | Logical 'and', evaluates both arguments | - | andalso | and | Logical 'and', short-circuits | - | or | NOT AVAILABLE | Logical 'or', evaluates both arguments | - | orelse | or | Logical 'or', short-circuits | - | =:= | === | A match operator | - | =/= | !== | A negative match | - | /= | != | Not equals | - | =< | <= | Less than or equals | +| Erlang | Elixir | Meaning | +|----------------|----------------|-----------------------------------------| +| and | NOT AVAILABLE | Logical 'and', evaluates both arguments | +| andalso | and | Logical 'and', short-circuits | +| or | NOT AVAILABLE | Logical 'or', evaluates both arguments | +| orelse | or | Logical 'or', short-circuits | +| =:= | === | A match operator | +| =/= | !== | A negative match | +| /= | != | Not equals | +| =< | <= | Less than or equals | ### Delimiters @@ -122,7 +111,7 @@ x = 2; y = 3 x + y ``` -### Variable Names +### Variable names Variables in Erlang can only be assigned once. The Erlang shell provides a special command `f` that allows you to erase the binding of a variable or all variables at once. @@ -161,14 +150,14 @@ iex> ^a = 3 ** (MatchError) no match of right hand side value: 3 ``` -### Calling Functions +### Calling functions Elixir allows you to omit parentheses in function calls, Erlang does not. - | Erlang | Elixir | - -------------------------------------- - | some_function(). | some_function | - | sum(A, B) | sum a, b | +| Erlang | Elixir | +|-------------------|----------------| +| some_function(). | some_function | +| sum(A, B) | sum a, b | Invoking a function from a module uses different syntax. In Erlang, you would write @@ -190,9 +179,8 @@ Kernel.self All of the Erlang built-ins reside in the `:erlang` module. -
-## 3 Data Types +## Data types Erlang and Elixir have the same data types for the most part, but there are a number of differences. @@ -264,7 +252,7 @@ elem({ :a, :b, :c }, 0) #=> :a put_elem({ :a, :b, :c }, 0, :d) #=> { :d, :b, :c } ``` -### Lists and Binaries +### Lists and binaries Elixir has a shortcut syntax for binaries: @@ -374,9 +362,8 @@ lines. """ ``` -
-## 4 Modules +## Modules Each Erlang module lives in its own file which has the following structure: @@ -452,15 +439,14 @@ HelloModule.Utils.priv #=> ** (UndefinedFunctionError) undefined function: HelloModule.Utils.priv/0 ``` -
-## 5 Function Syntax +## Function syntax [This chapter][3] from the Erlang book provides a detailed description of pattern matching and function syntax in Erlang. Here, I'm briefly covering the main points and provide sample code both in Erlang and Elixir. [3]: http://learnyousomeerlang.com/syntax-in-functions -### Pattern Matching +### Pattern matching Pattern matching in Elixir is based on Erlang's implementation and in general is very similar: @@ -574,7 +560,7 @@ mul_by 4, 3 #=> 12 mul_by 4 #=> 8 ``` -### Anonymous Functions +### Anonymous functions Anonymous functions are defined in the following way: @@ -637,7 +623,7 @@ f.({:a, :b}) #=> "All your {:a,:b} are belong to us" ``` -### First-Class Functions +### First-class functions Anonymous functions are first-class values, so they can be passed as arguments to other functions and also can serve as a return value. There is a special syntax to allow named functions be treated in the same manner. @@ -692,9 +678,8 @@ Enum.map [1,2,3], &Math.square/1 #=> [1, 4, 9] ``` -
-## 6 Control Flow +## Control flow The constructs `if` and `case` are actually expressions in both Erlang and Elixir, but may be used for control flow as in imperative languages. @@ -791,7 +776,7 @@ else end ``` -### Sending and Receiving Messages +### Sending and receiving messages The syntax for sending and receiving differs only slightly between Erlang and Elixir. @@ -825,9 +810,8 @@ after end ``` -
-## 7 Adding Elixir to existing Erlang programs +## Adding Elixir to existing Erlang programs Elixir compiles into BEAM byte code (via Erlang Abstract Format). This means that Elixir code can be called from Erlang and vice versa, without the need to write any bindings. All Elixir modules start with the `Elixir.` prefix followed by the regular Elixir name. For example, here is how to use the utf-8 aware `String` downcase from Elixir in Erlang: @@ -859,9 +843,8 @@ This should be enough to invoke Elixir functions straight from your Erlang code. If you are not using rebar, the easiest approach to use Elixir in your existing Erlang software is to install Elixir using one of the different ways specified in the [Getting Started guide](/getting-started/introduction.html) and add the `lib` directory in your checkout to `ERL_LIBS`. -
-## 8 Further Reading +## Further reading Erlang's official documentation site has a nice [collection][4] of programming examples. It can be a good exercise to translate them into Elixir. [Erlang cookbook][5] offers even more useful code examples. diff --git a/css/style.css b/css/style.css index 781605fa3..723feba38 100644 --- a/css/style.css +++ b/css/style.css @@ -161,6 +161,15 @@ ol ol ol { list-style: lower-roman } ol ol ol ol { list-style: upper-alpha } ol ol ol ol ol { list-style: lower-alpha } ul ul, ol ol, ul ol, ol ul { margin-bottom:0 } + +.toc ol { counter-reset: item; } +.toc ol li { display: block } +.toc ol li:before { + content: counters(item, ".") " "; + counter-increment: item; +} + + dl { margin: 0 0 1.692307em 5px } dt { font-weight: bold; @@ -305,6 +314,24 @@ td { border-bottom: 1px solid #e7e7e7; } +#content table { + margin-left: 1.692307em; + width: auto; + width: 85%; +} +#content table caption { color: #555; } +#content table th { + font-weight: bold; + padding: 10px 4%; + border-bottom: 3px solid #E6DFD5; + background-color:#FFFAF3; +} +#content td { + padding: 0.8125em 4%; + border-bottom: 1px solid #E6DFD5; + background-color:#FFFAF3; +} + /* Lists -------------------------------------------------------------- */ ul li, ol li { line-height: 2.1em; } diff --git a/getting-started/meta/macros.markdown b/getting-started/meta/macros.markdown index 8eb269175..aaf40359f 100644 --- a/getting-started/meta/macros.markdown +++ b/getting-started/meta/macros.markdown @@ -34,7 +34,9 @@ The function receives the arguments and passes them to `if`. However, as we lear Let's start `iex` with the module above: - $ iex macros.exs +```bash +$ iex macros.exs +``` And play with those definitions: diff --git a/getting-started/mix-otp/agent.markdown b/getting-started/mix-otp/agent.markdown index 4b928dca0..f243b3dc9 100644 --- a/getting-started/mix-otp/agent.markdown +++ b/getting-started/mix-otp/agent.markdown @@ -32,7 +32,9 @@ We will explore all of these abstractions in this guide. Keep in mind that they [Agents](/docs/stable/elixir/Agent.html) are simple wrappers around state. If all you want from a process is to keep state, agents are a great fit. Let's start an `iex` session inside the project with: - $ iex -S mix +```bash +$ iex -S mix +``` And play a bit with agents: diff --git a/getting-started/mix-otp/dependencies-and-umbrella-apps.markdown b/getting-started/mix-otp/dependencies-and-umbrella-apps.markdown index efa557358..d0939cb9e 100644 --- a/getting-started/mix-otp/dependencies-and-umbrella-apps.markdown +++ b/getting-started/mix-otp/dependencies-and-umbrella-apps.markdown @@ -60,13 +60,15 @@ You will notice that when you add a dependency to your project, Mix generates a Mix provides many tasks for working with dependencies, which can be seen in `mix help`: - $ mix help - mix deps # List dependencies and their status - mix deps.clean # Remove the given dependencies' files - mix deps.compile # Compile dependencies - mix deps.get # Get all out of date dependencies - mix deps.unlock # Unlock the given dependencies - mix deps.update # Update the given dependencies +```bash +$ mix help +mix deps # List dependencies and their status +mix deps.clean # Remove the given dependencies' files +mix deps.compile # Compile dependencies +mix deps.get # Get all out of date dependencies +mix deps.unlock # Unlock the given dependencies +mix deps.update # Update the given dependencies +``` The most common tasks are `mix deps.get` and `mix deps.update`. Once fetched, dependecies are automatically compiled for you. You can read more about deps by typing `mix help deps`, and in the [documentation for the Mix.Tasks.Deps module](/docs/stable/mix/Mix.Tasks.Deps.html). @@ -107,13 +109,15 @@ So let's get started! Let's start a new project using `mix new`. This new project will be named `kv_umbrella` and we need to pass the `--umbrella` option when creating it. Do not create this new project inside the existing `kv` project! - $ mix new kv_umbrella --umbrella - * creating .gitignore - * creating README.md - * creating mix.exs - * creating apps - * creating config - * creating config/config.exs +```bash +$ mix new kv_umbrella --umbrella +* creating .gitignore +* creating README.md +* creating mix.exs +* creating apps +* creating config +* creating config/config.exs +``` From the printed information, we can see far fewer files are generated. The generated `mix.exs` file is different too. Let's take a look (comments have been removed): @@ -136,8 +140,10 @@ What makes this project different from the previous one is simply the `apps_path Let's move inside the apps directory and start building `kv_server`. This time, we are going to pass the `--sup` flag, which will tell Mix to generate a supervision tree automatically for us, instead of building one manually as we did in previous chapters: - $ cd kv_umbrella/apps - $ mix new kv_server --module KVServer --sup +```bash +$ cd kv_umbrella/apps +$ mix new kv_server --module KVServer --sup +``` The generated files are similar to the ones we first generated for `kv`, with a few differences. Let's open up `mix.exs`: @@ -208,7 +214,9 @@ Notice that it defines the application callback function, `start/2`, and instead We can already try out our first umbrella child. We could run tests inside the `apps/kv_server` directory, but that wouldn't be much fun. Instead, go to the root of the umbrella project and run `mix test`: - $ mix test +```bash +$ mix test +``` And it works! diff --git a/getting-started/mix-otp/distributed-tasks-and-configuration.markdown b/getting-started/mix-otp/distributed-tasks-and-configuration.markdown index 62b58d310..c383695f8 100644 --- a/getting-started/mix-otp/distributed-tasks-and-configuration.markdown +++ b/getting-started/mix-otp/distributed-tasks-and-configuration.markdown @@ -29,7 +29,9 @@ Elixir ships with facilities to connect nodes and exchange information between t In order to run distributed code, we need to start the VM with a name. The name can be short (when in the same network) or long (requires the full computer address). Let's start a new IEx session: - $ iex --sname foo +```bash +$ iex --sname foo +``` You can see now the prompt is slightly different and shows the node name followed by the computer name: @@ -48,7 +50,9 @@ iex> defmodule Hello do If you have another computer on the same network with both Erlang and Elixir installed, you can start another shell on it. If you don't, you can simply start another IEx session in another terminal. In either case, give it the short name of `bar`: - $ iex --sname bar +```bash +$ iex --sname bar +``` Note that inside this new IEx session, we cannot access `Hello.world/0`: @@ -120,8 +124,10 @@ supervisor(Task.Supervisor, [[name: KV.RouterTasks]]), Now, let's start two named nodes again, but inside the `:kv` application: - $ iex --sname foo -S mix - $ iex --sname bar -S mix +```bash +$ iex --sname foo -S mix +$ iex --sname bar -S mix +``` From inside `bar@computer-name`, we can now spawn a task directly on the other node via the supervisor: @@ -209,11 +215,15 @@ The second test just checks that the code raises for unknown entries. In order to run the first test, we need to have two nodes running. Let's restart the node named `bar`, which is going to be used by tests: - $ iex --sname bar -S mix +```bash +$ iex --sname bar -S mix +``` And now run tests with: - $ elixir --sname foo -S mix test +```bash +$ elixir --sname foo -S mix test +``` Our test should successfuly pass. Excellent! @@ -243,19 +253,23 @@ ExUnit.start(exclude: exclude) Now run tests with `mix test`: - $ mix test - Excluding tags: [distributed: true] +```bash +$ mix test +Excluding tags: [distributed: true] - ....... +....... - Finished in 0.1 seconds (0.1s on load, 0.01s on tests) - 7 tests, 0 failures +Finished in 0.1 seconds (0.1s on load, 0.01s on tests) +7 tests, 0 failures +``` This time all tests passed and ExUnit warned us that distributed tests were being excluded. If you run tests with `$ elixir --sname foo -S mix test`, one extra test should run and successfully pass as long as the `bar@computer-name` node is available. The `mix test` command also allows us to dynamically include and exclude tags. For example, we can run `$ mix test --include distributed` to run distributed tests regardless of the value set in `test/test_helper.exs`. We could also pass `--exclude` to exclude a particular tag from the command line. Finally, `--only` can be used to run only tests with a particular tag: - $ elixir --sname foo -S mix test --only distributed +```bash +$ elixir --sname foo -S mix test --only distributed +``` You can read more about filters, tags and the default tags in [`ExUnit.Case` module documentation](/docs/stable/ex_unit/ExUnit.Case.html). @@ -292,8 +306,10 @@ We use `Application.get_env/2` to read the entry for `:routing_table` in `:kv`'s Since our routing table is now empty, our distributed test should fail. Restart the apps and re-run tests to see the failure: - $ iex --sname bar -S mix - $ elixir --sname foo -S mix test --only distributed +```bash +$ iex --sname bar -S mix +$ elixir --sname foo -S mix test --only distributed +``` The interesting thing about the application environment is that it can be configured not only for the current application, but for all applications. Such configuration is done by the `config/config.exs` file. For example, we can configure IEx default prompt to another value. Just open `apps/kv/config/config.exs` and add the following to the end: diff --git a/getting-started/mix-otp/docs-tests-and-pipelines.markdown b/getting-started/mix-otp/docs-tests-and-pipelines.markdown index 5678f8f93..929094d5c 100644 --- a/getting-started/mix-otp/docs-tests-and-pipelines.markdown +++ b/getting-started/mix-otp/docs-tests-and-pipelines.markdown @@ -234,14 +234,16 @@ defp format_msg({:error, _}), do: "ERROR\r\n" If we start our server, we can now send commands to it. For now we will get two different responses: "OK" when the command is known and "UNKNOWN COMMAND" otherwise: - $ telnet 127.0.0.1 4040 - Trying 127.0.0.1... - Connected to localhost. - Escape character is '^]'. - CREATE shopping - OK - HELLO - UNKNOWN COMMAND +```bash +$ telnet 127.0.0.1 4040 +Trying 127.0.0.1... +Connected to localhost. +Escape character is '^]'. +CREATE shopping +OK +HELLO +UNKNOWN COMMAND +``` This means our implementation is going in the correct direction, but it doesn't look very elegant, does it? diff --git a/getting-started/mix-otp/ets.markdown b/getting-started/mix-otp/ets.markdown index 49957d824..4d452deb3 100644 --- a/getting-started/mix-otp/ets.markdown +++ b/getting-started/mix-otp/ets.markdown @@ -239,7 +239,9 @@ We simply changed the callback from `handle_cast/2` to `handle_call/3` and chang Let's run the tests once again. This time though, we will pass the `--trace` option: - $ mix test --trace +```bash +$ mix test --trace +``` The `--trace` option is useful when your tests are deadlocking or there are race conditions, as it runs all tests synchronously (`async: true` has no effect) and shows detailed information about each test. This time we should be down to one failure (that may be intermittent): diff --git a/getting-started/mix-otp/introduction-to-mix.markdown b/getting-started/mix-otp/introduction-to-mix.markdown index 17b1efae3..75f92ed1c 100644 --- a/getting-started/mix-otp/introduction-to-mix.markdown +++ b/getting-started/mix-otp/introduction-to-mix.markdown @@ -50,7 +50,9 @@ When you install Elixir, besides getting the `elixir`, `elixirc` and `iex` execu Let's create our first project by invoking `mix new` from the command line. We'll pass the project name as argument (`kv`, in this case), and tell mix that our main module should be the all-uppercase `KV`, instead of the default, which would have been `Kv`: - $ mix new kv --module KV +```bash +$ mix new kv --module KV +``` Mix will create a directory named `kv` with a few files in it: @@ -69,11 +71,15 @@ Let's take a brief look at those generated files. > Note: Mix is an Elixir executable. This means that in order to run `mix`, you need to have elixir's executable in your PATH. If not, you can run it by passing the script as argument to elixir: > -> $ bin/elixir bin/mix new kv --module KV +> ```bash +> $ bin/elixir bin/mix new kv --module KV +> ``` > > Note that you can also execute any script in your PATH from Elixir via the -S option: > -> $ bin/elixir -S mix new kv --module KV +> ```bash +> $ bin/elixir -S mix new kv --module KV +> ``` > > When using -S, elixir finds the script wherever it is in your PATH and executes it. @@ -114,8 +120,10 @@ end This structure is enough to compile our project: - $ cd kv - $ mix compile +```bash +$ cd kv +$ mix compile +``` Will output: @@ -126,7 +134,9 @@ Notice the `lib/kv.ex` file was compiled and `kv.app` file was generated. All th Once the project is compiled, you can start an `iex` session inside the project by running: - $ iex -S mix +```bash +$ iex -S mix +``` ## Running tests @@ -193,7 +203,9 @@ For each failure, ExUnit prints a detailed report, containing the test name with In the second line of the failure, right below the test name, there is the location where the test was defined. If you copy the test location in this full second line (including the file and line number) and append it to `mix test`, Mix will load and run just that particular test: - $ mix test test/kv_test.exs:4 +```bash +$ mix test test/kv_test.exs:4 +``` This shortcut will be extremely useful as we build our project, allowing us to quickly iterate by running just a specific test. @@ -222,7 +234,9 @@ defp deps_path(_), do: "deps" Mix will default to the `:dev` environment, except for the `test` task that will default to the `:test` environment. The environment can be changed via the `MIX_ENV` environment variable: - $ MIX_ENV=prod mix compile +```bash +$ MIX_ENV=prod mix compile +``` ## Exploring @@ -230,7 +244,9 @@ There is much more to Mix, and we will continue to explore it as we build our pr Keep in mind that you can always invoke the help task to list all available tasks: - $ mix help +```bash +$ mix help +``` You can get further information about a particular task by invoking `mix help TASK`. diff --git a/getting-started/mix-otp/task-and-gen-tcp.markdown b/getting-started/mix-otp/task-and-gen-tcp.markdown index 1d02453c5..3085a8113 100644 --- a/getting-started/mix-otp/task-and-gen-tcp.markdown +++ b/getting-started/mix-otp/task-and-gen-tcp.markdown @@ -99,16 +99,18 @@ iex> KVServer.accept(4040) The server is now running, and you will even notice the console is blocked. Let's use [a `telnet` client](http://en.wikipedia.org/wiki/Telnet) to access our server. There are clients available on most operating systems, and their command lines are generally similar: - $ telnet 127.0.0.1 4040 - Trying 127.0.0.1... - Connected to localhost. - Escape character is '^]'. - hello - hello - is it me - is it me - you are looking for? - you are looking for? +```bash +$ telnet 127.0.0.1 4040 +Trying 127.0.0.1... +Connected to localhost. +Escape character is '^]'. +hello +hello +is it me +is it me +you are looking for? +you are looking for? +``` Type "hello", press enter, and you will get "hello" back. Excellent! @@ -150,26 +152,30 @@ With this change, we are saying that we want to run `KVServer.accept(4040)` as a Now that the server is part of the supervision tree, it should start automatically when we run the application. Type `mix run --no-halt` in the terminal, and once again use the `telnet` client to make sure that everything still works: - $ telnet 127.0.0.1 4040 - Trying 127.0.0.1... - Connected to localhost. - Escape character is '^]'. - say you - say you - say me - say me +```bash +$ telnet 127.0.0.1 4040 +Trying 127.0.0.1... +Connected to localhost. +Escape character is '^]'. +say you +say you +say me +say me +``` Yes, it works! If you kill the client, causing the whole server to crash, you will see another one starts right away. However, does it *scale*? Try to connect two telnet clients at the same time. When you do so, you will notice that the second client doesn't echo: - $ telnet 127.0.0.1 4040 - Trying 127.0.0.1... - Connected to localhost. - Escape character is '^]'. - hello - hello? - HELLOOOOOO? +```bash +$ telnet 127.0.0.1 4040 +Trying 127.0.0.1... +Connected to localhost. +Escape character is '^]'. +hello +hello? +HELLOOOOOO? +``` It doesn't seem to work at all. That's because we are serving requests in the same process that are accepting connections. When one client is connected, we can't accept another client. diff --git a/getting-started/module-attributes.markdown b/getting-started/module-attributes.markdown index 535793421..950dfda3a 100644 --- a/getting-started/module-attributes.markdown +++ b/getting-started/module-attributes.markdown @@ -60,12 +60,17 @@ end Elixir promotes the use of markdown with heredocs to write readable documentation. Heredocs are multiline strings, they start and end with triple quotes, keeping the formatting of the inner text. We can access the documentation of any compiled module directly from IEx: - $ elixirc math.ex - $ iex - iex> h Math # Access the docs for the module Math - ... - iex> h Math.sum # Access the docs for the sum function - ... +```bash +$ elixirc math.ex +$ iex +``` + +```iex +iex> h Math # Access the docs for the module Math +... +iex> h Math.sum # Access the docs for the sum function +... +``` We also provide a tool called [ExDoc](https://github.com/elixir-lang/ex_doc) which is used to generate HTML pages from the documentation. diff --git a/getting-started/modules.markdown b/getting-started/modules.markdown index 8a4810a40..d6592ffe4 100644 --- a/getting-started/modules.markdown +++ b/getting-started/modules.markdown @@ -44,7 +44,9 @@ end This file can be compiled using `elixirc`: - $ elixirc math.ex +```bash +$ elixirc math.ex +``` This will generate a file named `Elixir.Math.beam` containing the bytecode for the defined module. If we start `iex` again, our module definition will be available (provided that `iex` is started in the same directory the bytecode file is in): @@ -77,7 +79,9 @@ IO.puts Math.sum(1, 2) And execute it as: - $ elixir math.exs +```bash +$ elixir math.exs +``` The file will be compiled in memory and executed, printing "3" as the result. No bytecode file will be created. In the following examples, we recommend you write your code into script files and execute them as shown above. @@ -126,7 +130,9 @@ Giving an argument that does not match any of the clauses raises an error. Throughout this tutorial, we have been using the notation `name/arity` to refer to functions. It happens that this notation can actually be used to retrieve a named function as a function type. Let's start `iex` and run the `math.exs` file defined above: - $ iex math.exs +```bash +$ iex math.exs +``` ```iex iex> Math.zero?(0) @@ -248,7 +254,9 @@ If we save the code above in a file named "concat.ex" and compile it, Elixir wil The compiler is telling us that invoking the `join` function with two arguments will always choose the first definition of `join` whereas the second one will only be invoked when three arguments are passed: - $ iex concat.exs +```bash +$ iex concat.exs +``` ```iex iex> Concat.join "Hello", "world" diff --git a/install.markdown b/install.markdown index 4dddb39f1..0bd56e759 100644 --- a/install.markdown +++ b/install.markdown @@ -6,13 +6,13 @@ layout: default # {{ page.title }} -
- The quickest way to install Elixir is through a distribution or using one of the available installers. If not available, then we recommend the precompiled packages or compiling from source. Note Elixir requires Erlang 17.0 or later. Many of the instructions below will automatically install Erlang for you. In case they do not, read the "Installing Erlang" section below. -## 1 Distributions +
+ +## Distributions Choose your operating system and tool. @@ -53,15 +53,17 @@ Choose your operating system and tool. Those distributions will likely install Erlang automatically for you too. In case they don't, check the [Installing Erlang](/install.html#4-installing-erlang) section below. -## 2 Precompiled package +## Precompiled package Elixir provides a precompiled package for every release. First [install Erlang](/install.html#4-installing-erlang) and then download and unzip the [Precompiled.zip file for the latest release](https://github.com/elixir-lang/elixir/releases/). Once the release is unpacked, you are ready to run the `elixir` and `iex` commands from the `bin` directory. It is recommended that you add Elixir's `bin` path to your PATH environment variable to ease development. - $ export PATH="$PATH:/path/to/elixir/bin" +```bash +$ export PATH="$PATH:/path/to/elixir/bin" +``` -## 3 Compiling from source (Unix and MinGW) +## Compiling from source (Unix and MinGW) You can download and compile Elixir in few steps. The first one is to [install Erlang](/install.html#4-installing-erlang). @@ -69,17 +71,21 @@ Next you should download the [latest release](https://github.com/elixir-lang/eli After compiling, you are ready to run the `elixir` and `iex` commands from the `bin` directory. It is recommended that you add Elixir's `bin` path to your [PATH](http://en.wikipedia.org/wiki/Environment_variable) environment variable to ease development: - $ export PATH="$PATH:/path/to/elixir/bin" +```bash +$ export PATH="$PATH:/path/to/elixir/bin" +``` In case you are feeling a bit more adventurous, you can also compile from master: - $ git clone https://github.com/elixir-lang/elixir.git - $ cd elixir - $ make clean test +```bash +$ git clone https://github.com/elixir-lang/elixir.git +$ cd elixir +$ make clean test +``` If the tests pass, you are ready to go. Otherwise, feel free to open an issue [in the issues tracker on Github](https://github.com/elixir-lang/elixir). -## 4 Installing Erlang +## Installing Erlang The only prerequisite for Elixir is Erlang, version 17.0 or later, which can be easily installed with [Precompiled packages](https://www.erlang-solutions.com/downloads/download-erlang-otp). In case you want to install it directly from source, it can be found on [the Erlang website](http://www.erlang.org/download.html) or by following the excellent tutorial available in the [Riak documentation](http://docs.basho.com/riak/1.3.0/tutorials/installation/Installing-Erlang/).