Permalink
Browse files

Update records chapter

  • Loading branch information...
1 parent f7b9043 commit e26ecdcd6850036af911d3122af8a7e0f641fb33 @josevalim josevalim committed Dec 1, 2012
Showing with 8 additions and 57 deletions.
  1. +8 −57 getting_started/4.markdown
@@ -12,26 +12,25 @@ Elixir provides both records and protocols. This chapter will outline the main f
Records are simple structures that hold values. For example, we can define a `FileInfo` record that is supposed to store information about files as follows:
- defrecord FileInfo, atime: nil, mtime: nil, accesses: 0
+ defrecord FileInfo, atime: nil, accesses: 0
-The line above defines a module named `FileInfo` which contains a function named `new` (that returns a new record) and other functions to read and set the values in the record. Therefore, we can do:
+The line above will define a module named `FileInfo` which contains a function named `new` that returns a new record and other functions to read and set the values in the record:
file_info = FileInfo.new(atime: { 2010, 4, 17 })
file_info.atime #=> Returns the value of atime
file_info.atime({ 2012, 10, 13 }) #=> Updates the value of atime
-Elixir will also define an `update_#{field}` function that accepts a function of one argument. When we invoke the update function, it calls the function we have provided, passing it the current value of the field and updating the field with the value returned from our function:
+A record is simply a tuple where the first element is the record module name. We can get the record raw representation as follow:
+
+ inspect FileInfo.new, raw: true
+ #=> "{ FileInfo, nil, nil }"
+
+Besides defining readers and writers for each attribute, Elixir also defines an `update_#{attribute}` function to update the value. Such functions expect a function as argument that receives the current value and must return the new one. For example, every time the file is accessed, the accesses counter can be incremented with:
file_info = FileInfo.new(accesses: 10)
file_info = file_info.update_accesses(fn(x) -> x + 1 end)
file_info.accesses #=> 11
-Internally, a record is simply a tuple where the first element is always the record module name. In Interactive Elixir (`iex`) (or using IO.inspect), we can get all of the fields of a record:
-
- iex> defrecord FileInfo, atime: nil, mtime: nil
- iex> FileInfo.new
- FileInfo[atime: nil, mtime: nil]
-
### 4.1.1 Pattern matching
Elixir also allows one to pattern match against records. For example, imagine we want to check if a file was accessed or not based on the `FileInfo` record above, we could implement it as follow:
@@ -49,54 +48,6 @@ This syntax can also be used to create new records:
As we are going to see in the next section (4.2), this "brackets syntax" is powered by the access protocol and, in the records case, it is handled at compilation time which provides faster access and creation times compared to `file_info.accesses` and `FileInfo.new`.
-### 4.1.2 Default based functions
-
-Depending on the default value, Elixir will define helpers to interact with the record. For example, the test framework that ships with Elixir, called ExUnit, defines a record which keeps track of how many tests were executed and the failures that happened. The record definition is similar to:
-
- iex> defrecord Config, counter: 0, failures: []
-
-Since `counter` is an integer, Elixir automatically defines a helper named `increment_counter` that will increase the counter value:
-
- iex> new_config = Config.new.increment_counter
- Config[counter: 1, failures: []]
- iex> new_config.counter
- 1
-
-`increment_counter` also accepts a number to increment as argument:
-
- iex> new_config = Config.new.increment_counter 10
- Config[counter: 10, failures: []]
- iex> new_config.counter
- 10
-
-On the other hand if the default value is a list Elixir will define the two following helpers:
-
-* `prepend_field` - Receives another list and prepends its values
-* `merge_field` - Receives a keywords list and merges it into the current value;
-
-Keep in mind that records (as any other data structure) in Elixir are immutable. Every time you update a record's field, a new record is returned with the corresponding field updated. For example:
-
- iex> new_config = Config.new
- Config[counter: 0, failures: []]
- iex> new_config.counter
- 0
- iex> new_config.increment_counter
- Config[counter: 1, []]
-
-Notice how `increment_counter` returned not simply an updated value of the `counter` field, but a whole new record which has its `counter` field set to the old value plus one. What will happen if we call `increment_counter` multiple times?
-
- iex> new_config.increment_counter
- Config[counter: 1, failures: []]
- iex> new_config.increment_counter
- Config[counter: 1, failures: []]
-
-Since `new_config` remains unchanged, we get a new record with the `counter` field's value set to `1` every time we call `increment_counter`. In order to keep the new record, we need to assign it to a variable:
-
- iex> new_config = new_config.increment_counter
- Config[counter: 1, failures: []]
- iex> new_config.increment_counter
- Config[counter: 2, failures: []]
-
For more information on records, [check out the documentation for the `defrecord` macro](http://elixir-lang.org/docs/master/Kernel.html#defrecord/4)
## 4.2 Protocols

0 comments on commit e26ecdc

Please sign in to comment.