Skip to content

Latest commit

 

History

History
271 lines (159 loc) · 5.05 KB

PITCHME.md

File metadata and controls

271 lines (159 loc) · 5.05 KB

---?color=#ffffff

---?color=#3DED20

---?color=#F62020

---?color=#ffffff


Типови спецификации и поведения

(Typespecs and Behaviours)


Image-Absolute


Съдържание

  1. Типова спецификация(type specification)
  • Видове
  • Синтаксис
  • Дефиниране на собствени
  1. Поведения(Behaviours)
  • dynamic dispatch

Но първо!


Замисляли ли сте се?

---?image=assets/thinking.png&size=auto 90%


Хората в Хасково ...

---?image=assets/thinking.png&size=auto 90%


...пишат ли на Хаскел?

---?image=assets/troll.jpg&size=auto 90%


единствения отговор, който получих:

---?image=assets/answer.png&size=auto 50%


Типови спецификации


Type specification


Typespecs


Типспец?


"Звучи доста спечено"

---?image=assets/troll.jpg&size=auto 90%


съжалявам, че ще ви разочаровам...


... не ни правят кода по-бърз

Elixir идва с нотация за типове.


Изглеждат така:

@type age :: pos_integer()
@type sex :: :female | :male
@type location :: String.t()
@type asl :: {age(), sex()}

Функциите са така:

defmodule Foo do
  @spec is_even(integer) :: true | false
  def is_even(x), do: # ... не знам как
end

Използват се главно за:

  • да допринасят за документация(инструменти като ExDoc ги ползват)
  • от инструменти като Dialyzer за анализ на кода за грешки
  • когато пишем библиотеки за други хора
  • текстовите редактори

Типове и техния синтаксис


Като цяло са същите като в Erlang с още малко отгоре!

PS1: Гледаме документацията тук


Използване

PS1: Live coding starts here
PS2: Time for behaviours

---?image=assets/dialyzer.png&size=auto 70%


Поведения(behaviours)

---?image=assets/behaviour.jpg&size=auto 90%


Начин да разделим абстракцията от имплементацията.

---?image=assets/what.gif&size=auto 70%



Поведенията ни дават начин да правим две неща:

  • даден модул имплементира разни функции
  • осигурява, че са имплементирани

Ако се налага - мислите за тях като интерфейсите в !нормалните езици.


ok, нави ме, как го правим?


Да кажем, че бихме искали да напишем поведение за парсване на JSON/MsgPack(случайност).


Как би изглеждало това?


defmodule Parser do
  @callback encode(term) :: {:ok, String.t} | {:error, String.t}
  @callback decode(String.t) :: {:ok, term} | {:error, String.t}
end

И след това го вмъкваме в нашите имплементации по този начин:

defmodule JSON do
  @behaviour Parser

  def encode(term), do: # ... encode
  def decode(str), do: # ... decode
end

defmodule MsgPack do
  @behaviour Parser

  def encode(term), do: # ... encode
  def decode(str), do: # ... decode
end

Dynamic dispatch


Можем динамично да решаваме кога да извикаме даден модул.


Нищо не ни пречи да направим следното:


defmodule Parser do
  # ... rest of code ...

  def encode!(implementation, term) do
    implementation.encode(term)
  end
end

Parser.encode!(JSON, term)
#              ^ - динамично

Вече можем runtime да избираме какъв формат ни трябва!


... чакай малко ...


Behaviours vs Protocols

---?image=assets/fight.jpg&size=auto 90%


Двете не правят ли близки неща?


Разликите:

  • протоколите ни дават полиморфизъм над типове/дата
  • поведенията ни дават динамично да се включваме където ни трябва

Един вид - протоколите са поведения + логика за dynamic dispatch


Въпроси и обратна връзка: [email protected]


---?image=assets/beers.jpg&size=auto 90%