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.