Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[my] Completed basics lessons and 2 advanced lessons #293

Merged
merged 24 commits into from
Apr 21, 2016
Merged
Show file tree
Hide file tree
Changes from 23 commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion _config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,8 @@ description:
fr: Leçons sur le langage de programmation Elixir
gr: Μαθήματα προγραμματισμού της γλώσσας Elixir
it: Lezioni sul linguaggio di programmazione Elixir
pl: Lekcje programowania w języku Elixir
my: Pelajaran mengenai bahasa aturcara Elixir
pl: Lekcje programowania w języku Elixir
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think we need this change, can you remove this file?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it was edited due to merge error. how do I remove this file from this commit?

baseurl: /
url: https://elixirschool.com
og_image: https://elixirschool.com/assets/fb_share.jpg
Expand Down
3 changes: 1 addition & 2 deletions my/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,7 @@ _Maklumbalas dan penyertaan anda amat dialu-alukan!_

"Elixir ialah satu bahasa aturcara kefungsian(functional language) yang dinamik direka untuk membina aplikasi yang mudah untuk dinaiktaraf(scalable) dan mudah untuk diselenggara." - [elixir-lang.org](http:https://elixir-lang.org/)

Elixir leverages the battle tested ErlangVM to build distributed and fault-tolerant systems with low-latency out of the box.
Elixir meng-leverage ErlangVM untuk membina sistem yang bersifat mudah-agih(distributed) dan berdayatahan(fault-tolerant) serta mempunyai redah-kependaman(low-latency) yang disiap-pasang.
Elixir menuilkan kelebihan ErlangVM untuk membina sistem yang bersifat mudah-agih(distributed) dan berdayatahan(fault-tolerant) serta mempunyai redah-kependaman(low-latency) yang disiap-pasang.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Some of the other translators have started working on a Glossary for terms like these, if you want to check it out: https://github.com/doomspork/elixir-school/blob/master/GLOSSARY.md

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

agreed. moving them into glossary is a good idea. I'll work on that next.


__Ciri-ciri__:

Expand Down
175 changes: 175 additions & 0 deletions my/lessons/advanced/concurrency.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,175 @@
---
layout: page
title: Keserempakan(Concurrency)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm concerned these (...) sections in the titles will cause issues with the UI and CSS. Can we remove them @alkaha?

Perhaps we should move all instances of something (english) to the Glossary. Thought?

category: advanced
order: 4
lang: my
---

Salah satu faktor pelaris Elixir ialah sokongan kepada keserempakan(concurrency). Terima kasih kepada ErlangVM, keserempakan di dalam Elixir adalah lebih mudah dari yang dijangkakan. Model keserempakan bergantung kepada Actor, satu proses yang berkomunikasi dengan proses-proses lain melalui pengagihan mesej.

Di dalam pelajaran ini kita akan lihat modul-modul keserempakan yang didatangkan dengan Elixir. Di dalam bab seterusnya kita lihat kelakuan OTP yang melaksanakan mereka.

## Isi Kandungan

- [Proses](#proses)
- [Pengagihan Mesej](#pengagihan-mesej)
- [Perangkaian Proses](#perangkaian-proses)
- [Pengawasan Proses](#pengawasan-proses)
- [Agents](#agents)
- [Tasks](#tasks)

## Proses

Proses-proses di dalam ErlangVM adalah ringan dan memanafaatkan kesemua CPU apabila dijalankan. Walaupun mereka nampak seperti 'native thread', mereka sebenarnya adalah lebih ringkas dan ianya tidak janggal jika terdapat ribuan proses yang berjalan secara keserempakan di dalam aplikasi Elixir.

Cara paling mudah untuk membuat satu proses baru ialah menggunakan `spawn`, yang mengambil satu fungsi tanpa nama atau fungsi bernama. Apabila kita membuat satu proses baru ia akan memulangkan satu _Process Identifier_, atau PID, sebagai pengenalan unik untuk proses itu di dalam aplikasi kita.

Untuk bermula kita akan membuat satu modul dan takrifkan satu fungsi yang kita mahu jalankan:

```elixir
defmodule Example do
def add(a, b) do
IO.puts(a + b)
end
end

iex> Example.add(2, 3)
5
:ok
```

Untuk menjalankan fungsi tersebut secara tak segerak(asynchronous) kita gunakan `spawn/3`:

```elixir
iex> spawn(Example, :add, [2, 3])
5
#PID<0.80.0>
```

### Pengagihan Mesej

Untuk berkomunikasi, proses-proses bergantung kepada pengagihan mesej. Terdapat dua komponen penting di dalam pengagihan mesej, `send/2` dan `receive/2`. Fungsi `send/2` mengupayakan kita untuk menghantar mesej kepada PID. Untuk mengawasi penerimaan mesej, kita gunakan `receive`.

```elixir
defmodule Example do
def listen do
receive do
{:ok, "hello"} -> IO.puts "World"
end
end
end

iex> pid = spawn(Example, :listen, [])
#PID<0.108.0>

iex> send pid, {:ok, "hello"}
World
{:ok, "hello"}

iex> send pid, :ok
:ok
```

### Perangkaian Proses

Fungsi `spawn` mempunyai satu masalah iaitu untuk mengetahui apabila sesatu proses itu runtuh(crash). Untuk itu kita perlu untuk merangkaikan proses-proses kita dengan menggunakan `spawn_link`. Dua proses yang dirangkaikan akan menerima 'exit notification' dari satu sama lain:

```elixir
defmodule Example do
def explode, do: exit(:kaboom)
end

iex> spawn(Example, :explode, [])
#PID<0.66.0>

iex> spawn_link(Example, :explode, [])
** (EXIT from #PID<0.57.0>) :kaboom
```

Kadang-kadang kita tidak mahu proses yang dirangkaikan meruntuhkan proses sedia ada. Untuk itu kita perlu untk memerangkap 'exit' tersebut. 'Exit' yang diperangkap akan diterima sebagai satu mesej dalam bentuk tuple: `{:Exit, from_pid, reason}`.

```elixir
defmodule Example do
def explode, do: exit(:kaboom)
def run do
Process.flag(:trap_exit, true)
spawn_link(Example, :explode, [])

receive do
{:EXIT, from_pid, reason} -> IO.puts "Exit reason: #{reason}"
end
end
end

iex> Example.run
Exit reason: kaboom
:ok
```

### Pengawasan Proses

Bagaiana pula jika kita tidak mahu merangkaikan dua proses tetapi masih diberitahu mengenai keadaan semasa proses-proses tersebut? Untuk itu kita boleh membuat pengawasan proses dengan menggunakan `spawn_monitor`. Apabila mengawasi satu proses, kita akan mendapat satu mesej jika proses tersebut runtuh tanpa meruntuhkan sama proses semasa kita atau tanpa memerlukan 'exit' itu diperangkap.

```elixir
defmodule Example do
def explode, do: exit(:kaboom)
def run do
{pid, ref} = spawn_monitor(Example, :explode, [])

receive do
{:DOWN, ref, :process, from_pid, reason} -> IO.puts "Exit reason: #{reason}"
end
end
end

iex> Example.run
Exit reason: kaboom
:ok
```

## Agent

Agent adalah sejenis peniskalaan(abstraction) proses-proses 'background' yang menyelenggara keadaan semasa(state). Mereka boleh dicapai daripada proses-proses lain dari dalam aplikasi dan nod kita. Keadaan semasa(state) Agent kita ditetapkan kepada nilai yang dipulangkan oleh fungsi-fungsi kita:

```elixir
iex> {:ok, agent} = Agent.start_link(fn -> [1, 2, 3] end)
{:ok, #PID<0.65.0>}

iex> Agent.update(agent, fn (state) -> state ++ [4, 5] end)
:ok

iex> Agent.get(agent, &(&1))
[1, 2, 3, 4, 5]
```

Apabila kita menamakan satu Agent, ia boleh dirujuk sebagai Agent dan tidak melalui PID-nya.

```elixir
iex> Agent.start_link(fn -> [1, 2, 3] end, name: Numbers)
{:ok, #PID<0.74.0>}

iex> Agent.get(Numbers, &(&1))
[1, 2, 3]
```

## Task

'Task' menyediakan satu cara untk menjalankan satu fungsi di 'background' dan menerima nilai yang dipulangkan kemudian. Ianya amat berguna apabila menguruskan operasi-operasi yang berat tanpa merencatkan perjalanan aplikasi.

```elixir
defmodule Example do
def double(x) do
:timer.sleep(2000)
x * 2
end
end

iex> task = Task.async(Example, :double, [2000])
%Task{pid: #PID<0.111.0>, ref: #Reference<0.0.8.200>}

# Do some work

iex> Task.await(task)
4000
```
147 changes: 147 additions & 0 deletions my/lessons/advanced/erlang.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,147 @@
---
layout: page
title: Kesalingbolehgunaan(Interoperability) Dengan Erlang
category: advanced
order: 1
lang: my
---

Salah satu faedah tambahan daripada membina di atas ErlangVM ialah lambakan pustaka sedia ada yang tersedia untuk kita. Kesalingbolehgunaan(Interoperability) mengupayakan kita untuk menuilkan(leverage) pustaka-pustaka tersebut dan pustaka rasmi Erlang daripada kod Elixir kita. Di dalam pelajaran ini kita akan melihat bagaimana untuk mencapai kefungsian di dalam pustaka rasmi dan juga pustaka-pustaka pihak ketiga Erlang.

## Isi Kandungan

- [Pustaka Rasmi](#pustaka-rasmi)
- [Pakej Erlang](#pakej-erlang)
- [Perbezaan Nyata](#perbezaan-nyata)
- [Atom](#atom)
- [String](#string)
- [Pembolehubah](#pembolehubah)


## Pustaka Rasmi

Pustaka rasmi Erlang yang besar boleh dicapai dari mana-mana kod Elixir di dalam aplikasi kita. Modul-modul Erlang diwakilkan oleh atom-atom berhuruf kecil seperti `:os` dan `:timer`.

Mari kita gunakan `:timer.tc` untuk mengukur masa yang digunakan untuk menjalankan satu fungsi:

```elixir
defmodule Example do
def timed(fun, args) do
{time, result} = :timer.tc(fun, args)
IO.puts "Time: #{time}ms"
IO.puts "Result: #{result}"
end
end

iex> Example.timed(fn (n) -> (n * n) * n end, [100])
Time: 8ms
Result: 1000000
```

Sila lihat [Erlang Reference Manual](http:https://erlang.org/doc/apps/stdlib/) untuk mendapatkan senarai lengkap modul-modul yang disediakan.

## Pakej Erlang

Di dalam pelajaran lepas kita telah melihat Mix dan cara-cara menguruskan komponen-komponen sokongan(dependencies). Pustaka Erlang juga boleh diuruskan dengan cara yang sama. Jika pustaka Erlang yang diperlukan itu masih belum dimasukkan ke dalam [Hex](https://hex.pm), anda boleh membuat rujukan terus ke repositori git:

```elixir
def deps do
[{:png, github: "yuce/png"}]
end
```

Sekarang kita boleh mencapai pustaka Erlang tersebut:

```elixir
png = :png.create(#{:size => {30, 30},
:mode => {:indexed, 8},
:file => file,
:palette => palette}),
```

## Perbezaan Nyata

Oleh kerana sekarang kita telah tahu bagaimana untuk menggunakan pustaka Elixir kita patut melihat beberapa isu yang didatangkan oleh kesalingbolehgunaan dengan Erlang.

### Atom

Atom-atom Erlang nampak lebih kurang sama dengan atom Elixir, cuma tanpa tanda titik bertindih (`:`). Mereka diwakili oleh string huruf kecil dan garis bawah.

Elixir:

```elixir
:example
```

Erlang:

```erlang
example.
```

### String

Apabila kita bercakap mengenai string di dalam Elixir, kita merujuk kepada 'UTF-8 encoded binaries'. Di dalam Erlang, string masih ditandakan menggunakan tanda ungkapan berganda ("") tetapi merujuk kepada list aksara.

Elixir:

```elixir
iex> is_list('Example')
true
iex> is_list("Example")
false
iex> is_binary("Example")
true
iex> <<"Example">> === "Example"
true
```

Erlang:

```erlang
1> is_list('Example').
false
2> is_list("Example").
true
3> is_binary("Example").
false
4> is_binary(<<"Example">>).
true
```

Penting untuk diperhatikan bahawa banyak pustaka Erlang yang lama mungkin tidak menyokong 'binary' jadi kita perlu menukarkan string Elixir kepada list aksara. Nasib baik ianya mudah untuk dilakukan dengan menggunakan fungsi `to_char_list/1`:

```elixir
iex> :string.words("Hello World")
** (FunctionClauseError) no function clause matching in :string.strip_left/2
(stdlib) string.erl:380: :string.strip_left("Hello World", 32)
(stdlib) string.erl:378: :string.strip/3
(stdlib) string.erl:316: :string.words/2

iex> "Hello World" |> to_char_list |> :string.words
2
```

### Pembolehubah

Elixir:

```elixir
iex> x = 10
10

iex> x1 = x + 10
20
```

Erlang:

```erlang
1> X = 10.
10

2> X1 = X + 1.
11
```

Itu sahaja! Menuilkan kelebihan Erlang dari dalam aplikasi Elixir adalah cukup mudah dan secara tidak lansung menggandakan jumlah pustaka yang tersedia untuk kita.
11 changes: 5 additions & 6 deletions my/lessons/basics/composition.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ order: 8
lang: my
---

Kita tahu dari pengalaman bahawa menyimpan semua fungsi di dalam satu fail dan skop adalah amat berkecamuk. Di dalam pelajaran ini kita akan melihat bagaimana untuk meletakkan beberapa fungsi ke dalam satu kumpulan dan menetapkan sejenis map khas yang dikenali sebagai struct dalam usaha untuk menguruskan kod kita dengan lebih efisien.
Kita tahu dari pengalaman bahawa menyimpan semua fungsi di dalam satu fail dan skop membawa kepada keadaan kelam-kabut. Di dalam pelajaran ini kita akan melihat bagaimana untuk meletakkan beberapa fungsi ke dalam satu kumpulan dan menetapkan sejenis map khas yang dikenali sebagai struct dalam usaha untuk menguruskan kod kita dengan lebih efisien.

## Kandungan

Expand All @@ -21,7 +21,7 @@ Kita tahu dari pengalaman bahawa menyimpan semua fungsi di dalam satu fail dan s

## Modul

Penggunaan modul-modul adalah cara yang terbaik untuk menguruskan fungsi-fungsi ke dalam satu namespace. Tambahan kepada pengumpulan fungsi-fungsi, mereka juga membenarkan kita menetapkan fungsi-fungsi named dan private yang telah kita cover dalam pelajaran lepas.
Penggunaan modul-modul adalah cara yang terbaik untuk menguruskan fungsi-fungsi di dalam satu namespace. Tambahan kepada pengumpulan fungsi-fungsi, mereka juga membenarkan kita menetapkan fungsi bernama dan fungsi terlindung yang telah kita lihat dalam pelajaran lepas.

Mari kita lihat satu contoh asas:

Expand All @@ -36,7 +36,6 @@ iex> Example.greeting "Sean"
"Hello Sean."
```

It is possible to nest modules in Elixir, allowing you to further namespace your functionality:
Elixir membolehkan untuk membina modul dalam bentuk bersarang, membenarkan anda untuk mengembangkan penggunaan 'namespace' kefungsian anda:

```elixir
Expand Down Expand Up @@ -68,7 +67,7 @@ defmodule Example do
end
```

Adalah penting untuk dijelaska bahawa terdapat beberapa ciri-ciri simpanan dalam Elixir. Tiga yang paling biasa adalah:
Adalah penting untuk dijelaskan bahawa terdapat beberapa ciri-ciri simpanan dalam Elixir. Tiga yang paling biasa adalah:

+ `moduledoc` — menjana dokumentasi modul semasa.
+ `doc` — menjana dokumentasi untuk fungsi dan makro.
Expand All @@ -78,7 +77,7 @@ Adalah penting untuk dijelaska bahawa terdapat beberapa ciri-ciri simpanan dalam

Struct adalah sejenis map khas yang mengandungi satu set key dan value. Ia mesti ditetapkan di dalam satu modul, yang mana ia mendapat namanya(nama struct adalah nama modul yang mana ia terkandung). Menjadi kebiasaan apabila satu modul hanya mengandungi struct di dalamnya.

Gunakan `defstruct` untuk menetapkan satu struct, di samping satu keyword list yang mengandungi key dan nilai lalai:
Gunakan `defstruct` untuk menetapkan satu struct, di samping satu list katakunci yang mengandungi katakunci dan nilai lalai:

```elixir
defmodule Example.User do
Expand Down Expand Up @@ -217,7 +216,7 @@ defmodule Example do
end
```

Jika kita cuba memanggil satu makro yang masih belum dipasang Elixir akan menerbitkan ralat.
Jika kita cuba memanggil satu makro yang masih belum dipasang Elixir akan menimbulkan ralat.

### `use`

Expand Down
Loading