From 16ce33aa6d666c235149c7941d0cef2043d22dc9 Mon Sep 17 00:00:00 2001 From: Rob Phoenix Date: Fri, 27 Nov 2015 11:10:15 +0000 Subject: [PATCH] Changed some grammar and punctuation in Getting Started Guide Minor changes to some of the grammar and punctuation in the Getting Started Guide. Hopefully nothing too opinionated, a comma here, a word change there. Intended to make the guide clearer, and improve readability. --- getting-started/alias-require-and-import.markdown | 2 +- getting-started/binaries-strings-and-char-lists.markdown | 2 +- getting-started/comprehensions.markdown | 2 +- getting-started/enumerables-and-streams.markdown | 8 ++++---- getting-started/introduction.markdown | 4 ++-- getting-started/io-and-the-file-system.markdown | 4 ++-- getting-started/maps-and-dicts.markdown | 8 ++++---- getting-started/module-attributes.markdown | 2 +- getting-started/processes.markdown | 6 +++--- getting-started/recursion.markdown | 6 +++--- getting-started/sigils.markdown | 6 +++--- getting-started/try-catch-and-rescue.markdown | 6 +++--- getting-started/where-to-go-next.markdown | 4 ++-- 13 files changed, 30 insertions(+), 30 deletions(-) diff --git a/getting-started/alias-require-and-import.markdown b/getting-started/alias-require-and-import.markdown index 77cb388b1..27c458de9 100644 --- a/getting-started/alias-require-and-import.markdown +++ b/getting-started/alias-require-and-import.markdown @@ -166,7 +166,7 @@ end The example above will define two modules: `Foo` and `Foo.Bar`. The second can be accessed as `Bar` inside `Foo` as long as they are in the same lexical scope. -If later the `Bar` module is moved outside the `Foo` module definition, it will need to be referenced by its full name (`Foo.Bar`) or an alias will need to be set using the `alias` directive discussed above. The `Bar` module definition will change too. This code is equivalent to the example above: +If, later, the `Bar` module is moved outside the `Foo` module definition, it will need to be referenced by its full name (`Foo.Bar`) or an alias will need to be set using the `alias` directive discussed above. The `Bar` module definition will change too. This code is equivalent to the example above: ```elixir defmodule Foo.Bar do diff --git a/getting-started/binaries-strings-and-char-lists.markdown b/getting-started/binaries-strings-and-char-lists.markdown index d56810a4f..17da6ba98 100644 --- a/getting-started/binaries-strings-and-char-lists.markdown +++ b/getting-started/binaries-strings-and-char-lists.markdown @@ -153,7 +153,7 @@ iex> rest "llo" ``` -This finishes our tour of bitstrings, binaries and strings. A string is a UTF-8 encoded binary, and a binary is a bitstring where the number of bits is divisible by 8. Although this shows the flexibility Elixir provides to work with bits and bytes, 99% of the time you will be working with binaries and using the `is_binary/1` and `byte_size/1` functions. +This finishes our tour of bitstrings, binaries and strings. A string is a UTF-8 encoded binary, and a binary is a bitstring where the number of bits is divisible by 8. Although this shows the flexibility Elixir provides for working with bits and bytes, 99% of the time you will be working with binaries and using the `is_binary/1` and `byte_size/1` functions. ## Char lists diff --git a/getting-started/comprehensions.markdown b/getting-started/comprehensions.markdown index 84af0b8e6..b5e530a11 100644 --- a/getting-started/comprehensions.markdown +++ b/getting-started/comprehensions.markdown @@ -122,7 +122,7 @@ iex> for <>, do: {r, g, b} [{213, 45, 132}, {64, 76, 32}, {76, 0, 0}, {234, 32, 15}] ``` -A bitstring generator can be mixed with the "regular" enumerable generators and provides filters as well. +A bitstring generator can be mixed with "regular" enumerable generators, and supports filters as well. ## Results other than lists diff --git a/getting-started/enumerables-and-streams.markdown b/getting-started/enumerables-and-streams.markdown index 07416f5d6..3af3fb77f 100644 --- a/getting-started/enumerables-and-streams.markdown +++ b/getting-started/enumerables-and-streams.markdown @@ -30,7 +30,7 @@ iex> Enum.reduce(1..3, 0, &+/2) 6 ``` -Since the Enum module was designed to work across different data types, its API is limited to functions that are useful across many data types. For specific operations, you may need to reach to modules specific to the data types. For example, if you want to insert an element at a given position in a list, you should use the `List.insert_at/3` function from [the `List` module](/docs/stable/elixir/List.html), as it would make little sense to insert a value into, for example, a range. +Since the Enum module was designed to work across different data types, its API is limited to functions that are useful across many data types. For specific operations, you may need to reach for modules specific to the data type. For example, if you want to insert an element at a given position in a list, you should use the `List.insert_at/3` function from [the `List` module](/docs/stable/elixir/List.html), as it would make little sense to insert a value into, for example, a range. We say the functions in the `Enum` module are polymorphic because they can work with diverse data types. In particular, the functions in the `Enum` module can work with any data type that implements [the `Enumerable` protocol](/docs/stable/elixir/Enumerable.html). We are going to discuss Protocols in a later chapter, for now we are going to move on to a specific kind of enumerable called streams. @@ -91,7 +91,7 @@ iex> 1..100_000 |> Stream.map(&(&1 * 3)) |> Stream.filter(odd?) #Stream<[enum: 1..100000, funs: [...]]> ``` -Many functions in the `Stream` module accept any enumerable as argument and return a stream as result. It also provides functions for creating streams, possibly infinite. For example, `Stream.cycle/1` can be used to create a stream that cycles a given enumerable infinitely. Be careful to not call a function like `Enum.map/2` on such streams, as they would cycle forever: +Many functions in the `Stream` module accept any enumerable as an argument and return a stream as a result. It also provides functions for creating streams, possibly infinite. For example, `Stream.cycle/1` can be used to create a stream that cycles a given enumerable infinitely. Be careful to not call a function like `Enum.map/2` on such streams, as they would cycle forever: ```iex iex> stream = Stream.cycle([1, 2, 3]) @@ -109,7 +109,7 @@ iex> Enum.take(stream, 3) ["h", "e", "ł"] ``` -Another interesting function is `Stream.resource/3` which can be used to wrap around resources, guaranteeing they are opened right before enumeration and closed afterwards, even in case of failures. For example, we can use it to stream a file: +Another interesting function is `Stream.resource/3` which can be used to wrap around resources, guaranteeing they are opened right before enumeration and closed afterwards, even in the case of failures. For example, we can use it to stream a file: ```iex iex> stream = File.stream!("path/to/file") @@ -119,6 +119,6 @@ iex> Enum.take(stream, 10) The example above will fetch the first 10 lines of the file you have selected. This means streams can be very useful for handling large files or even slow resources like network resources. -The amount of functions and functionality in [`Enum`](/docs/stable/elixir/Enum.html) and [`Stream`](/docs/stable/elixir/Stream.html) modules can be daunting at first but you will get familiar with them case by case. In particular, focus on the `Enum` module first and only move to `Stream` for the particular scenarios where laziness is required to either deal with slow resources or large, possibly infinite, collections. +The amount of functions and functionality in the [`Enum`](/docs/stable/elixir/Enum.html) and [`Stream`](/docs/stable/elixir/Stream.html) modules can be daunting at first, but you will get familiar with them case by case. In particular, focus on the `Enum` module first and only move to `Stream` for the particular scenarios where laziness is required, to either deal with slow resources or large, possibly infinite, collections. Next we'll look at a feature central to Elixir, Processes, which allows us to write concurrent, parallel and distributed programs in an easy and understandable way. diff --git a/getting-started/introduction.markdown b/getting-started/introduction.markdown index 68da0c680..456585928 100644 --- a/getting-started/introduction.markdown +++ b/getting-started/introduction.markdown @@ -74,8 +74,8 @@ When going through this getting started guide, it is common to have questions, a * [elixir-talk mailing list](https://groups.google.com/group/elixir-lang-talk) * [elixir tag on StackOverflow](https://stackoverflow.com/questions/tagged/elixir) -When doing so, remember those two tips: +When doing so, remember these two tips: * Instead of asking "how to do X in Elixir", ask "how to solve Y in Elixir". In other words, don't ask how to implement a particular solution, instead describe the problem at hand. Stating the problem gives more context and less bias for a correct answer. - * In case things are not working as expected, please include as much information in your report, for example: your Elixir version, the code snippet and the error message along side the error stacktrace. Use sites like [Gist](https://gist.github.com/) to paste this information. + * In case things are not working as expected, please include as much information as you can in your report, for example: your Elixir version, the code snippet and the error message alongside the error stacktrace. Use sites like [Gist](https://gist.github.com/) to paste this information. diff --git a/getting-started/io-and-the-file-system.markdown b/getting-started/io-and-the-file-system.markdown index 820b0dfd7..afaec0446 100644 --- a/getting-started/io-and-the-file-system.markdown +++ b/getting-started/io-and-the-file-system.markdown @@ -163,8 +163,8 @@ hello world However, this requires some attention. A list may represent either a bunch of bytes or a bunch of characters and which one to use depends on the encoding of the IO device. If the file is opened without encoding, the file is expected to be in raw mode, and the functions in the `IO` module starting with `bin*` must be used. Those functions expect an `iodata` as argument; i.e., they expect a list of integers representing bytes and binaries to be given. -On the other hand, `:stdio` and files opened with `:utf8` encoding work with the remaining functions in the `IO` module. Those functions expect a `char_data` as argument, that is, a list of characters or strings. +On the other hand, `:stdio` and files opened with `:utf8` encoding work with the remaining functions in the `IO` module. Those functions expect a `char_data` as an argument, that is, a list of characters or strings. -Although this is a subtle difference, you only need to worry about those details if you intend to pass lists to those functions. Binaries are already represented by the underlying bytes and as such their representation is always raw. +Although this is a subtle difference, you only need to worry about these details if you intend to pass lists to those functions. Binaries are already represented by the underlying bytes and as such their representation is always raw. This finishes our tour of IO devices and IO related functionality. We have learned about four Elixir modules - [`IO`](/docs/stable/elixir/IO.html), [`File`](/docs/stable/elixir/File.html), [`Path`](/docs/stable/elixir/Path.html) and [`StringIO`](/docs/stable/elixir/StringIO.html) - as well as how the VM uses processes for the underlying IO mechanisms and how to use `chardata` and `iodata` for IO operations. diff --git a/getting-started/maps-and-dicts.markdown b/getting-started/maps-and-dicts.markdown index 36040cf95..0f420d8cf 100644 --- a/getting-started/maps-and-dicts.markdown +++ b/getting-started/maps-and-dicts.markdown @@ -60,7 +60,7 @@ query = from w in Weather, select: w ``` -Those features are what prompted keyword lists to be the default mechanism for passing options to functions in Elixir. In chapter 5, when we discussed the `if/2` macro, we mentioned the following syntax is supported: +These features are what prompted keyword lists to be the default mechanism for passing options to functions in Elixir. In chapter 5, when we discussed the `if/2` macro, we mentioned the following syntax is supported: ```iex iex> if false, do: :this, else: :that @@ -76,7 +76,7 @@ iex> if(false, [do: :this, else: :that]) In general, when the keyword list is the last argument of a function, the square brackets are optional. -In order to manipulate keyword lists, Elixir provides [the `Keyword` module](/docs/stable/elixir/Keyword.html). Remember though keyword lists are simply lists, and as such they provide the same linear performance characteristics as lists. The longer the list, the longer it will take to find a key, to count the number of items, and so on. For this reason, keyword lists are used in Elixir mainly as options. If you need to store many items or guarantee one-key associates with at maximum one-value, you should use maps instead. +In order to manipulate keyword lists, Elixir provides [the `Keyword` module](/docs/stable/elixir/Keyword.html). Remember, though, keyword lists are simply lists, and as such they provide the same linear performance characteristics as lists. The longer the list, the longer it will take to find a key, to count the number of items, and so on. For this reason, keyword lists are used in Elixir mainly as options. If you need to store many items or guarantee one-key associates with at maximum one-value, you should use maps instead. Although we can pattern match on keyword lists, it is rarely done in practice since pattern matching on lists require the number of items and their order to match: @@ -215,6 +215,6 @@ The `Dict` module allows any developer to implement their own variation of `Dict That said, you may be wondering, which of `Keyword`, `Map` or `Dict` modules should you use in your code? The answer is: it depends. -If your code is expecting one specific data structure as argument, use the respective module as it leads to more assertive code. For example, if you expect a keyword as an argument, explicitly use the `Keyword` module instead of `Dict`. However, if your API is meant to work with any dictionary, use the `Dict` module (and make sure to write tests that pass different dict implementations as arguments). +If your code is expecting one specific data structure as an argument, use the respective module as it leads to more assertive code. For example, if you expect a keyword as an argument, explicitly use the `Keyword` module instead of `Dict`. However, if your API is meant to work with any dictionary, use the `Dict` module (and make sure to write tests that pass different dictionary implementations as arguments). -This concludes our introduction to associative data structures in Elixir. You will find out that given keyword lists and maps, you will always have the right tool to tackle problems that require associative data structures in Elixir. +This concludes our introduction to associative data structures in Elixir. You will find out that, given keyword lists and maps, you will always have the right tool to tackle problems that require associative data structures in Elixir. diff --git a/getting-started/module-attributes.markdown b/getting-started/module-attributes.markdown index caa0f5fcf..5956c26ae 100644 --- a/getting-started/module-attributes.markdown +++ b/getting-started/module-attributes.markdown @@ -150,7 +150,7 @@ Plug.Adapters.Cowboy.http MyPlug, [] In the example above, we have used the `plug/1` macro to connect functions that will be invoked when there is a web request. Internally, every time you call `plug/1`, the Plug library stores the given argument in a `@plugs` attribute. Just before the module is compiled, Plug runs a callback that defines a function (`call/2`) which handles http requests. This function will run all plugs inside `@plugs` in order. -In order to understand the underlying code, we'd need macros, so we will revisit this pattern in the meta-programming guide. However the focus here is exactly on how using module attributes as storage allow developers to create DSLs. +In order to understand the underlying code, we'd need macros, so we will revisit this pattern in the meta-programming guide. However the focus here is on how using module attributes as storage allows developers to create DSLs. Another example comes from [the ExUnit framework](/docs/stable/ex_unit/) which uses module attributes as annotation and storage: diff --git a/getting-started/processes.markdown b/getting-started/processes.markdown index 1e763997a..3431b1045 100644 --- a/getting-started/processes.markdown +++ b/getting-started/processes.markdown @@ -166,7 +166,7 @@ Function: #Function<20.90072148/0 in :erl_eval.expr/5> (stdlib) proc_lib.erl:239: :proc_lib.init_p_do_apply/3 ``` -Besides providing better error logging, there are a couple other differences: `start/1` and `start_link/1` return `{:ok, pid}` rather than just the PID. This is what enables Tasks to be used in supervision trees. Furthermore, tasks provides convenience functions, like `Task.async/1` and `Task.await/1`, and functionality to ease distribution. +Besides providing better error logging, there are a couple of other differences: `start/1` and `start_link/1` return `{:ok, pid}` rather than just the PID. This is what enables Tasks to be used in supervision trees. Furthermore, Tasks provides convenience functions, like `Task.async/1` and `Task.await/1`, and functionality to ease distribution. We will explore those functionalities in the ***Mix and OTP guide***, for now it is enough to remember to use Tasks to get better logging. @@ -194,7 +194,7 @@ defmodule KV do end ``` -Note that the `start_link` function basically spawns a new process that runs the `loop/1` function, starting with an empty map. The `loop/1` function then waits for messages and performs the appropriate action for each message. In case of a `:get` message, it sends a message back to the caller and calls `loop/1` again, to wait for a new message. While the `:put` message actually invokes `loop/1` with a new version of the map, with the given `key` and `value` stored. +Note that the `start_link` function basically spawns a new process that runs the `loop/1` function, starting with an empty map. The `loop/1` function then waits for messages and performs the appropriate action for each message. In the case of a `:get` message, it sends a message back to the caller and calls `loop/1` again, to wait for a new message. While the `:put` message actually invokes `loop/1` with a new version of the map, with the given `key` and `value` stored. Let's give it a try by running `iex kv.exs`: @@ -231,7 +231,7 @@ iex> flush :world ``` -Using processes around state and name registering are very common patterns in Elixir applications. However, most of the time, we won't implement those patterns manually as above, but by using one of the many of the abstractions that ships with Elixir. For example, Elixir provides [agents](/docs/stable/elixir/Agent.html) which are simple abstractions around state: +Using processes around state and name registering are very common patterns in Elixir applications. However, most of the time, we won't implement those patterns manually as above, but by using one of the many abstractions that ships with Elixir. For example, Elixir provides [agents](/docs/stable/elixir/Agent.html), which are simple abstractions around state: ```iex iex> {:ok, pid} = Agent.start_link(fn -> %{} end) diff --git a/getting-started/recursion.markdown b/getting-started/recursion.markdown index bb80fb61b..33d2576f2 100644 --- a/getting-started/recursion.markdown +++ b/getting-started/recursion.markdown @@ -46,10 +46,10 @@ The first clause has a guard which says "use this definition if and only if `n` The second definition matches the pattern and has no guard so it will be executed. It first prints our `msg` and then calls itself passing `n - 1` (`2`) as the second argument. -Our `msg` is printed and `print_multiple_times/2` is called again this time with the second argument set to `1`. +Our `msg` is printed and `print_multiple_times/2` is called again, this time with the second argument set to `1`. Because `n` is now set to `1`, the guard in our first definition of `print_multiple_times/2` evaluates to true, and we execute this particular definition. The `msg` is printed, and there is nothing left to execute. -We defined `print_multiple_times/2` so that no matter what number is passed as the second argument it either triggers our first definition (known as a _base case_) or it triggers our second definition which will ensure that we get exactly one step closer to our base case. +We defined `print_multiple_times/2` so that, no matter what number is passed as the second argument, it either triggers our first definition (known as a _base case_) or it triggers our second definition, which will ensure that we get exactly one step closer to our base case. ## Reduce and map algorithms @@ -106,7 +106,7 @@ iex math.exs iex> Math.double_each([1, 2, 3]) #=> [2, 4, 6] ``` -Here we have used recursion to traverse a list doubling each element and returning a new list. The process of taking a list and _mapping_ over it is known as a _map algorithm_. +Here we have used recursion to traverse a list, doubling each element and returning a new list. The process of taking a list and _mapping_ over it is known as a _map algorithm_. Recursion and [tail call](https://en.wikipedia.org/wiki/Tail_call) optimization are an important part of Elixir and are commonly used to create loops. However, when programming in Elixir you will rarely use recursion as above to manipulate lists. diff --git a/getting-started/sigils.markdown b/getting-started/sigils.markdown index b5ae8be92..32db34c9c 100644 --- a/getting-started/sigils.markdown +++ b/getting-started/sigils.markdown @@ -10,7 +10,7 @@ redirect_from: /getting_started/18.html We have already learned that Elixir provides double-quoted strings and single-quoted char lists. However, this only covers the surface of structures that have textual representation in the language. Atoms, for example, are mostly created via the `:atom` representation. -One of Elixir's goals is extensibility: developers should be able to extend the language to fit any particular domain. Computer science has become such a wide field that it is impossible for a language to tackle many fields as part of its core. Our best bet is to rather make the language extensible, so developers, companies and communities can extend the language to their relevant domains. +One of Elixir's goals is extensibility: developers should be able to extend the language to fit any particular domain. Computer science has become such a wide field that it is impossible for a language to tackle many fields as part of its core. Rather, our best bet is to make the language extensible, so developers, companies and communities can extend the language to their relevant domains. In this chapter, we are going to explore sigils, which are one of the mechanisms provided by the language for working with textual representations. Sigils start with the tilde (`~`) character which is followed by a letter (which identifies the sigil) and then a delimiter; optionally, modifiers can be added after the final delimiter. @@ -85,7 +85,7 @@ iex> ~w(foo bar bat) ["foo", "bar", "bat"] ``` -The `~w` sigil also accepts the `c`, `s` and `a` modifiers (for char lists, strings and atoms, respectively) which specify the data type of the elements of the resulting list: +The `~w` sigil also accepts the `c`, `s` and `a` modifiers (for char lists, strings and atoms, respectively), which specify the data type of the elements of the resulting list: ```iex iex> ~w(foo bar bat)a @@ -191,4 +191,4 @@ iex> ~i(42)n -42 ``` -Sigils can also be used to do compile-time work with the help of macros. For example, regular expressions in Elixir are compiled into an efficient representation during compilation of the source code, therefore skipping this step at runtime. If you're interested in the subject, we recommend you to learn more about macros and check out how sigils are implemented in the `Kernel` module (where the `sigil_*` functions are defined). +Sigils can also be used to do compile-time work with the help of macros. For example, regular expressions in Elixir are compiled into an efficient representation during compilation of the source code, therefore skipping this step at runtime. If you're interested in the subject, we recommend you learn more about macros and check out how sigils are implemented in the `Kernel` module (where the `sigil_*` functions are defined). diff --git a/getting-started/try-catch-and-rescue.markdown b/getting-started/try-catch-and-rescue.markdown index ee68e3cbb..0bcdd1a09 100644 --- a/getting-started/try-catch-and-rescue.markdown +++ b/getting-started/try-catch-and-rescue.markdown @@ -70,7 +70,7 @@ iex> try do "Error!" ``` -In practice, however, Elixir developers rarely use the `try/rescue` construct. For example, many languages would force you to rescue an error when a file cannot be opened successfully. Elixir instead provides a `File.read/1` function which returns a tuple containing informations about whether the file was successfully opened: +In practice, however, Elixir developers rarely use the `try/rescue` construct. For example, many languages would force you to rescue an error when a file cannot be opened successfully. Elixir instead provides a `File.read/1` function which returns a tuple containing information about whether the file was opened successfully: ```iex iex> File.read "hello" @@ -102,7 +102,7 @@ iex> File.read! "unknown" Many functions in the standard library follow the pattern of having a counterpart that raises an exception instead of returning tuples to match against. The convention is to create a function (`foo`) which returns `{:ok, result}` or `{:error, reason}` tuples and another function (`foo!`, same name but with a trailing `!`) that takes the same arguments as `foo` but which raises an exception if there's an error. `foo!` should return the result (not wrapped in a tuple) if everything goes fine. The [`File` module](/docs/stable/elixir/File.html) is a good example of this convention. -In Elixir, we avoid using `try/rescue` because **we don't use errors for control flow**. We take errors literally: they are reserved to unexpected and/or exceptional situations. In case you actually need flow control constructs, *throws* should be used. That's what we are going to see next. +In Elixir, we avoid using `try/rescue` because **we don't use errors for control flow**. We take errors literally: they are reserved for unexpected and/or exceptional situations. In case you actually need flow control constructs, *throws* should be used. That's what we are going to see next. ## Throws @@ -202,4 +202,4 @@ iex> what_happened :rescued ``` -This finishes our introduction to `try`, `catch` and `rescue`. You will find they are used less frequently in Elixir than in other languages although they may be handy in some situations where a library or some particular code is not playing "by the rules". +This finishes our introduction to `try`, `catch` and `rescue`. You will find they are used less frequently in Elixir than in other languages, although they may be handy in some situations where a library or some particular code is not playing "by the rules". diff --git a/getting-started/where-to-go-next.markdown b/getting-started/where-to-go-next.markdown index fa717c5c1..34426c1de 100644 --- a/getting-started/where-to-go-next.markdown +++ b/getting-started/where-to-go-next.markdown @@ -22,13 +22,13 @@ We have written a guide that covers how to build an Elixir application, with its ## Meta-programming -Elixir is an extensible and very customizable programming language thanks to its meta-programming support. Most meta-programming in Elixir is done through macros, which are very useful in several situations, especially for writing DSLs. We have written a short guide that explains the basic mechanisms behind macros and shows how to write macros and use them to create DSLs: +Elixir is an extensible and very customizable programming language thanks to its meta-programming support. Most meta-programming in Elixir is done through macros, which are very useful in several situations, especially for writing DSLs. We have written a short guide that explains the basic mechanisms behind macros, shows how to write macros, and how to use macros to create DSLs: * [Meta-programming in Elixir](/getting-started/meta/quote-and-unquote.html) ## Community and other resources -We have a [Learning](/learning.html) section that explores books, screencasts and other resources for learning Elixir and explore the ecosystem. There are also plenty of Elixir resources out there, like conference talks, open source projects, and other learning material produced by the community. +We have a [Learning](/learning.html) section that suggests books, screencasts and other resources for learning Elixir and exploring the ecosystem. There are also plenty of Elixir resources out there, like conference talks, open source projects, and other learning material produced by the community. Remember that in case of any difficulties, you can always visit the **#elixir-lang** channel on **irc.freenode.net** or send a message to the [mailing list](https://groups.google.com/group/elixir-lang-talk). You can be sure that there will be someone willing to help. To keep posted on the latest news and announcements, follow the [blog](/blog/) and follow the language development on the [elixir-core mailing list](https://groups.google.com/group/elixir-lang-core).