1 điểm bởi GN⁺ 3 giờ trước | 1 bình luận | Chia sẻ qua WhatsApp
  • Suy luận kiểu và kiểm tra kiểu dần (gradual) được áp dụng cho mọi chương trình Elixir, giúp tìm ra mã chết và các lỗi đã được xác minh chắc chắn sẽ thất bại khi chạy ngay cả khi không có chú thích kiểu
  • Kiểu dynamic() khác với any() vốn “cho phép mọi thứ”: nó theo dõi phạm vi kiểu có thể có tại runtime và chỉ báo vi phạm khi hoàn toàn không chồng lấp với kiểu được cho phép
  • Giá trị dynamic(integer() or binary()) sẽ không tạo vi phạm với các lời gọi có phần khả năng chồng lấp, như phép toán số hoặc hàm chuỗi, nhưng sẽ tạo vi phạm với các lời gọi chỉ nhận map như Map.fetch!
  • dynamic() được thu hẹp theo cách nó được sử dụng, tinh chỉnh data trong đoạn mã như data.a + data.b thành một map có dạng %{..., a: number(), b: number()}
  • Trong guard, hệ thống suy luận hợp, giao và phủ định để dùng các điều kiện như is_list, is_integer, is_map_key, not is_map_key, tuple_size làm thông tin kiểu
  • case và các câu lệnh điều kiện phản ánh thông tin của nhánh trước vào nhánh sau, thực hiện kiểm tra kiểu theo cách như xử lý nil trước rồi thu hẹp giá trị còn lại thành binary()
  • Kiểu đã được bổ sung cho nhiều hàm liên quan đến tuple và map trong thư viện chuẩn, giúp tìm ra các nhánh trùng lặp và mã chết trong codebase hiện có
  • Trong “If T: Benchmark for Type Narrowing”, Elixir vượt qua 12 trong 13 hạng mục, cho thấy có thể khôi phục thông tin kiểu chính xác trong mã Elixir thông thường
  • v1.20 cũng tiếp tục cải thiện thời gian biên dịch cho ứng dụng trong môi trường đa lõi, và trong benchmark tổng hợp, công cụ build của Elixir cho kết quả nhanh nhất среди các ngôn ngữ BEAM
  • Tùy chọn compiler mới :module_definition cho phép chọn cách thực thi định nghĩa module với giá trị mặc định là :compiled hoặc :interpreted, và có thể bật bằng elixirc_options: [module_definition: :interpreted] trong mix.exs
  • Tùy chọn :module_definition không ảnh hưởng đến file .beam được ghi ra đĩa mà chỉ thay đổi cách thực thi bên trong defmodule, và có thể giúp cải thiện thời gian biên dịch trong các dự án lớn
  • Chữ ký kiểu mới sử dụng kiểu tập hợp sẽ được thảo luận cùng với định nghĩa typed struct sau khi hoàn tất nghiên cứu về hiệu năng hệ thống kiểu của v1.20, kiểu đệ quy, kiểu tham số hóa, và duyệt key-value của map

1 bình luận

 
Ý kiến trên Hacker News
  • Có thể chỉ là trải nghiệm cá nhân, nhưng có cảm giác nếu đó không phải là ngôn ngữ có type ngay từ đầu thì sẽ không hoạt động tốt bằng ngôn ngữ static type thực thụ

    • Đồng ý, nhưng cũng có góc nhìn khác: “Why are gradual static types so great?” https://www.benkuhn.net/gradual/
    • Ngược lại, vì TypeScript phải hỗ trợ đủ mọi kiểu mẫu kỳ lạ mà mọi người đã dùng trong ngôn ngữ không có type, nên nó lại trở thành hệ thống kiểu tôi thích nhất
  • Tôi đã làm lập trình viên Elixir chuyên nghiệp khoảng 10 năm và đã mong chờ type từ lâu. Rất vui khi lần này bước khởi đầu đó đã thực sự xuất hiện
    Tuy vậy, tôi muốn biết trạng thái hiện tại trong v1.20 so với Dialyzer không có đặc tả thì thế nào. Tôi hiểu cách tiếp cận success typing của Dialyzer gần giống kiểu “nếu có ít nhất một tổ hợp đối số chạy được thì không cảnh báo”, chứ không phải “nếu có tổ hợp đối số có thể thất bại thì cảnh báo”, và tôi cứ nghĩ Elixir lần này cũng làm điều gì đó tương tự, còn Dialyzer thì tôi không thấy hữu ích lắm

    • Tôi tò mò không biết nó sẽ phát hiện ra những gì trong codebase Elixir 10 năm tuổi vẫn đang chạy của tôi
  • Tôi đã thấy vài bài trên HN về hệ thống gradual typing của Elixir nhưng chưa theo dõi kỹ. Tôi muốn hỏi có ai biết liệu hệ thống gradual typing này có thể thay đổi độ phức tạp tiệm cận của chương trình so với mã không có type hay không
    Theo tôi biết, phần lớn các hệ thống gradual typing, ví dụ như Racket, có thể làm chương trình chậm hơn về mặt tiệm cận, dù cũng có một số ngoại lệ [1]
    [1] https://doi.org/10.1145/3314221.3314627

    • Hệ thống gradual typing của Elixir không thể thay đổi độ phức tạp tiệm cận của chương trình. Theo thiết kế, nó loại trừ rõ ràng các runtime cast ở ranh giới static/dynamic, vốn là nguyên nhân làm chậm ở các hệ thống gradual typing khác
      Hầu hết các hệ thống gradual typing đều chèn ép buộc khi giá trị đi qua ranh giới giữa mã có type và không có type. Ví dụ như kiểm tra mọi phần tử trong danh sách, hoặc bọc giá trị bằng type proxy. Nhưng nhóm Elixir đã công bố kết quả strong arrows để đạt được tính soundness mà không cần các kiểm tra runtime như vậy, và bytecode mà compiler tạo ra giống hệt mã không có type về mặt ngữ nghĩa
  • Trớ trêu là các nhà phê bình nói rằng type là cần thiết, còn fan Elixir thì nói không cần type và Elixir bằng cách nào đó rất thần kỳ nên không phát sinh lỗi liên quan đến type, giờ thêm type vào thì lại tìm ra bug. Chẳng phải trước đó họ nói không cần để ngăn bug sao? Dù vậy đây vẫn là thay đổi tốt. Trước đây tôi đã dùng Elixir khá nhiều và rất thích, nhưng thật khó để đồng tình với việc thiếu type

    • Đây là ngụy biện Goomba
      https://en.wiktionary.org/wiki/Goomba_fallacy
    • Tôi không theo dõi Elixir quá sâu, nhưng những gì tôi thấy từ phía Erlang thì hơi khác. Vì đằng nào cũng phải xử lý lỗi một cách gọn gàng, nên lỗi type cũng có thể được xử lý bằng chính cơ chế phục hồi khi thất bại mà bạn vốn phải có sẵn
      Tôi không đồng ý với góc nhìn đó, nhưng đó là lập luận dễ bảo vệ hơn nhiều so với kiểu “$LANGUAGE là phép màu”
    • Tôi không dám chắc chưa từng thấy ai nói như vậy, nhưng tôi không nhớ là đã thấy, và dù có thì chắc cũng là thiểu số rất nhỏ. Lập luận phản đối thực tế thường gần với kiểu “type thì tốt, nhưng có chi phí, và chi phí đó không phải lúc nào cũng mang lại lợi ích đủ lớn”
      Trước khi lý thuyết kiểu tập hợp phát triển, có lẽ đó còn là một lập trường đúng
    • Điều tương tự cũng đã xảy ra với JavaScript/TypeScript và Python. Đôi khi chỉ có thể để mọi người tin điều họ muốn tin
    • Đó là vòng đời tự nhiên. Ngôn ngữ dynamic typing thu hút fan, những người khác thì đúng khi nói rằng nó sẽ hữu ích hơn rất nhiều nếu có static typing. Fan lại xem đó là chuyện mang tính cá nhân và nói rằng static typing là không cần thiết. Lý do thì đủ kiểu: “đằng nào cũng không hữu ích”, “trái với tinh thần của ngôn ngữ”, “chỉ là ngôn ngữ script thôi”, “dùng debugger là được”, “static typing làm giảm năng suất”, v.v.
      Rồi cuối cùng họ vẫn thêm static typing. Điều đó đã xảy ra với Python, JavaScript, Ruby, và chắc còn nữa
  • Tôi rất thích việc có thể cập nhật Elixir mà không gặp thay đổi phá vỡ tương thích trong nhiều dự án, và compiler còn tìm bug miễn phí cho mình. Tôi đã quá quen với điều đó rồi

  • Nhìn thấy điều này tôi thực sự rất vui. Giờ nó đang tiến gần hơn tới mức “một ngôn ngữ tuyệt vời”, và với tôi Elixir là ứng viên số một
    Nếu có ngôn ngữ nào khác cũng dễ dùng như vậy mà vẫn tiếp tục bổ sung các tính năng tuyệt vời theo cách ổn định và an toàn, tôi rất muốn được giới thiệu. Tôi đã từng thành thạo Go rồi chuyển sang học C# nâng cao, nhưng tôi có cảm giác Go đã ngừng bổ sung các tính năng hay

  • Trong tháng vừa qua tôi đã thử làm track Elixir trên exercism.io https://exercism.org/tracks/elixir
    Thật sự rất tuyệt

  • À, lại bắt đầu rồi. Có vẻ tôi sẽ lại học Elixir thêm 1 năm nữa
    Tôi thích mọi thứ ở Elixir, nhưng hơn bất kỳ ngôn ngữ nào khác, Elixir luôn khiến tôi tiếp tục nghi ngờ chính mình. Có lẽ não tôi không hợp với kiểu hàm, nhưng thay đổi này khiến tôi muốn thử lại
    Điều đáng tiếc là hệ sinh thái khó mà xem là thân thiện với người mới bắt đầu, và khi trả lời câu hỏi thì người ta thường mặc định là bạn đã biết khá nhiều về ngôn ngữ rồi

    • https://pragprog.com/titles/lhelph/functional-web-developmen...
      Đừng để tiêu đề đánh lừa. Nửa đầu cuốn sách đơn giản chỉ là Elixir
      Trong 8 năm qua, mỗi lần tôi cần làm quen lại với Elixir thì tôi lại dùng cuốn sách này, và lần nào cũng hiệu quả. Tôi chưa từng đọc hết
      Một trong những tiêu chí để đánh giá sách lập trình kiểu dự án hướng dẫn như thế này có tốt hay không là: dù đã bắt đầu nhiều lần mà chưa đi đến cuối, liệu đến khoảng giữa sách bạn đã có đủ công cụ để quay lại làm việc của mình hay chưa
    • Tôi đã trải qua điều này cực kỳ đau đớn khi lần đầu học Haskell trong một môn kiểu như “Tổng quan về các mô hình lập trình” thời đại học. Lúc đó tôi đã lập trình được vài năm rồi, nên thật khó tin khi mình lại bất lực đến thế chỉ để hoàn thành những việc mà từ lâu vốn thấy là cơ bản
      Nhưng tôi nghĩ không phải vì não không hợp, mà là vì sự tương phản giữa mức kinh nghiệm tích lũy trong các ngôn ngữ mệnh lệnh và việc phải bắt đầu lại như người mới trong phong cách thuần hàm
      Rồi sẽ dần khá lên thôi. Bước ngoặt để tôi thấy thoải mái với lập trình hàm là khi nhận ra mình thích việc ghép các đoạn code kiểu Bash “one-liner” được giãn cách thoáng ra đến mức nào. Dữ liệu bắt đầu ở một dạng nào đó, tôi đổ nó ra bằng một lệnh, nghĩ xem bước nào sẽ đưa nó gần hơn tới dạng mình muốn, rồi pipe sang lệnh tiếp theo và xem lại. Cứ thế tiếp tục, đến cuối cùng thường còn lại một chuỗi các phép biến đổi dữ liệu mà không thay đổi dữ liệu tại chỗ
      Một phần lý do cách này thấy dễ chịu trong shell là vì ngày nào bạn cũng đi qua lại trong hệ thống tệp và tích lũy dần vốn từ lệnh. Thư viện “hàm” quen thuộc của tôi trong môi trường kiểu Unix đã lớn lên đáng kể qua nhiều năm. Trong môi trường lập trình thuần hàm, bạn cũng phải làm điều tương tự, chỉ là việc học vốn từ cần thêm chút công sức. Các “lệnh” thường dùng sẽ là những hàm như map, fold, zip thay vì grep, cat, sort
      Nhưng cốt lõi thực sự là như nhau, và sức hấp dẫn của việc tạo pipeline cũng áp dụng giống hệt ở cả hai bên. Bạn có thể xây từng mảnh một, và với mỗi câu đố nhỏ, bạn quên bước trước đi rồi chỉ nghĩ xem dữ liệu trước mắt cần được biến đổi thế nào ở bước tiếp theo. Mức yêu cầu ngữ cảnh thấp này vừa mới mẻ vừa dễ chịu
      Chúc bạn nhất định sẽ thử và thấy thích. Khi bạn học được cách tận hưởng trạng thái mình chưa làm được điều gì đó, đó cũng là lúc cuối cùng bạn sẽ làm tốt nó
    • Không biết bạn có biết chút Rust nào không. Tôi cũng không có nhiều kinh nghiệm với ngôn ngữ hàm, nhưng Gleam lại cho cảm giác quen thuộc nhờ những phần rất giống Rust, nên tôi có thể tập trung vào khái niệm nhiều hơn là cú pháp
      Tất nhiên tôi mới chỉ nghịch vài buổi chiều thôi, nhưng nếu tôi định lại rèn não mình theo hướng ngôn ngữ hàm, thì vì sự quen thuộc tôi có lẽ sẽ chọn Gleam
    • Tôi khuyên bạn nên hỏi trên ElixirForum. Tôi chưa từng thấy phản ứng nào thật sự thù địch
      Đôi khi có những bài mơ hồ nên không thu hút được chú ý, hoặc bị phớt lờ vì có mùi kiểu “làm hộ bài tập cho tôi”
      Nhưng các bài viết thể hiện sự tò mò thật sự thì theo tôi thấy đều nhận được câu trả lời
    • Mấy câu như thế này lúc nào cũng làm tôi bối rối. Với tôi, chương trình hướng đối tượng đầy trạng thái còn khó suy luận hơn nhiều
  • Tuyệt vời. Có vẻ ở 1.20, việc biên dịch ứng dụng umbrella lớn của chúng tôi đã nhanh hơn khá nhiều

  • Tôi tò mò không biết so với Gleam thì thế nào. Hay là giờ tại sao vẫn nên dùng Elixir thay vì Gleam? Có lẽ Phoenix, đặc biệt là LiveView, là sức hút lớn của Elixir

    • Khác biệt nằm ở việc bạn thích Rust hay thích Erlang. Dùng Gleam thì giống cảm giác dùng Rust, còn dùng Elixir thì giống cảm giác dùng Erlang
      Tôi không rõ trạng thái hiện tại của Gleam OTP, nhưng lần cuối tôi xem thì nó chưa ổn lắm
      Nếu cả hai điều đó đều không quan trọng với bạn và thứ duy nhất bạn quan tâm là type, thì cứ dùng Gleam. Nhưng vậy thì chẳng phải dùng Rust luôn sẽ hợp lý hơn sao?
    • Ngay trên website của Gleam đã có tài liệu so sánh
    • Gleam không có macro, trong khi nhiều thư viện Elixir như Phoenix hay Ecto dùng macro rất hiệu quả
      Ví dụ, ở Gleam thì việc decode/encode JSON có thể trở nên dài dòng. Trong Rust bạn chỉ cần derive serde, còn trong Elixir thì chỉ cần một lời gọi hàm
      Elixir có hệ sinh thái trưởng thành hơn. Ví dụ ở Gleam bạn có thể dùng Phoenix hoặc các framework Gleam khác, nhưng trải nghiệm sẽ không giống nhau
      Lý do lớn nhất khiến Gleam hấp dẫn hơn Elixir là type, và giờ Elixir đang thu hẹp khoảng cách đó. Một điểm nữa là có thể compile sang JavaScript, còn bên Elixir thì Hologram đang làm điều gì đó tương tự
      Cá nhân tôi thích hệ thống type của Gleam và cú pháp kiểu Rust hơn, nhưng hiện tại tôi vẫn thấy Elixir là lựa chọn tốt hơn cho mọi dự án phát triển web của mình
    • Về cơ bản là vì Phoenix và Ecto thôi