You can create temporary variables that are only in scope briefly using the with
expression. If you define variables using the with
expression, those variables are only in scope within that expression and go out of scope after the expression is complete.
Here's an example of opening a file, with the file handle being a temporary variable.
fifth_line = with {:ok, file} = File.open("data.txt")
do
read_fifth_line(file)
end
In this example a file is opened and pattern matching causes the file handle to be assigned to the variable file
. The fifth line of the file is read and returned from the with
expression. As with a function, the last value of the last expression within a with
expression is returned and is assigned to the fifth_line
variable. The variable file
will go of scope when the with
expression completes.
Since I am not yet familiar with how the File I/O functions in Elixir work, I'm going to do something much simpler in IEx.
iex> number = with sum = Enum.sum(1..10) do
...> sum + 1
...> end
56
In IEx I have to put the do
on the same line as with
, but in source code files, do
can go on the next line.
It's also possible to have multiple lines creating temporary variables in the head of the with
statement that can use temporary variables from previous lines, like so:
customer_names = with db = Database.open("person_data"),
customer_table = Database.table(db, "customer")
customer_record = Database.where(customer_table, fn customer -> customer.age > 18 end)
do
customer_record.first_name <> " " <> customer_record.last_name
end
I did not have a real database, and I don't think there is even a Database
module, so this is a conceptual example rather than an example that you can run.
The db
, customer_table
, and customer_record
variables are all temporary. They can be used in the other other lines in the with
statement header and last until the end
causes them to go out of scope.
The expressions in the header of the with
expression can use pattern matching and even guard clauses, just like a function header.