Znaki magiczne w kodzie elixirowym
Mała odskocznia od tematów JVMowych. Dziś przyjrzymy się mechanizmowi sigiliW w elixirze.
Czym jest sigil?
Wikipedia mówi, że jest to symbol utworzony do celów magicznych. I ta definicja całkiem ładnie wpisuje się w to co robią. Swoim zachowaniem przypominają interpolatory ze scali jednak są pomiędzy nimi drobne różnice, które jednak nie będą dla nas istotne (trochę inna składnia i duperele wynikające z różnic w języku). To co odróżnia sigile w elixirze od interpolatorów w scali to sposób w jaki obrabiany jest argument. Na przykładzie:
Listing 1. Interpretacja ciągu znaków
iex(3)> ~S"Napis #{1+1}"
"Napis \#{1+1}"
iex(4)> ~s"Napis #{1+1}"
"Napis 2"
Sigil, zapisany jako ~S lub ~s (ogólna konwencja ~ZNAK), będzie miał przekazany argument w zależności od wielkości znaku. Jeżeli zapiszemy go wielką literą, to string przekazany w argumencie nie będzie interpretowany. Jeżeli zapiszemy małą to sigil otrzyma już „wyliczony” argument.
Własne sigile
Tworzenie własnych sigili jest stosunkowo proste. By zachować porządek w kodzie warto wydzielić je do osobnego modułu:
Listing 2. Moduł z sigilami
defmodule SigilsExample do
@moduledoc false
import DateToString
def sigil_m(string, []), do: Stream.zip(String.split(string, "@"), [:name, :domain]) |> Enum.to_list
def sigil_l(string, []), do: IO.puts(string)
def sigil_l(string, [t]), do: IO.puts( DateToString.date_to_string(:os.timestamp |>:calendar.now_to_datetime) "# " string)
end
zasada jest prosta funkcja, która jest ukryta pod sigilem nazywa się sigil\_ZNAK. Elixir już samodzielnie dokona rozkminy potrzebnej do rozróżniania wielkości liter. Drugim argumentem jest lista dodatkowych parametrów. Pozwala to na sterowanie sposobem działania funkcji. Na powyższym przykładzie sigiel logujący ~l może dodawać aktualny czas gdy dodamy parametr t.
Użycie
To co przypadło mi do gustu w przypadku elixira to poza możliwością tworzenia własnych sigili to duża elastyczność w wykorzystaniu ograniczników dla ciągu znaków. Wszystkie poniższe zapisy są poprawne:
Listing 3. Różne zapisy sigili
defmodule LearnElixir do
import SigilsExample
def main() do
~l"log"t
~l'log't
~l/log/t
~l|log|t
~l<log>t
~l{log}t
~l[log]t
~l(log)t
end
end
Pozwala to na wytworzenie pewnych konwencji tak jak w przypadku zapisu wyrażeń regularnych z użyciem slashy r/WYRAŻENIE/ig.
Elixir generalnie jest całkiem fajnym językiem, który daje dużo możliwości i pozwala „uciec” z JVMki.