mirror of
https://github.com/livebook-dev/livebook.git
synced 2025-10-27 13:56:21 +08:00
Add a notebook about the unique features behind Elixir and Livebook (#314)
This commit is contained in:
parent
91a9f62fb9
commit
fcf53c4bf2
4 changed files with 152 additions and 118 deletions
|
|
@ -55,6 +55,11 @@ defmodule Livebook.Notebook.Explore do
|
|||
image_url: "/images/logo.png"
|
||||
)
|
||||
|
||||
defnotebook(:elixir_and_livebook,
|
||||
description: "Learn how to use some of Elixir and Livebook unique features together.",
|
||||
image_url: "/images/live-elixir.png"
|
||||
)
|
||||
|
||||
defnotebook(:intro_to_elixir,
|
||||
description: "New to Elixir? Learn about the language and its core concepts.",
|
||||
image_url: "/images/elixir.png"
|
||||
|
|
@ -90,7 +95,8 @@ defmodule Livebook.Notebook.Explore do
|
|||
@spec notebook_infos() :: list(notebook_info())
|
||||
def notebook_infos() do
|
||||
[
|
||||
@intro_to_livebook
|
||||
@intro_to_livebook,
|
||||
@elixir_and_livebook
|
||||
# @intro_to_elixir, @intro_to_nx, @intro_to_axon, @intro_to_vega_lite
|
||||
]
|
||||
end
|
||||
|
|
|
|||
138
lib/livebook/notebook/explore/elixir_and_livebook.livemd
Normal file
138
lib/livebook/notebook/explore/elixir_and_livebook.livemd
Normal file
|
|
@ -0,0 +1,138 @@
|
|||
# Elixir and Livebook
|
||||
|
||||
## Modules
|
||||
|
||||
You can use code cells to execute any Elixir code:
|
||||
|
||||
```elixir
|
||||
IO.puts("hello world!")
|
||||
```
|
||||
|
||||
But you can define modules inside cells too!
|
||||
|
||||
```elixir
|
||||
defmodule Utils do
|
||||
@doc """
|
||||
Generates a random binary id.
|
||||
"""
|
||||
@spec random_id() :: binary()
|
||||
def random_id() do
|
||||
:crypto.strong_rand_bytes(20) |> Base.encode32(case: :lower)
|
||||
end
|
||||
end
|
||||
```
|
||||
|
||||
If you're surprised by the above output, keep in mind that
|
||||
every Elixir expression evaluates to some value and as so
|
||||
does module compilation!
|
||||
|
||||
Having the module defined, let's take it for a spin.
|
||||
|
||||
```elixir
|
||||
Utils.random_id()
|
||||
```
|
||||
|
||||
## Autocompletion
|
||||
|
||||
Elixir code cells also support autocompletion by pressing
|
||||
<kbd>Ctrl</kbd> + <kbd>Spacebar</kbd>. You can try it out by making sure the
|
||||
module in the previous section has been defined and then
|
||||
put the cursor after the `.` below and press <kbd>Ctrl</kbd> + <kbd>Spacebar</kbd>:
|
||||
|
||||
```elixir
|
||||
Utils.
|
||||
```
|
||||
|
||||
You can also press `Tab` to cycle across the different options.
|
||||
|
||||
## Imports
|
||||
|
||||
You can import modules as normally to make the imported functions visible
|
||||
to all subsequent cells. Usually you want to keep `import`, `alias`, and
|
||||
`require` in the first section, as part of the notebook setup.
|
||||
|
||||
For instance, you can import `IEx.Helpers` and bring all of the amazing
|
||||
conveniences in Elixir's shell to your notebook:
|
||||
|
||||
|
||||
```elixir
|
||||
import IEx.Helpers
|
||||
```
|
||||
|
||||
```elixir
|
||||
h(Enum.map())
|
||||
```
|
||||
|
||||
```elixir
|
||||
# Sidenote: http://www.numbat.org.au/thenumbat
|
||||
i("I ❤️ Numbats")
|
||||
```
|
||||
|
||||
## Using packages
|
||||
|
||||
Sometimes you need a dependency or two and notebooks are no exception to this.
|
||||
In Livebook, you can use [`Mix.install/2`](https://hexdocs.pm/mix/Mix.html#install/2)
|
||||
to bring dependencies into your notebook! This approach is especially useful when
|
||||
sharing notebooks because everyone will be able to get the same dependencies.
|
||||
Let's try this out:
|
||||
|
||||
**Note:** compiling dependencies may use a reasonable amount of memory. If you are
|
||||
hosting Livebook, make sure you have enough memory allocated to the Livebook
|
||||
instance, otherwise the command below will fail.
|
||||
|
||||
```elixir
|
||||
Mix.install([
|
||||
{:jason, "~> 1.2"}
|
||||
])
|
||||
```
|
||||
|
||||
```elixir
|
||||
%{elixir: "is awesome"}
|
||||
|> Jason.encode!()
|
||||
|> IO.puts()
|
||||
```
|
||||
|
||||
It is a good idea to specify versions of the installed packages,
|
||||
so that the notebook is easily reproducible later on.
|
||||
|
||||
Also keep in mind that `Mix.install/2` can be called only once
|
||||
per runtime, so if you need to modify the dependencies, you should
|
||||
go to the notebook runtime configuration and **reconnect** the current
|
||||
runtime. Let's learn how to do that.
|
||||
|
||||
## Runtimes
|
||||
|
||||
Livebook has a concept of **runtime**, which in practice is an Elixir node responsible
|
||||
for evaluating your code. You can choose the runtime by clicking the "Runtime" icon
|
||||
on the sidebar (or by using the `rs` keyword shortcut).
|
||||
|
||||
By default, a new Elixir node is started (similarly to starting `iex`). You
|
||||
can click reconnect whenever you want to discard the current node and start
|
||||
a new one.
|
||||
|
||||
You can also choose to run inside a _Mix_ project (as you would with `iex -S mix`),
|
||||
manually _attach_ to an existing distributed node, or run your Elixir notebook
|
||||
_embedded_ within the Livebook source itself.
|
||||
|
||||
## Running tests
|
||||
|
||||
It is also possible to run tests directly from your notebooks.
|
||||
The key is to disable `ExUnit`'s autorun feature and then explicitly
|
||||
run the test suite after all test cases have been defined:
|
||||
|
||||
```elixir
|
||||
ExUnit.start(autorun: false)
|
||||
|
||||
defmodule MyTest do
|
||||
use ExUnit.Case, async: true
|
||||
|
||||
test "it works" do
|
||||
assert true
|
||||
end
|
||||
end
|
||||
|
||||
ExUnit.run()
|
||||
```
|
||||
|
||||
This helps you follow best practices and ensure the code you write
|
||||
behaves as expected!
|
||||
|
|
@ -18,7 +18,7 @@ and run them locally.
|
|||
|
||||
Each notebook consists of a number of cells, which serve as primary building blocks.
|
||||
There are **Markdown** cells (such as this one) that allow you to describe your work
|
||||
and **Elixir** cells where the magic takes place!
|
||||
and **Elixir** cells to run your code!
|
||||
|
||||
To insert a new cell move your cursor between cells and click one of the revealed buttons. 👇
|
||||
|
||||
|
|
@ -72,119 +72,6 @@ with just a few assumptions on how particular elements are represented. Thanks t
|
|||
approach you can easily keep notebooks under version control and get readable diffs.
|
||||
You can also easily preview those files, reuse for blog posts, and even edit in a text editor.
|
||||
|
||||
## Modules
|
||||
|
||||
As we have seen, Elixir cells can be used for working on tiny snippets,
|
||||
but you may as well define a module!
|
||||
|
||||
```elixir
|
||||
defmodule Utils do
|
||||
@doc """
|
||||
Generates a random binary id.
|
||||
"""
|
||||
@spec random_id() :: binary()
|
||||
def random_id() do
|
||||
:crypto.strong_rand_bytes(20) |> Base.encode32(case: :lower)
|
||||
end
|
||||
end
|
||||
```
|
||||
|
||||
If you're surprised by the above output, keep in mind that
|
||||
every Elixir expression evaluates to some value and as so does module compilation!
|
||||
|
||||
Having the module defined, let's take it for a spin.
|
||||
|
||||
```elixir
|
||||
Utils.random_id()
|
||||
```
|
||||
|
||||
## Imports
|
||||
|
||||
You can import modules as normally to make the imported functions visible
|
||||
to all subsequent cells. Usually you want to keep `import`, `alias` and `require`
|
||||
in the first section, as part of the notebook setup.
|
||||
|
||||
```elixir
|
||||
import IEx.Helpers
|
||||
```
|
||||
|
||||
```elixir
|
||||
h(Enum.map())
|
||||
```
|
||||
|
||||
```elixir
|
||||
# Sidenote: http://www.numbat.org.au/thenumbat
|
||||
i("I ❤️ Numbats")
|
||||
```
|
||||
|
||||
## Runtimes
|
||||
|
||||
Livebook has a concept of **runtime**, which in practice is an Elixir node responsible
|
||||
for evaluating your code.
|
||||
|
||||
By default, a new Elixir node is started (similarly to starting `iex`),
|
||||
but you can also choose to run inside a Mix project (as you would with `iex -S mix`)
|
||||
or even manually attach to an existing distributed node!
|
||||
You can configure the runtime by clicking the "Runtime" icon on the sidebar.
|
||||
|
||||
## Using packages
|
||||
|
||||
Sometimes you need a dependency or two and notebooks are no exception to this.
|
||||
|
||||
One way to work with packages is to create a Mix project and configure the notebook
|
||||
to run in its context (as pointed out above). This approach makes sense if you already have
|
||||
a Mix project that you are working on, especially because this makes all project's
|
||||
modules available as well.
|
||||
|
||||
But there are cases when you just want to play around with a new package
|
||||
or quickly prototype some code that relies on such. Fortunately, Elixir v1.12+ ships with
|
||||
[`Mix.install/2`](https://hexdocs.pm/mix/Mix.html#install/2) that allows you to install
|
||||
dependencies into your Elixir runtime! This approach is especially useful when sharing notebooks
|
||||
because everyone will be able to get the same dependencies. Let's try this out:
|
||||
|
||||
**Note:** compiling dependencies may use a reasonable amount of memory. If you are
|
||||
hosting Livebook, make sure you have enough memory allocated to the Livebook
|
||||
instance, otherwise the command below will fail.
|
||||
|
||||
```elixir
|
||||
Mix.install([
|
||||
{:jason, "~> 1.2"}
|
||||
])
|
||||
```
|
||||
|
||||
```elixir
|
||||
%{elixir: "is awesome"}
|
||||
|> Jason.encode!()
|
||||
|> IO.puts()
|
||||
```
|
||||
|
||||
It is a good idea to specify versions of the installed packages,
|
||||
so that the notebook is easily reproducible later on.
|
||||
|
||||
Also keep in mind that `Mix.install/2` can be called only once
|
||||
per runtime, so if you need to modify the dependencies, you should
|
||||
go to the notebook runtime configuration and **reconnect** the current runtime.
|
||||
|
||||
## Running tests
|
||||
|
||||
It is also possible to run tests directly from your notebooks.
|
||||
The key is to disable `ExUnit`'s autorun feature and then explicitly
|
||||
run the test suite after all test cases have been defined:
|
||||
|
||||
```elixir
|
||||
ExUnit.start(autorun: false)
|
||||
|
||||
defmodule MyTest do
|
||||
use ExUnit.Case, async: true
|
||||
|
||||
test "it works" do
|
||||
assert true
|
||||
end
|
||||
end
|
||||
|
||||
ExUnit.run()
|
||||
```
|
||||
|
||||
## Math
|
||||
|
||||
Livebook uses $\\TeX$ syntax for math.
|
||||
|
|
@ -204,10 +91,13 @@ to optimise how you move around. Livebook leverages the concept of
|
|||
Make sure to check out the shortcuts by clicking the "Keyboard" icon in
|
||||
the sidebar or by typing `?`.
|
||||
|
||||
## Final notes
|
||||
## Next steps
|
||||
|
||||
Livebook is an open source project, so feel free to look into
|
||||
[the repository](https://github.com/elixir-nx/livebook)
|
||||
That's our quick your intro to Livebook! Now you are ready to learn
|
||||
how Elixir integrates with Livebook in the ["Elixir and Livebook"](/explore/notebooks/elixir-and-livebook) notebook.
|
||||
|
||||
Finally, remember Livebook is an open source project, so feel free to look
|
||||
into [the repository](https://github.com/elixir-nx/livebook)
|
||||
to contribute, report bugs, suggest features or just skim over the codebase.
|
||||
|
||||
Now go ahead and build something cool! 🚢
|
||||
|
|
|
|||
BIN
priv/static/images/live-elixir.png
Normal file
BIN
priv/static/images/live-elixir.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 18 KiB |
Loading…
Add table
Reference in a new issue