Disons que je veux faire correspondre un motif à un texte. Plus précisément, je veux faire correspondre le motif sur la première lettre.
Par exemple, comment créer un modèle qui correspond aux mots "à propos de" et "analogique" mais pas à "bêta"?
J'ai essayé ceci:
defmodule MatchStick do
def doMatch([head | tail]) when head == "a" do 1 end
def doMatch([head | tail]) do 0 end
end
res = MatchStick.doMatch("abcd");
J'ai aussi essayé des listes de personnages:
defmodule MatchStick do
def doMatch([head | tail]) when head == 'a' do 1 end
def doMatch([head | tail]) do 0 end
end
res = MatchStick.doMatch('abcd');
Ni travaillé. Quelle est la bonne façon de faire correspondre le texte?
defmodule MatchStick do
def doMatch("a" <> rest) do 1 end
def doMatch(_) do 0 end
end
Vous devez utiliser l'opérateur de concaténation de chaînes vu ici
Exemple:
iex> "he" <> rest = "hello"
"hello"
iex> rest
"llo"
Dans Elixir, les chaînes simples citées sont assez différentes des chaînes doubles. Les chaînes simples entre guillemets sont essentiellement des listes d'entiers, chaque entier représentant un caractère. Par conséquent, ils s'appellent également des listes de caractères. Ils sont principalement utilisés pour la compatibilité avec Erlang, car c'est ainsi que fonctionnent les chaînes Erlang. Vous pouvez utiliser des chaînes entre guillemets comme vous utiliseriez des listes:
iex> hd('a')
97
iex> [97 | rest] = 'abcd'
'abcd'
iex> rest
'bcd'
iex> 'ab' ++ rest = 'abcd'
'abcd'
iex> rest
'cd'
La fonction de correspondance pour les chaînes entre guillemets ressemblerait à ceci:
def match('a' ++ rest), do: 1
def match(_), do: 0
Elixir vous cachera la liste et l'affichera sous forme de chaîne, lorsque tous les entiers représentent des caractères valides. Pour inciter Elixir à vous montrer la représentation interne d'une liste de caractères, vous pouvez insérer un 0
, qui est un caractère invalide:
iex> string = 'abcd'
'abcd'
iex> string ++ [0]
[97, 98, 99, 100, 0]
Cependant, les chaînes entre guillemets doubles dans Elixir sont généralement utilisées, car elles gèrent correctement UTF-8, sont beaucoup plus faciles à utiliser et sont utilisées par tous les modules Elixir internes (par exemple, le module utile String
). Les chaînes à double guillemet sont des fichiers binaires, vous pouvez donc les traiter comme n'importe quel autre type binaire:
iex> <<97, 98, 99, 100>>
"abcd"
iex> <<1256 :: utf8>>
"Ө"
iex> <<97>> <> rest = "abcd"
"abcd"
iex> rest
"bcd"
iex> "ab" <> rest = "abcd"
"abcd"
iex> rest
"cd"
La fonction de correspondance pour les chaînes à double guillemet ressemblerait à ceci:
def match("a" <> rest), do: 1
def match(_), do: 0
Elixir masquera également la représentation interne des chaînes binaires. Pour le révéler, vous pouvez à nouveau insérer un 0
:
iex> string = "abcd"
"abcd"
iex> string <> <<0>>
<<97, 98, 99, 100, 0>>
Enfin, pour convertir des chaînes entre guillemets simples et des chaînes à guillemets doubles, utilisez les fonctions to_string
et to_char_list
:
iex> to_string('abcd')
"abcd"
iex> to_char_list("abcd")
'abcd'
Pour les détecter, vous pouvez utiliser is_list
et is_binary
. Celles-ci fonctionnent également dans les clauses de garde.
iex> is_list('abcd')
true
iex> is_binary('abcd')
false
iex> is_list("abcd")
false
iex> is_binary("abcd")
true
Par exemple, pour rendre la version à double guillemet compatible avec des chaînes à guillemets simples:
def match(str) when is_list(str), do: match(to_string(str))
def match("a" <> rest), do: 1
def match(_), do: 0
Si vous souhaitez appliquer une correspondance de modèle en tête d'une liste de caractères, vous devez faire une petite différence dans votre deuxième extrait de code.
'a'
est en fait une charlist avec un élément, donc comparer avec la tête d'une charlist sera toujours faux. Une charlist est vraiment une liste de valeurs entières:
iex> 'abcd' == [97, 98, 99, 100]
true
Le caractère a
équivaut à un entier 97
. Vous pouvez obtenir le code entier d'un caractère dans Elixir en le faisant précéder d'un ?
, ainsi:
iex> ?a == 97
true
iex> ?a == hd('a')
true
Donc, dans votre clause de garde, vous voudrez faire correspondre head == ?a
, ou plus simplement:
defmodule MatchStick do
def doMatch([?a | _tail]), do: 1
def doMatch(_), do: 0
end