Bạn có chắc chắn muốn xóa bài viết này không ?
Bạn có chắc chắn muốn xóa bình luận này không ?
Cuối tuần học elixir và một vài cảm nhận ban đầu
Mình được @kiennt dụ dỗ, nên đã quyết định cuối tuần vừa rồi thử elixir xem mặt mũi nó ra sao mà nhiều bạn quảng cáo thế. Mình tìm hiểu chủ yếu dựa trên trang chủ : http://elixir-lang.org/getting-started chứ chưa đọc thêm gì nhiều. Cảm nhận sau một ngày đọc về spec của elixir thì:
- Elixir là một ngôn ngữ lập trình hàm thuần tuý (pure functional programming). Các qui tắc về immutable khá chặt, về cơ bản thì elixir không cho phép thay đổi một biến nào đó (không như scala mặc dù đã có
val
vẫn cố nới lỏng bằng phép cho dùngvar
). - Elixir có tính balance khá tốt giữa việc cân bằng các thuộc tính:
- Lập trình hàm
- Tính toán song song (dùng otp)
- syntax sugar (dùng
sigils
hoặc làmacro
) - dynamic type nhưng vẫn support "nearly" strong type thông qua type spec
Elixir là gì
Theo định nghĩa trên trang chủ thì
Elixir is a dynamic, functional language designed for building scalable and maintainable applications.
Elixir leverages the Erlang VM, known for running low-latency, distributed and fault-tolerant systems, while also being successfully used in web development and the embedded software domain.
Việc vừa dynamic lại vừa functional programming làm elixir có chút nét tương đồng với clojure. Tuy nhiên tận dụng erlang vm lại là một điểm khác biết rất lớn. Erlang là một ngôn ngữ lập trình chủ yếu cho các chương trình phân tán, và đỏi hỏi tính song song lớn, tuy nhiên lại không được sử dụng rộng rãi bởi sự xấu xí về mặt syntax của nó :v. Elixir đã khắc phục nhược điểm này bằng việc sử dụng lại các khái niệm syntax được yêu thích trên ruby lang như là module, block, hash... khiến cho chúng ta có một ngôn ngữ vừa có hiệu năng tốt, lại vừa có syntax tương đối dễ nhìn.
Elixir được tạo ra bởi José Valim, một người mà cộng đồng ruby không hề lạ lùng gì, là core contributor của rails, creator của devise library cũng như nhiều thư viện ruby nổi tiếng khác. Chình vì thế mà elixir đã đi theo con được của ruby bằng tạo ra một web framework chuẩn mực là phoenix để leverage cho chính ngôn ngữ mà nó được viết bằng.
Một vài khái niệm trên elixir
Khác nhau giữa List và Tuples
Ở elixir thì List sẽ là linked list, còn tuples sẽ là fixed size list (nằm cạnh nhau trên memory). 2 cấu trúc dữ liệu này sẽ có complexity khác nhau với một số phép toán nên cần chú ý
Tham khảo: http://stackoverflow.com/questions/31192923/lists-vs-tuples-what-to-use-and-when
Anym function và capture syntax
anym function tương đối giống lambda function trong python. Function trong elixir là first class citizen, tức là có thể truyền vào như parameter.
fn a, b -> a + b
Để support tạo anym function một cách nhanh hơn elixir support syntax gọi là capture syntaxsyntax
fun = &(&1 + 1)
//tương đương với
fn a -> a + 1
Pattern matching
Bài viết dưới đây của @kiennt đã cover quá đủ :P
https://elixirvn.com/introduction-about-elixir-pattern-matching-1af7d7bdf708#.d2ig3w7hi
Loops in Elixir
Vì elixir không hỗ trợ mutable variable nên để loop trong elixir bạn chỉ có cách dùng recursive function
defmodule Recursion do
def print_multiple_times(msg, n) when n <= 1 do
IO.puts msg
end
def print_multiple_times(msg, n) do
IO.puts msg
print_multiple_times(msg, n - 1)
end
end
Ngoài ra thì elixir còn hỗ trợ comprehension để bạn có thể loop trên những protocol hỗ trợ dạng generator
iex> for n <- [1, 2, 3, 4], do: n * n
[1, 4, 9, 16]
Stream và Pipe operator
Elixir Stream hỗ trợ lazy operations, tức là khi nào cần mới xử lý. Thay vì trả về ngay 1 list mới thì stream sẽ build xử lý trước (computational unit) rồi sau đó apply cái xử lý đó lần lượt vào list.
Để thao tác trên stream dễ dàng, thì chúng ta có pipe operator
, mà cách dùng thì nhìn ví dụ dưới đây chắc cũng hiểu :v :
iex> 1..100_000 |> Stream.map(&(&1 * 3)) |> Stream.filter(odd?) |> Enum.sum
Process và Task
Elixir process tương ứng với process trong erlang VM. Process trong elixir được sử dụng rất rộng rãi, đọc file cũng tạo process mới, lưu state cũng tạo process mới, nên mình thích thì mình tạo process mới thôi. Mỗi process sẽ được identify thông qua PID
iex> spawn fn -> 1 + 2 end
#PID<0.43.0>
Các process sẽ nói chuyện với nhau thông qua send
và receive
message
iex> send self(), {:hello, "world"}
{:hello, "world"}
iex> receive do
...> {:hello, msg} -> msg
...> {:world, msg} -> "won't match"
...> end
"world"
message sẽ được lưu ở mailbox
hay chính là một dạng queue.
Để error từ process con propagate lên process cha thì thay vì spawn chúng ta dùng spawn_link
Ngoài ra để kiểm soát lỗi tốt hơn thì chúng ta dùng Task
thay vì process
iex(1)> Task.start fn -> raise "oops" end
{:ok, #PID<0.55.0>}
Module và protocol/struct
Elixir hỗ trợ polymophism thông qua protocol (giống interface) và struct (giống struct bình thường)
iex> defmodule User do
...> defstruct name: "john", age: 27
...> end
{:module, User,
<<70, 79, 82, ...>>, {:__struct__, 0}}
defimpl Blank, for: User do
def blank?(_), do: false
end
Liên quan về syntax với erlang
Tham khảo http://elixir-lang.org/crash-course.html có nhiều so sánh về syntax giữa 2 ngôn ngữ, khá là dễ hiểu.
Tạm thời tìm hiểu đến đây đã, tuần tiếp sẽ là mix, otp và phoenix nhé :D






