Эликсир сложного паттерна - PullRequest
2 голосов
/ 07 марта 2019

Я читаю замечательную Радость эликсира и пытаюсь обернуть голову вокруг порядка операций в примере сопоставления с образцом.

У меня есть список

crew = [  
    %{name: "mal", age: 40},
    %{name: "zoey", age: 36},
]

Теперь я могу использовать сопоставление с образцом, чтобы взять первый элемент списка и назначить имя другой переменной, например

[first = %{name: first_name} | others] = crew

Я понимаю, что первый элемент в crew был присвоен first, а name из first был присвоен first_name:

iex> first
%{age: 40, name: "mal"}
iex> first_name
"mal"

. В соответствии с примерами я также могу присвоить имя другой переменной справаслева:

%{name: first_name2} = first

Но то же самое не получается, когда я пробую это слева направо:

iex> first = %{name: first_name3}
** (CompileError) iex:33: undefined function first_name3/0
    (stdlib) lists.erl:1354: :lists.mapfoldl/3
    (stdlib) lists.erl:1355: :lists.mapfoldl/3

Мой вопрос: почему слева налевоПравильно ли присвоение ОК при сопоставлении списков, но не за пределами сопоставления списков?

Ответы [ 2 ]

2 голосов
/ 07 марта 2019

Правая часть = (оператор совпадения) вычисляется первой.В выражении

 first = %{name: first_name3}

Он пытается получить значение first_name3, но в области действия нет first_name3.

Для выражения

[first = %{name: first_name} | others] = crew

вы можете думать об этом как

[first = %{name: first_name} = %{age: 40, name: "mal"} | others] = crew

или

others = tl(crew)
head = hd(crew)
first = %{name: first_name} = head

Вот еще один пример:

x = "foo" связывает переменную x со строкой "foo"(потому что x сначала не связан).Теперь, когда x привязан к "foo", "foo" = x также является допустимым выражением, поскольку "foo" соответствует x.

1 голос
/ 07 марта 2019

Это потому, что эликсир оценивает последовательность. Когда вы запустите iex, ваша среда будет пустой. Когда вы наберете first =% {name: first_name3}, оно начнется с оценки правой части. Внутри реальной карты вы пытаетесь связать ключ «имя» с переменной first_name3. Если first_name3 не существует в вашей среде, выражение не будет оценено, и вы получите неопределенную ошибку функции.

это должно работать:

first_name3 = "John"
first = %{name: first_name3}
...