Die Magie von Custom Sigils in Elixir

Illustration eines Zauberrituals

Elixir Sigils sind universelle kleine Tools zur Handhabung gängiger Datentypen. Beispiele für built-in Sigils umfassen Strings (~s), reguläre Ausdrücke (~r), Datumsangaben (~D) und Wortlisten (~w). Aber, wie du vielleicht vermutet hast, endet die Flexibilität von Elixir hier nicht — Elixir erlaubt es uns, unsere eigenen Sigils für unsere spezifischen Bedürfnisse zu bauen. Los geht’s!

Lust auf Kreativität? Wie ihr eure eigenen Sigils bauen könnt

Konzeptuell sind Sigils Funktionen, die Parameter empfangen, wie es auch andere Funktionen tun. Die Funktionsnamen der Sigils folgen dabei einer speziellen Syntax, die du unten sehen kannst (vgl. Schritt 1). Anders als bei regulären Funktionen sind wir dabei jedoch nicht auf die üblichen Separatoren um die Funktionsparameter `()` beschränkt, sondern es stehen uns gleich acht verschiedene dieser Separatoren zur Verfügung (vgl. Schritt 2). Die Parameter eines Sigils bestehen aus einem String als Input und einer Liste an Modifikatoren (vgl. Schritt 3).

Schritt für Schritt zum eigenen Sigil

  1. Definiere eine Funktion mit dem Namen sigil_x, wobei du ‚x‘ ändern kannst — es kann entweder ein einzelner Kleinbuchstabe oder eine Sequenz von Großbuchstaben sein.

  2. Such Dir aus den acht Typen einen Separator aus, der Dir gefällt: ~r(hello) ~r/hello/ ~r|hello| ~r"hello" ~r'hello' ~r[hello] ~r{hello} ~r<hello>.
    Persönliche Empfehlung: Obwohl ~s/https:\/\// und ~s(https://) dasselbe Ergebnis liefern, finde ich den zweiten Ausdruck (bei Weitem) lesbarer.

				
					# Different syntax, same result:

iex(14)> ~s/https:\/\//    
"https://"

iex(15)> ~s(https://)
"https://"
				
			
  1. Ein Sigil nimmt zwei Parameter: einen String und eine Liste an Modifikatoren. Die Modifikatoren sind optional. Damit bekommen wir die folgende Signatur: sigil_x(string, Modifikatoren \\ []).

  2. Und so sieht das dann eingebaut im Template aus: `<%= ~x(string) %>` bzw. mit Modifikatoren `<%= ~x(string)m %>`.

Beispiele von Custom Sigils OHNE Modifikator

Ohne einen Modifikator wird unser Sigil einfach den modifizierten Eingabestring zurückgeben. So sieht das Ganze in der Praxis aus:

Beispiel 1 ohne Modifikator

				
					defmodule YourProject.SigilSorcery do
  def sigil_UPREV(string, _modifier) do
    String.upcase(string)
    |> String.reverse()
  end
end
				
			

Taadaa, wir haben unser erstes Custom Sigil!

Was hier passiert: Das Sigil nimmt einen String, wandelt ihn in Großbuchstaben um und reversed ihn auch gleich.

				
					import YourProject.SigilSorcery

iex(92)> ~UPREV(hello)
"OLLEH"
				
			

Beispiel 2 ohne Modifikator

				
					defmodule YourProject.EmojiSigil do
  @emoji_map %{
    "star" => "⭐",
    "sun" => "🌞",
    "moon" => "🌙",
    "planet" => "🪐",
    "rocket" => "🚀",
  }

  def sigil_EMO(string, _modifiers) do
    String.split(string)
    |> Enum.map(&replace_with_emoji/1)
    |> Enum.join(" ")
  end

  defp replace_with_emoji(word) do
    Map.get(@emoji_map, word, word)
  end
end
				
			

Was hier passiert: Das Sigil nimmt einen String, splittet ihn an den Leerzeichen und ersetzt jedes einzelne Wort, für das es eine Emoji-Entsprechung findet, durch das passende Emoji. Falls das Wort keine Entsprechung hat, geben wir es zurück, ohne es durch ein Emoji zu ersetzen. Schlussendlich joinen wir die Liste wieder zu einem String.

				
					import YourProject.EmojiSigil

iex(92)> ~EMO{star sun moon planet rocket}
"⭐ ☀️ 🌙 🪐 🚀"
iex(93)> ~EMO{hello star hello sun and moon}
"hello ⭐ hi ☀️ and see you 🌙"
				
			

Beispiele von Custom Sigils MIT Modifikator

Modifikatoren sind optional. Wenn wir sie verwenden möchten, müssen wir sie in der Funktionssignatur definieren. Modifikatoren werden als eine Liste von Strings übergeben. Wie oben schon kurz erwähnt, rufst du das Sigil folgendermaßen auf `~x(string)m`. So sieht das Ganze in der Praxis aus:

Beispiel 1 mit Modifikator

				
					defmodule YourProject.SigilCase do
  def sigil_STR(string, 'u'), do: String.upcase(string)
  def sigil_STR(string, 'l'), do: String.downcase(string)
  def sigil_STR(string, 'r'), do: String.reverse(string)
end
				
			

Was hier passiert: Wir definieren drei clauses einer Funktion, von denen jede einen String und einen Modifikator nimmt. Der Modifikator ‚u‘ wandelt den String in Großbuchstaben um, ‚l‘ in Kleinbuchstaben und der Modifikator ‚r‘ reversed den String.

				
					import YourProject.SigilCase

iex(92)> ~STR(hello)u
"HELLO"

iex(93)> ~STR(HellO)l
"hello"

iex(94)> ~STR(hello)r
"olleh"
				
			

Beispiel 2 mit Modifikator

				
					defmodule YourProject.ZooSigil do
  def sigil_ZOO(string, modifiers) do

    repeat_count = String.to_integer(List.to_string(modifiers))


    String.split(string)
    |> Enum.map(&replace_with_animal(&1, repeat_count))
    |> Enum.join(" ")
  end

  defp replace_with_animal(word, repeat_count) do
  emoji=
    case word do
      "cat" -> "🐱"
      "dog" -> "🐶"
      "bird" -> "🐦"
      _ -> word
    end

    String.duplicate(emoji, repeat_count)
  end
end
				
			

Was hier passiert: Das Sigil nimmt einen String, splittet ihn an den Leerzeichen und ersetzt jedes einzelne Wort, für das es eine Emoji-Entsprechung findet, durch das passende Emoji. Dann geben wir das Emoji jeweils n-mal zurück, wobei n der Sigilmodifikator ist. Letztlich joinen wir die Liste wieder zu einem String.

				
					import YourProject.ZooSigil

iex(92)> ~ZOO(cat dog bird)3
"🐱🐱🐱 🐶🐶🐶 🐦🐦🐦"
				
			

Wage es, dich der Sigilmagie zu bedienen

Sigils sind praktische kleine Werkzeuge, sie sind eine Mischung aus Effizienzoptimierung und einem Spielplatz für Deine Kreativität. Egal, ob du dich an regulären Ausdrücken austobst, mit Listen hantierst oder generell einfach nur Spaß daran hast, deine eigenen Sigils zu bauen … Sigils sind eine wertvolle Ergänzung deiner Coding Journey. Also los, setze diese Magie mit einem Lächeln ein und erlebe, wie dein Elixir-Code das Gewöhnliche hinter sich lässt und … zauberhaft wird 🧙🏼☺️.

Related stories:

Picture of Ariadne Engelbrecht

Ariadne Engelbrecht

Ari stieß 2022 zu uns und arbeitet seitdem als Software Engineer bei Inspired. Egal ob Theorie oder aktives Programmieren, sie verbringt ihre Zeit am Liebsten in der IT-Welt – z.B. (als Volunteer) auf Kongressen.

Bisherige Posts