Skip to content

Remove mentions to unless/2 in the case/cond/if guide #13852

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Sep 22, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 8 additions & 8 deletions lib/elixir/pages/getting-started/case-cond-and-if.md
Original file line number Diff line number Diff line change
Expand Up @@ -67,24 +67,24 @@ iex> case :ok do

The documentation for the `Kernel` module lists all available guards in its sidebar. You can also consult the complete [Patterns and Guards](../references/patterns-and-guards.md#guards) reference for in-depth documentation.

## if/unless
## if

`case` builds on pattern matching and guards to destructure and match on certain conditions. However, patterns and guards are limited only to certain expressions which are optimized by the compiler. In many situations, you need to write conditions that go beyond what can be expressed with `case`. For those, `if/2` (and `unless/2`) are useful alternatives:
`case` builds on pattern matching and guards to destructure and match on certain conditions. However, patterns and guards are limited only to certain expressions which are optimized by the compiler. In many situations, you need to write conditions that go beyond what can be expressed with `case`. For those, `if/2` is a useful alternative:

```elixir
iex> if true do
...> "This works!"
...> end
"This works!"
iex> unless true do
iex> if false do
...> "This will never be seen"
...> end
nil
```

If the condition given to `if/2` returns `false` or `nil`, the body given between `do`-`end` is not executed and instead it returns `nil`. The opposite happens with `unless/2`.
If the condition given to `if/2` returns `false` or `nil`, the body given between `do`-`end` is not executed and instead it returns `nil`.

They also support `else` blocks (although using `else` with `unless` is generally discouraged):
`if/2` also supports `else` blocks:

```elixir
iex> if nil do
Expand Down Expand Up @@ -121,9 +121,9 @@ iex> x = if true do
2
```

> #### `if` and `unless` are macros {: .info}
> #### `if` is a macro {: .info}
>
> An interesting note regarding `if/2` and `unless/2` is that they are implemented as macros in the language: they aren't special language constructs as they would be in many languages. You can check the documentation and their source for more information.
> An interesting note regarding `if/2` is that it is implemented as a macro in the language: it isn't a special language construct as it would be in many languages. You can check the documentation and its source for more information.

If you find yourself nesting several `if/2` blocks, you may want to consider using `cond/1` instead. Let's check it out.

Expand Down Expand Up @@ -159,7 +159,7 @@ iex> cond do
"This is always true (equivalent to else)"
```

Similar to `if/2` and `unless/2`, `cond` considers any value besides `nil` and `false` to be true:
Similar to `if/2`, `cond` considers any value besides `nil` and `false` to be true:

```elixir
iex> cond do
Expand Down
11 changes: 7 additions & 4 deletions lib/elixir/pages/meta-programming/macros.md
Original file line number Diff line number Diff line change
Expand Up @@ -84,17 +84,20 @@ end

`Macro.expand_once/2` receives a quoted expression and expands it according to the current environment. In this case, it expanded/invoked the `Unless.macro_unless/2` macro and returned its result. We then proceeded to convert the returned quoted expression to a string and print it (we will talk about `__ENV__` later in this chapter).

That's what macros are all about. They are about receiving quoted expressions and transforming them into something else. In fact, `unless/2` in Elixir is implemented as a macro:
That's what macros are all about. They are about receiving quoted expressions and transforming them into something else.
In fact, `if/2` in Elixir is implemented as a macro:

```elixir
defmacro unless(clause, do: expression) do
defmacro if(clause, do: expression) do
quote do
if(!unquote(clause), do: unquote(expression))
case clause do
x when x in [false, nil] -> nil
_ -> unquote(expression)
end
end
```

Constructs such as `unless/2`, `defmacro/2`, `def/2`, `defprotocol/2`, and many others used throughout the Elixir standard library are written in pure Elixir, often as a macro. This means that the constructs being used to build the language can be used by developers to extend the language to the domains they are working on.
Constructs such as `if/2`, `defmacro/2`, `def/2`, `defprotocol/2`, and many others used throughout the Elixir standard library are written in pure Elixir, often as a macro. This means that the constructs being used to build the language can be used by developers to extend the language to the domains they are working on.

We can define any function and macro we want, including ones that override the built-in definitions provided by Elixir. The only exceptions are Elixir special forms which are not implemented in Elixir and therefore cannot be overridden. The full list of special forms is available in `Kernel.SpecialForms`.

Expand Down