Ваш код, как указано, не выдает ошибку, о которой вы сказали. Однако, если я немного его почистю, появится ошибка:
italy : String
italy = "italy"
canada : String
canada = "canada"
countryConvert : String -> String
countryConvert country =
case country of
italy -> "Италия"
canada -> "Канада"
Чтобы быть более точным, он выдает эту ошибку с Elm 0.18
. Если вы попытаетесь скомпилировать с 0.19
, вы получите чуть более информативную ошибку:
$ elm make Countries.elm
The name `italy` is first defined here:
5| italy = "italy"
^^^^^
But then it is defined AGAIN over here:
17| italy -> "Италия"
^^^^^
Think of a more helpful name for one of them and you should be all set!
Это все еще может быть немного загадочным, хотя. Главное, что нужно понять, это то, что выражения case
имеют две цели, которые иногда пересекаются: сравнивать отдельные значения или с test значения структуры («форма», на языке сообщения об ошибке 0,18) и значения «деструктура» - присвоение локальных имен частям этой структуры. В руководстве Вяза есть хороший простой пример .
Для сравнения отдельных значений эти значения должны быть in-line в каждом предложении выражения case. Предполагается, что любые переменные, которые вы используете, являются новыми объявлениями , локальными по отношению к этому предложению выражения case.
Таким образом, в вашем выражении case вы не сопоставляете значения, которые italy
и canada
имеют в остальной части вашей программы. Вместо этого вы объявляете две новые локальные переменные , которые просто случаются с , а также с именами italy
и canada
. Другими словами, вы вообще не «разбирали» строку country
- все, что вы сделали, это просто объявили для нее новое локальное имя (italy
). И именно поэтому 0.19
жалуется на слежку. (См. это объяснение , почему теневое копирование является ошибкой, а не просто предупреждением в 0.19.)
Поскольку также нет структурной разницы между предложениями выражения case, 0.18
фактически жалуется на то, что ваши два предложения case идентичны. Каждый будет соответствовать любой строке и назначать ее новой локальной переменной italy
; другая также будет соответствовать любой строке и присвоит ее новой локальной переменной canada
.
Альтернативы, которые будут работать:
Вы можете просто вставить значения:
countryConvert : String -> String
countryConvert country =
case country of
"italy" -> "Италия"
"canada" -> "Канада"
_ -> country
Вы можете использовать простую конструкцию if-else:
countryConvert : String -> String
countryConvert country =
if country == italy then
"Италия"
else if country == canada then
"Канада"
else
country
Или используйте Dict
:
countries : Dict String String
countries =
fromList
[ ( "italy", "Италия" )
, ( "canada", "Канада" )
]
countryConvert : String -> String
countryConvert country =
case get country countries of
Just c ->
c
Nothing ->
country
Обратите внимание, что вам все еще нужно выражение case
с этим подходом. Это потому, что Dict.get
может быть передан ключ, которого нет в Dict. Таким образом, вы можете рассмотреть возможность использования типа возврата вашей функции Maybe String
, чтобы было ясно, что вызывающая сторона может переехать в страну, которую вы не знаете как перевести. И это обязанность вызывающего абонента решить, что делать в этом случае.