Kontrol Yapilari
Burada Elixir’in bize sundugu kontrol yapilarini inceleyecegiz.
if and unless
Muhtemelen if/2
daha once kullandiniz ve eger daha once Ruby de kullandiysaniz muhtemelen unless/2
ile de tanistiniz. Elixir’de bunlar asagi yukari ayni sekilde calismaktadir fakat bunlar makro olarak tanimlanmistir, dilin bir bileseni olarak degil. Dil icerisince nasil uygulandiklarini Cekirdek Modul icerisinde inceleyebilirsiniz.
Elixir’de, false
ve nil
dışında herşey true olarak kabul edilir:
iex> if String.valid?("Merhaba") do
...> "Evet bu bir string"
...> else
...> "Hayir bu bir string degil"
...> end
"Evet bu bir string"
iex> if "bu bir string midir" do
...> "evet tabii ki"
...> end
"evet tabii ki"
unless/2
kullanmak ise if/2
gibidir fakat olumsuz/ters mantikla calisir:
iex> unless is_integer("merhaba") do
...> "Integer degil"
...> end
"Integer degil"
case
Eger birden fazla karsilastirma yapmak gerekirse case/2
kullanilabilir:
iex> case {:ok, "Merhaba Dunya"} do
...> {:ok, result} -> result
...> {:error} -> "Hata!"
...> _ -> "Varsayilan diger tum karsilastirma sonuclari"
...> end
"Merhaba Dunya"
_
degiskeni case/2
karsilastirmalarinda onemlidir. Kullanilmazsa ve aranilan deger eslesmezse
hata verecektir. Yani aslinda varsayilan deger yok sayilmistir.
iex> case :pire do
...> :deve -> "Deve"
...> end
** (CaseClauseError) no case clause matching: :pire
iex> case :pire do
...> :deve -> "Deve"
...> _ -> "Pire"
...> end
"Pire"
_
degiskeni else
gibi dusunulebilir. Hicbir deger tutmazsa bunu kullan gibi.
case/2
ornegini bulmaya (pattern-matching) dayandigi icin, onun kurallari gecerlidir. Eger varolan bir deger ile karsilastirma yapacaksiniz, daha once de degindigimiz gibi sapka operatorunu (pin operator) kullanabilirsiniz ^/1
:
iex> kek = 3.14
3.14
iex> case "kirazli kek" do
...> ^kek -> "Hic lezzetli degil"
...> kek -> "Iddiaya varim ki #{kek} cok tatlidir"
...> end
"Iddiaya varim ki kirazli kek cok tatlidir"
case/2
nin diger guzel ozelligi de kosullu karsilastirmalari (guard clauses)
desteklemesidir:
Asagidaki ornek direkt olarak resmi Elixir Baslarken sayfasindan alinmistir.
iex> case {1, 2, 3} do
...> {1, x, 3} when x > 0 ->
...> "x sifirdan buyuk"
...> _ ->
...> "x sifirdan buyuk degil"
...> end
"x sifirdan buyuk"
Elixir resmi dokumanlarindan devamini inceleyebilirsiniz. Kosullu karsilastimalar (guard clauses) hakkinda daha fazla.
cond
Degerleri karsilastirmak yerine durumlari karsilastirmak istersek cond/1
kullanmamiz gerekir; bu diger dillerdeki else if
veya elsif
e benzemektedir:
Asagidaki ornek direkt olarak resmi Elixir Baslarken sayfasindan alinmistir.
iex> cond do
...> 2 + 2 == 5 ->
...> "Bu dogru degildir"
...> 2 * 2 == 3 ->
...> "Bu da degil"
...> 1 + 1 == 2 ->
...> "Ama bu dogrudur"
...> end
"Ama bu dogrudur"
case/2
ve cond/1
will raise an error if there is no match. To handle this, we can define a condition set to true
:
iex> cond do
...> 7 + 1 == 0 -> "Yanlis"
...> true -> "Varsayilan durum"
...> end
"Varsayilan durum"
with
with/1
pipe |
operatorunun kullanilamadigi bazi durumlarda kullanisli olabilir.
with/1
ifadesi anahtar kelimeler (keywords), uretecler (generators) ve son olarak ifadelerden olusur.
Uretecleri (generators) liste kapsamlari konusunda inceleyecegiz, fakat simdilik
bilmemiz gereken <-
ifadesinin sag ve sol taraflarinin karsilastirmasinin ornegini bulma (pattern matching) ile yapildigidir.
Basit bir with/1
ornegiyle basliyoruz:
iex> user = %{isim: "Mete", soyisim: "Unal"}
%{isim: "Mete", soyisim: "Unal"}
iex> with {:ok, first} <- Map.fetch(user, :isim),
...> {:ok, last} <- Map.fetch(user, :soyisim),
...> do: last <> ", " <> first
"Unal, Mete"
Bu ifadenin karsiliginin olmadigi durumda, eslesmeyen deger geri donecektir:
iex> user = %{isim: "Mete"}
%{isim: "Mete"}
iex> with {:ok, first} <- Map.fetch(user, :isim),
...> {:ok, last} <- Map.fetch(user, :soyisim),
...> do: last <> ", " <> first
:error
Simdi de with/1
olmayan daha buyuk bir kod ornegini inceleyip, nasil daha iyi yazilabilir onu inceleyelim:
case Repo.insert(changeset) do
{:ok, user} ->
case Guardian.encode_and_sign(user, :token, claims) do
{:ok, token, full_claims} ->
important_stuff(token, full_claims)
error ->
error
end
error ->
error
end
Yukaridaki kodu with/1
ile yazdigimizda daha kisa, basit ve kolay anlasilir bir kod obegi elde edecegiz.
with {:ok, user} <- Repo.insert(changeset),
{:ok, token, full_claims} <- Guardian.encode_and_sign(user, :token, claims) do
important_stuff(token, full_claims)
end
Elixir 1.3 ile birlikte with/1
ile birlikte else
desteklenmeye baslanmistir.
import Integer
m = %{a: 1, c: 3}
a =
with {:ok, number} <- Map.fetch(m, :a),
true <- is_even(number) do
IO.puts("#{number}, 2 ile bolumu : #{div(number, 2)}")
:cift
else
:error ->
IO.puts("Bu deger mapte mevcut degil")
:error
_ ->
IO.puts("tek sayi")
:tek
end
case
teki gibi ornegini bulma (pattern-matching) sayesinde hatalar indirgenmektedir.
Caught a mistake or want to contribute to the lesson? Edit this lesson on GitHub!