Skip to content

Commit b7fb1f4

Browse files
committed
Chapter about typespecs and behaviours
This commit adds the first draft of a chapter about typespecs and behaviours. With the current version of the "Getting started" guide, this chapter becomes chapter 20 while the "Where to go next?" chapter becomes chapter 21; for this reason, I also updated the chapter numbers accordingly where needed.
1 parent 335c0c5 commit b7fb1f4

File tree

3 files changed

+162
-20
lines changed

3 files changed

+162
-20
lines changed

_layouts/getting_started.html

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,8 @@ <h3 class="widget-title">Getting Started</h3>
2929
<li><a class="spec" href="/getting_started/17.html">try, catch and rescue</a></li>
3030
<li><a class="spec" href="/getting_started/18.html">Comprehensions</a></li>
3131
<li><a class="spec" href="/getting_started/19.html">Sigils</a></li>
32-
<li><a class="spec" href="/getting_started/20.html">Where to go next</a></li>
32+
<li><a class="spec" href="/getting_started/20.html">Typespecs and behaviours</a></li>
33+
<li><a class="spec" href="/getting_started/21.html">Where to go next</a></li>
3334
</ol>
3435
</div>
3536
<div class="widget">

getting_started/20.markdown

Lines changed: 116 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,44 +1,141 @@
11
---
22
layout: getting_started
3-
title: 20 Where to go next
3+
title: 20 Typespecs and behaviours
44
guide: 20
5-
last: true
65
---
76

87
# {{ page.title }}
98

109
{% include toc.html %}
1110

12-
Eager to learn more? Keep on reading!
11+
## 20.1 Types and specs
1312

14-
## 20.1 Build your first Elixir project
13+
Elixir is a dynamically typed language, so all types in Elixir are inferred by the runtime. Nonetheless, Elixir comes with **typespecs**, which are a notation used for:
1514

16-
In order to get your first project started, Elixir ships with a build tool called Mix. You can get your new project started by simply running:
15+
1. declaring custom data types;
16+
2. declaring typed function signatures (specifications).
1717

18-
mix new path/to/new/project
18+
### 20.1.1 Function specifications
1919

20-
We have written a guide that covers how to build an Elixir application, with its own supervision tree, configuration, tests and more. The application works as a distributed key-value store where we organize key-value pairs into buckets and distribute those buckets across multiple nodes:
20+
By default, Elixir provides some basic types, such as `integer` or `pid`, as well as more complex types: for example, the `round/1` function, which rounds a float to its nearest integer, takes a `number` as an argument (an `integer` or a `float`) and returns a `float`. As you can see [in its documentation](http://elixir-lang.org/docs/stable/elixir/Kernel.html#round/1), `round/1`'s typed signature is written as:
2121

22-
* [Mix and OTP](/getting_started/mix_otp/1.html)
22+
```
23+
round(number) :: integer
24+
```
2325

24-
## 20.2 Community and other resources
26+
`::` means that the function on the left side *returns* a value whose type is what's on the right side. Function specs are written with the `@spec` directive, placed right before the function definition. The `round/1` function could be written as:
2527

26-
On the sidebar, you can find the link to some Elixir books and screencasts. There are plenty of Elixir resources out there, like conference talks, open source projects, and other learning materials produced by the community.
28+
```elixir
29+
@spec round(number) :: integer
30+
def round(number), do: # implementation...
31+
```
2732

28-
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](http://groups.google.com/group/elixir-lang-talk). You can be sure that there will be someone willing to help. And to keep posted on the latest news and announcements, follow the [blog](/blog/) and follow language developments on the [elixir-core mailing list](http://groups.google.com/group/elixir-lang-core).
33+
Elixir supports compound types as well. For example, a list of integers has type `[integer]`. You can see all the types provided by Elixir [in the typespecs docs](http://elixir-lang.org/docs/stable/elixir/Kernel.Typespec.html).
2934

30-
Don't forget [you can also check the source code of Elixir itself](https://github.com/elixir-lang/elixir), which is mostly written in Elixir (mainly the `lib` directory), or [explore Elixir's documentation](/docs.html).
35+
### 20.1.2 Defining custom types
3136

32-
## 20.3 A Byte of Erlang
37+
While Elixir provides a lot of useful built-in types, it's convenient to define custom types when appropriate. This can be done when defining modules modules through the `@type` directive.
3338

34-
As the main page of this site puts it:
39+
Say we have a `RudeCalculator` module, which performs the usual arithmetic operations (sum, product and so on) but, instead of returning numbers, it returns tuples with the result of an operation as the first element and a random offense as the second element.
3540

36-
> Elixir is a programming language built on top of the Erlang VM.
41+
```elixir
42+
defmodule LousyCalculator do
43+
@spec add(number, number) :: {number, String.t}
44+
def add(x, y), do: {x + y, "You need a calculator to do that?!"}
3745

38-
Sooner or later, an Elixir developer will want to interface with existing Erlang libraries. Here's a list of online resources that cover Erlang's fundamentals and its more advanced features:
46+
@spec multiply(number, number) :: {number, String.t}
47+
def multiply(x, y), do: {x * y, "Jeez, come on!"}
48+
end
49+
```
3950

40-
* This [Erlang Syntax: A Crash Course](/crash-course.html) provides a concise intro to Erlang's syntax. Each code snippet is accompanied by equivalent code in Elixir. This is an opportunity for you to not only get some exposure to Erlang's syntax but also review some of the things you have learned in this guide.
51+
As you can see in the example, tuples are a compound type and each tuple is identified by the types inside it. To understand why `String.t` is not written as `string`, have another look at the [typespecs docs](http://elixir-lang.org/docs/stable/elixir/Kernel.Typespec.html).
4152

42-
* Erlang's official website has a short [tutorial](http://www.erlang.org/course/concurrent_programming.html) with pictures that briefly describe Erlang's primitives for concurrent programming.
53+
Defining function specs this way works, but it quickly becomes annoying since we're repeating the type `{number, String.t}` over and over. We can use the `@type` directory in order to declare our own custom type.
4354

44-
* [Learn You Some Erlang for Great Good!](http://learnyousomeerlang.com/) is an excellent introduction to Erlang, its design principles, standard library, best practices and much more. If you are serious about Elixir, you'll want to get a solid understanding of Erlang principles. Once you have read through the crash course mentioned above, you'll be able to safely skip the first couple of chapters in the book that mostly deal with the syntax. When you reach [The Hitchhiker's Guide to Concurrency](http://learnyousomeerlang.com/the-hitchhikers-guide-to-concurrency) chapter, that's where the real fun starts.
55+
```elixir
56+
defmodule LousyCalculator do
57+
@typedoc """
58+
Just a number followed by a string.
59+
"""
60+
@type number_with_offense :: {number, String.t}
61+
62+
@spec add(number, number) :: number_with_offense
63+
def add(x, y), do: {x + y, "You need a calculator to do that?!"}
64+
65+
@spec multiply(number, number) :: number_with_offense
66+
def multiply(x, y), do: {x * y, "Jeez, come on!"}
67+
end
68+
```
69+
70+
The `@typedoc` directive, similarly to the `@doc` and `@moduledoc` directives, is used to document custom types.
71+
72+
Custom types defined through `@type` are exported and available outside the module they're defined in:
73+
74+
```elixir
75+
defmodule PoliteCalculator do
76+
@spec add(number, number) :: number
77+
def add(x, y), do: make_polite(LousyCalculator.add(x, y))
78+
79+
@spec make_polite(LousyCalculator.number_with_offense) :: number
80+
defp make_polite({num, _offense}), do: num
81+
end
82+
```
83+
84+
If you want to keep a custom type private, you can use the `@typep` directive instead of `@type`.
85+
86+
### 20.1.3 Static code analysis
87+
88+
Typespecs are not only useful to developers and as additional documentation. The Erlang tool [Dyalizer](http://www.erlang.org/doc/man/dialyzer.html), for example, uses typespecs in order to perform static analysis of code. That's why, in the `PoliteCalculator` example, we wrote a spec for the `make_polite/1` function even if it was defined as a private function.
89+
90+
91+
## 20.2 Behaviours
92+
93+
Many modules share the same public API. Take a look at [Plug](https://github.com/elixir-lang/plug), which, as it description states, is a **specification** for composable modules in web applications. Each *plug* is a module which **has to** implement at least two public functions: `init/1` and `call/2`.
94+
95+
Behaviors provide a way to:
96+
97+
* define a set of functions that have to be implemented by a module;
98+
* ensure that a module implements all the functions in that set.
99+
100+
If you have to, you can think of behaviours like interfaces in object oriented languages like Java: a set of function signatures that a module has to implement.
101+
102+
### 20.2.1 Defining behaviours
103+
104+
Say we have want to implement a bunch of parsers, each parsing structured data: for example, a JSON parser and a YAML parser. Each of these two parsers will *behave* the same way: both will provide a `parse/1` function and a `extensions/0` function. The `parse/1` function will return an Elixir representation of the structured data, while the `extensions/0` function will return a list of file extensions that can be used for each type of data (e.g., `.json` for JSON files).
105+
106+
We can create a `Parser` behaviour:
107+
108+
```elixir
109+
defmodule Parser do
110+
use Behaviour
111+
112+
defcallback parse(String.t) :: any
113+
defcallback extensions() :: [String.t]
114+
end
115+
```
116+
117+
Modules adopting the `Parser` behaviour will have to implement all the functions defined with `defcallback`. As you can see, `defcallback` expects a function name but also a function specification like the ones used with the `@spec` directive we saw above.
118+
119+
### 20.2.2 Adopting behaviours
120+
121+
Adopting a behaviour is straightforward:
122+
123+
```elixir
124+
defmodule JSONParser do
125+
@behaviour Parser
126+
127+
def parse(str), do: # ... parse JSON
128+
def extensions, do: ["json"]
129+
end
130+
```
131+
132+
```elixir
133+
defmodule YAMLParser do
134+
@behaviour Parser
135+
136+
def parse(str), do: # ... parse YAML
137+
def extensions, do: ["yml"]
138+
end
139+
```
140+
141+
If a module adopting a given behaviour doesn't implement one of the callbacks required by that behaviour, a compile-time warning will be generated.

getting_started/21.markdown

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
---
2+
layout: getting_started
3+
title: 21 Where to go next
4+
guide: 21
5+
last: true
6+
---
7+
8+
# {{ page.title }}
9+
10+
{% include toc.html %}
11+
12+
Eager to learn more? Keep on reading!
13+
14+
## 21.1 Build your first Elixir project
15+
16+
In order to get your first project started, Elixir ships with a build tool called Mix. You can get your new project started by simply running:
17+
18+
mix new path/to/new/project
19+
20+
We have written a guide that covers how to build an Elixir application, with its own supervision tree, configuration, tests and more. The application works as a distributed key-value store where we organize key-value pairs into buckets and distribute those buckets across multiple nodes:
21+
22+
* [Mix and OTP](/getting_started/mix_otp/1.html)
23+
24+
## 21.2 Community and other resources
25+
26+
On the sidebar, you can find the link to some Elixir books and screencasts. There are plenty of Elixir resources out there, like conference talks, open source projects, and other learning materials produced by the community.
27+
28+
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](http://groups.google.com/group/elixir-lang-talk). You can be sure that there will be someone willing to help. And to keep posted on the latest news and announcements, follow the [blog](/blog/) and follow language developments on the [elixir-core mailing list](http://groups.google.com/group/elixir-lang-core).
29+
30+
Don't forget [you can also check the source code of Elixir itself](https://github.com/elixir-lang/elixir), which is mostly written in Elixir (mainly the `lib` directory), or [explore Elixir's documentation](/docs.html).
31+
32+
## 21.3 A Byte of Erlang
33+
34+
As the main page of this site puts it:
35+
36+
> Elixir is a programming language built on top of the Erlang VM.
37+
38+
Sooner or later, an Elixir developer will want to interface with existing Erlang libraries. Here's a list of online resources that cover Erlang's fundamentals and its more advanced features:
39+
40+
* This [Erlang Syntax: A Crash Course](/crash-course.html) provides a concise intro to Erlang's syntax. Each code snippet is accompanied by equivalent code in Elixir. This is an opportunity for you to not only get some exposure to Erlang's syntax but also review some of the things you have learned in this guide.
41+
42+
* Erlang's official website has a short [tutorial](http://www.erlang.org/course/concurrent_programming.html) with pictures that briefly describe Erlang's primitives for concurrent programming.
43+
44+
* [Learn You Some Erlang for Great Good!](http://learnyousomeerlang.com/) is an excellent introduction to Erlang, its design principles, standard library, best practices and much more. If you are serious about Elixir, you'll want to get a solid understanding of Erlang principles. Once you have read through the crash course mentioned above, you'll be able to safely skip the first couple of chapters in the book that mostly deal with the syntax. When you reach [The Hitchhiker's Guide to Concurrency](http://learnyousomeerlang.com/the-hitchhikers-guide-to-concurrency) chapter, that's where the real fun starts.

0 commit comments

Comments
 (0)