Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
20 changes: 10 additions & 10 deletions lib/elixir/lib/exception.ex
Original file line number Diff line number Diff line change
Expand Up @@ -288,10 +288,10 @@ defmodule Exception do
end
end

defp is_map_node?({:is_map, _, [_]}), do: true
defp is_map_node?(_), do: false
defp is_map_key_node?({:is_map_key, _, [_, _]}), do: true
defp is_map_key_node?(_), do: false
defp map_node?({:is_map, _, [_]}), do: true
defp map_node?(_), do: false
defp map_key_node?({:is_map_key, _, [_, _]}), do: true
defp map_key_node?(_), do: false

defp struct_validation_node?(
{:is_atom, _, [{{:., [], [:erlang, :map_get]}, _, [:__struct__, _]}]}
Expand All @@ -305,16 +305,16 @@ defmodule Exception do

defp struct_validation_node?(_), do: false

defp is_struct_macro?(
defp struct_macro?(
{:and, _,
[
{:and, _, [%{node: node_1 = {_, _, [arg]}}, %{node: node_2 = {_, _, [arg, _]}}]},
%{node: node_3 = {_, _, [{_, _, [_, arg]}]}}
]}
),
do: is_map_node?(node_1) and is_map_key_node?(node_2) and struct_validation_node?(node_3)
do: map_node?(node_1) and map_key_node?(node_2) and struct_validation_node?(node_3)

defp is_struct_macro?(
defp struct_macro?(
{:and, _,
[
{:and, _,
Expand All @@ -329,12 +329,12 @@ defmodule Exception do
%{node: node_3 = {_, _, [{_, _, [_, arg]}, _]}}
]}
),
do: is_map_node?(node_1) and is_map_key_node?(node_2) and struct_validation_node?(node_3)
do: map_node?(node_1) and map_key_node?(node_2) and struct_validation_node?(node_3)

defp is_struct_macro?(_), do: false
defp struct_macro?(_), do: false

defp translate_guard(guard) do
if is_struct_macro?(guard) do
if struct_macro?(guard) do
undo_is_struct_guard(guard)
else
guard
Expand Down
8 changes: 4 additions & 4 deletions lib/elixir/pages/references/patterns-and-guards.md
Original file line number Diff line number Diff line change
Expand Up @@ -378,23 +378,23 @@ However, if your guard has multiple conditions, such as checking for tuples or m
There exists an additional way to simplify a chain of `or` expressions in guards: Elixir supports writing "multiple guards" in the same clause. The following code:

```elixir
def is_number_or_nil(term) when is_integer(term) or is_float(term) or is_nil(term),
def number_or_nil?(term) when is_integer(term) or is_float(term) or is_nil(term),
do: :maybe_number
def is_number_or_nil(_other),
def number_or_nil?(_other),
do: :something_else
```

can be alternatively written as:

```elixir
def is_number_or_nil(term)
def number_or_nil?(term)
when is_integer(term)
when is_float(term)
when is_nil(term) do
:maybe_number
end

def is_number_or_nil(_other) do
def number_or_nil?(_other) do
:something_else
end
```
Expand Down
30 changes: 15 additions & 15 deletions lib/elixir/test/elixir/kernel/guard_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ defmodule Kernel.GuardTest do
defguard is_foo(atom) when atom == :foo
defguard is_equal(foo, bar) when foo == bar

def is_foobar(atom) when is_foo(atom) do
def foobar?(atom) when is_foo(atom) do
is_foo(atom)
end
end
Expand Down Expand Up @@ -151,39 +151,39 @@ defmodule Kernel.GuardTest do
defmodule IntegerPrivateGuards do
defguardp is_even(value) when is_integer(value) and rem(value, 2) == 0

def is_even_and_large?(value) when is_even(value) and value > 100, do: true
def is_even_and_large?(_), do: false
def even_and_large?(value) when is_even(value) and value > 100, do: true
def even_and_large?(_), do: false

def is_even_and_small?(value) do
def even_and_small?(value) do
if is_even(value) and value <= 100, do: true, else: false
end
end

test "defguardp defines private guards that work inside and outside guard clauses" do
assert IntegerPrivateGuards.is_even_and_large?(102)
refute IntegerPrivateGuards.is_even_and_large?(98)
refute IntegerPrivateGuards.is_even_and_large?(99)
refute IntegerPrivateGuards.is_even_and_large?(103)
assert IntegerPrivateGuards.even_and_large?(102)
refute IntegerPrivateGuards.even_and_large?(98)
refute IntegerPrivateGuards.even_and_large?(99)
refute IntegerPrivateGuards.even_and_large?(103)

assert IntegerPrivateGuards.is_even_and_small?(98)
refute IntegerPrivateGuards.is_even_and_small?(99)
refute IntegerPrivateGuards.is_even_and_small?(102)
refute IntegerPrivateGuards.is_even_and_small?(103)
assert IntegerPrivateGuards.even_and_small?(98)
refute IntegerPrivateGuards.even_and_small?(99)
refute IntegerPrivateGuards.even_and_small?(102)
refute IntegerPrivateGuards.even_and_small?(103)

assert_compile_error(~r"cannot find or invoke local is_even/1", fn ->
defmodule IntegerPrivateGuardUtils do
import IntegerPrivateGuards

def is_even_and_large?(value) when is_even(value) and value > 100, do: true
def is_even_and_large?(_), do: false
def even_and_large?(value) when is_even(value) and value > 100, do: true
def even_and_large?(_), do: false
end
end)

assert_compile_error(~r"undefined function is_even/1", fn ->
defmodule IntegerPrivateFunctionUtils do
import IntegerPrivateGuards

def is_even_and_small?(value) do
def even_and_small?(value) do
if is_even(value) and value <= 100, do: true, else: false
end
end
Expand Down
6 changes: 3 additions & 3 deletions lib/elixir/test/elixir/kernel/lexical_tracker_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -406,7 +406,7 @@ defmodule Kernel.LexicalTrackerTest do
{{compile, exports, runtime, _}, _binding} =
Code.eval_string("""
defmodule Kernel.LexicalTrackerTest.StructPattern do
def is_uri(%URI{}), do: true
def uri?(%URI{}), do: true
Kernel.LexicalTracker.references(__ENV__.lexical_tracker)
end |> elem(3)
""")
Expand Down Expand Up @@ -439,8 +439,8 @@ defmodule Kernel.LexicalTrackerTest do
{{compile, exports, runtime, _}, _binding} =
Code.eval_string("""
defmodule Kernel.LexicalTrackerTest.PatternGuardsRuntime do
def is_uri_atom(URI), do: true
def is_range_struct(range) when is_struct(range, Range), do: true
def uri_atom?(URI), do: true
def range_struct?(range) when is_struct(range, Range), do: true
Kernel.LexicalTracker.references(__ENV__.lexical_tracker)
end |> elem(3)
""")
Expand Down
2 changes: 1 addition & 1 deletion lib/mix/test/mix/umbrella_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -454,7 +454,7 @@ defmodule Mix.UmbrellaTest do
# Add struct dependency
File.write!("lib/bar.ex", """
defmodule Bar do
def is_foo_bar(%Foo{bar: true}), do: true
def foo_bar?(%Foo{bar: true}), do: true
end
""")

Expand Down