1 คะแนน โดย GN⁺ 3 시간 전 | 1 ความคิดเห็น | แชร์ทาง WhatsApp
  • การอนุมานชนิดข้อมูลและการตรวจสอบชนิดข้อมูลแบบค่อยเป็นค่อยไป (gradual) ถูกนำมาใช้กับทุกโปรแกรม Elixir ทำให้สามารถค้นหาโค้ดที่ไม่มีวันถูกรันและ บั๊กที่ยืนยันได้ ว่าจะล้มเหลวขณะรันได้แม้ไม่มี type annotation
  • ชนิดข้อมูล dynamic() ต่างจาก any() ที่หมายถึง “อะไรก็ได้” ตรงที่มันติดตามขอบเขตของชนิดข้อมูลที่เป็นไปได้ขณะรัน และจะรายงานการละเมิดเฉพาะเมื่อไม่ทับซ้อนกับชนิดข้อมูลที่อนุญาตเลยเท่านั้น
  • ค่า dynamic(integer() or binary()) จะไม่แจ้งการละเมิดในกรณีเรียกใช้ที่มีความเป็นไปได้บางส่วนทับซ้อนกัน เช่น การคำนวณตัวเลขหรือฟังก์ชันสตริง แต่จะรายงานการละเมิดกับการเรียกที่รับเฉพาะ map อย่าง Map.fetch!
  • dynamic() จะถูกทำให้แคบลงตามวิธีการใช้งาน และในโค้ดอย่าง data.a + data.b จะกลั่น data ให้เป็น map รูปแบบ %{..., a: number(), b: number()}
  • ใน guard มีการอนุมาน ยูเนียน·อินเตอร์เซกชัน·นิเสธ เพื่อใช้เงื่อนไขอย่าง is_list, is_integer, is_map_key, not is_map_key, tuple_size เป็นข้อมูลชนิดข้อมูล
  • case และเงื่อนไขต่าง ๆ จะสะท้อนข้อมูลจาก clause ก่อนหน้าไปยัง clause ถัดไป ทำให้ตรวจสอบชนิดข้อมูลแบบที่จัดการ nil ก่อน แล้วค่อยทำให้ค่าที่เหลือแคบลงเป็น binary() ได้
  • มีการเพิ่มชนิดข้อมูลให้กับหลายฟังก์ชันเกี่ยวกับ tuple และ map ใน standard library ซึ่งช่วยค้นหา clause ที่ซ้ำซ้อนและโค้ดที่ไม่มีวันถูกรันในโค้ดเบสเดิม
  • ใน “If T: Benchmark for Type Narrowing” สามารถผ่านได้ 12 จาก 13 หมวด แสดงให้เห็นว่าสามารถกู้คืนข้อมูลชนิดข้อมูลที่แม่นยำจากโค้ด Elixir ทั่วไปได้
  • v1.20 ยังปรับปรุงเวลา compile อีกครั้งสำหรับแอปพลิเคชันในสภาพแวดล้อมหลายคอร์ และใน benchmark แบบสังเคราะห์ เครื่องมือ build ของ Elixir ให้ผลลัพธ์เร็วที่สุดในกลุ่มภาษา BEAM
  • ตัวเลือกคอมไพเลอร์ใหม่ :module_definition ช่วยให้เลือกวิธีรันการนิยาม module ได้ด้วยค่าเริ่มต้น :compiled หรือ :interpreted และเปิดใช้ได้ด้วย elixirc_options: [module_definition: :interpreted] ใน mix.exs
  • ตัวเลือก :module_definition ไม่มีผลกับไฟล์ .beam ที่ถูกเขียนลงดิสก์ และเปลี่ยนเฉพาะวิธีรันภายใน defmodule เท่านั้น ซึ่งอาจช่วยปรับปรุงเวลา compile ของโปรเจ็กต์ขนาดใหญ่ได้
  • type signature แบบใหม่ที่ใช้ set-theoretic types มีกำหนดจะนำมาหารือพร้อมการนิยาม typed struct หลังจากงานวิจัยด้านประสิทธิภาพของระบบชนิดข้อมูลใน v1.20, recursive types, parameterized types และการไล่วน key-value ของ map บรรลุผลแล้ว

1 ความคิดเห็น

 
GN⁺ 3 시간 전
ความคิดเห็นจาก Hacker News
  • อาจเป็นเพียงประสบการณ์ส่วนตัว แต่รู้สึกว่าถ้าไม่ใช่ภาษาที่มี type มาตั้งแต่ต้น มันก็ทำงานได้ไม่ดีเท่า ภาษาที่เป็น static type อย่างแท้จริง

    • เห็นด้วย แต่ก็มีอีกมุมมองหนึ่ง: “Why are gradual static types so great?” https://www.benkuhn.net/gradual/
    • ในทางกลับกัน TypeScript ต้องรองรับสารพัดแพตเทิร์นประหลาดที่ผู้คนทำกันมาในภาษาที่ไม่มี type จึงกลายเป็น ระบบ type ที่ฉันชอบที่สุด
  • ฉันทำงานเป็นนักพัฒนา Elixir มืออาชีพมาราว 10 ปี และรอคอยให้มี type มานานมาก ดีใจจริง ๆ ที่ครั้งนี้การเริ่มต้นนั้นเกิดขึ้นจริงแล้ว
    แต่อยากรู้ว่าสถานะที่เข้ามาใน v1.20 นี้เทียบกับ Dialyzer แบบไม่มีสเปกเป็นอย่างไร เท่าที่เข้าใจ แนวทาง success typing ของ Dialyzer ใกล้เคียงกับ “ถ้ามีชุดอาร์กิวเมนต์ที่ใช้แล้วทำงานได้แม้เพียงชุดเดียว ก็จะไม่เตือน” มากกว่า “ถ้ามีชุดอาร์กิวเมนต์ที่อาจล้มเหลวก็จะเตือน” และก่อนหน้านี้ฉันก็คิดว่าสิ่งที่ Elixir ทำตรงนี้น่าจะคล้ายกัน จึงไม่ค่อยรู้สึกว่า Dialyzer มีประโยชน์มากนัก

    • อยากรู้ว่ามันจะค้นพบอะไรได้บ้างใน โค้ดเบส Elixir อายุ 10 ปีที่ยังใช้งานอยู่
  • ฉันเห็นโพสต์เกี่ยวกับระบบ gradual type ของ Elixir บน HN มาหลายครั้ง แต่ไม่ได้ตามรายละเอียด อยากรู้ว่ามีใครทราบไหมว่าระบบ gradual type นี้สามารถเปลี่ยน ความซับซ้อนเชิงกำกับ ของโปรแกรมเมื่อเทียบกับโค้ดที่ไม่มี type ได้หรือไม่
    เท่าที่ฉันทราบ ระบบ gradual type ส่วนใหญ่ เช่น Racket สามารถทำให้โปรแกรมช้าลงในเชิงกำกับได้ และก็มีข้อยกเว้นอยู่บ้าง [1]
    [1] https://doi.org/10.1145/3314221.3314627

    • ระบบ gradual type ของ Elixir ไม่สามารถเปลี่ยน ความซับซ้อนเชิงกำกับ ของโปรแกรมได้ โดยในการออกแบบได้ตัด runtime cast ที่ขอบเขตระหว่าง static/dynamic ซึ่งเป็นสาเหตุที่ทำให้ระบบ gradual type อื่น ๆ ช้าลง ออกไปอย่างชัดเจน
      ระบบ gradual type ส่วนใหญ่มักแทรกการบังคับตรวจเมื่อค่าข้ามขอบเขตระหว่างโค้ดที่มี type กับไม่มี type เช่น ตรวจทุกองค์ประกอบของลิสต์ หรือห่อค่าด้วย type proxy แต่ทีม Elixir ได้เผยแพร่ผลลัพธ์ของ strong arrows เพื่อให้ได้ความถูกต้องโดยไม่ต้องมีการตรวจที่ runtime แบบนั้น และ bytecode ที่คอมไพเลอร์สร้างออกมาก็มีความหมายเชิงพฤติกรรมเหมือนกับโค้ดที่ไม่มี type ทุกประการ
  • น่าแดกดันที่พวกนักวิจารณ์บอกว่าจำเป็นต้องมี type ส่วนแฟน ๆ Elixir ก็บอกว่าไม่ต้องมี type และ Elixir เหมือนมีเวทมนตร์อะไรบางอย่างจนไม่เกิดบั๊กที่เกี่ยวกับ type แต่พอเพิ่ม type เข้าไป ตอนนี้มันกลับช่วยหาบั๊กได้ แล้วไม่ใช่ว่าเมื่อก่อนบอกว่าไม่จำเป็นต่อการป้องกันบั๊กหรือ? ถึงอย่างนั้นก็ถือเป็นการเปลี่ยนแปลงที่ดี ฉันเคยใช้ Elixir พอสมควรและสนุกกับมันมาก แต่ยากจะเห็นด้วยกับ การไม่มี type

    • นี่คือ Goomba fallacy
      https://en.wiktionary.org/wiki/Goomba_fallacy
    • ฉันไม่ได้ตาม Elixir อย่างลึกมากเป็นพิเศษ แต่สิ่งที่เคยเห็นจากฝั่ง Erlang มีภาพที่ต่างออกไปเล็กน้อย คือในเมื่ออย่างไรก็ต้องจัดการกับความล้มเหลวอย่างสวยงามอยู่แล้ว ก็สามารถจัดการข้อผิดพลาดด้าน type ด้วย กลไกกู้คืนจากความล้มเหลว ที่ควรมีอยู่แล้วได้
      ฉันไม่เห็นด้วยกับมุมมองนั้น แต่ก็เป็นข้ออ้างที่ป้องกันได้มากกว่าการบอกว่า “$LANGUAGE เป็นเวทมนตร์” มาก
    • ฉันคงรับประกันไม่ได้ว่าไม่เคยมีใครพูดแบบนั้นเลย แต่ฉันจำไม่ได้ว่าเคยเห็น และถึงมีก็คงเป็นคนส่วนน้อยมาก เหตุผลคัดค้านจริง ๆ โดยมากจะใกล้เคียงกับว่า “type นั้นดี แต่มีต้นทุน และต้นทุนนั้นก็ไม่ได้ให้ผลตอบแทนคุ้มเสมอไป”
      ก่อนที่ ทฤษฎี type เชิงเซต จะพัฒนาขึ้น จุดยืนแบบนั้นก็อาจจะถูกต้องอยู่เหมือนกัน
    • เรื่องเดียวกันนี้ก็เกิดใน JavaScript/TypeScript และ Python ด้วย บางครั้งก็ทำได้แค่ปล่อยให้ผู้คนเชื่อในสิ่งที่เขาอยากเชื่อ
    • นี่แหละวัฏจักรชีวิต ภาษาที่เป็น dynamic type จะมีแฟนคลับขึ้นมา แล้วคนอื่นก็บอกอย่างถูกต้องว่าถ้ามี static type มันจะมีประโยชน์ขึ้นมาก แฟน ๆ ก็รับเรื่องนี้เป็นการโจมตีส่วนตัว แล้วบอกว่า static type ไม่จำเป็น ด้วยเหตุผลต่าง ๆ เช่น “ยังไงก็ไม่ได้มีประโยชน์ขนาดนั้น”, “ขัดกับจิตวิญญาณของภาษา”, “มันก็เป็นแค่ภาษาสคริปต์”, “ใช้ดีบักเกอร์ก็พอ”, “static type ทำลายผลิตภาพ” เป็นต้น
      แล้วสุดท้ายก็มีการเพิ่ม static type เข้าไป เรื่องนี้เกิดกับ Python, JavaScript, Ruby และคงมีอีก
  • การอัปเดต Elixir แล้วไม่มี breaking change ในหลายโปรเจ็กต์ แถมคอมไพเลอร์ยังช่วยหาบั๊กให้ฟรี ๆ เป็นเรื่องที่ดีมาก ฉันชินกับมันไปแล้ว

  • เห็นสิ่งนี้แล้วดีใจมาก ตอนนี้มันเข้าใกล้ระดับ “ภาษาที่ยอดเยี่ยม” จริง ๆ และสำหรับฉัน Elixir คือผู้ท้าชิงอันดับหนึ่ง
    ถ้ามีภาษาอื่นที่ใช้งานง่ายอยู่แล้ว แต่ยังคงเพิ่มฟีเจอร์ยอดเยี่ยมเข้ามาอย่างมั่นคงและปลอดภัยได้ต่อเนื่อง รบกวนบอกที ฉันเคยกำลังจะเชี่ยวชาญ Go แล้วค่อย ๆ ย้ายไปเรียน C# ระดับสูง แต่รู้สึกว่า Go หยุดเพิ่มฟีเจอร์ดี ๆ ไปแล้ว

  • ตลอดเดือนที่ผ่านมา ฉันลองทำ แทร็ก Elixir บน exercism.io https://exercism.org/tracks/elixir
    ยอดเยี่ยมมาก

  • อ้อ เริ่มอีกแล้วสินะ ดูเหมือนจะได้กลับไปเรียน Elixir อีก 1 ปี
    ฉันชอบทุกอย่างของ Elixir แต่ถ้าเทียบกับภาษาอื่นแล้ว Elixir นี่แหละที่ทำให้ฉันสงสัยในตัวเองอยู่เรื่อย ๆ สมองฉันคงไม่เหมาะกับแนว functional แต่การเปลี่ยนแปลงครั้งนี้ก็ทำให้อยากลองอีกครั้ง
    ที่น่าเสียดายคือคงพูดไม่ได้เต็มปากว่า ecosystem เป็นมิตรกับมือใหม่ และเวลาตอบคำถามก็มักมีการตั้งสมมติฐานว่าคนถามรู้ภาษานี้มาพอสมควรแล้ว

    • https://pragprog.com/titles/lhelph/functional-web-developmen...
      อย่าหลงเชื่อชื่อหนังสือ ครึ่งแรกของเล่มเป็นเรื่อง Elixir ล้วน ๆ
      ตลอด 8 ปีที่ผ่านมา ทุกครั้งที่ฉันต้องกลับมาปรับตัวกับ Elixir อีกครั้ง ฉันก็ใช้หนังสือเล่มนี้ และมันได้ผลดีทุกครั้ง ไม่เคยอ่านจบเลย
      เกณฑ์อย่างหนึ่งที่ฉันใช้ดูว่าหนังสือเขียนโปรแกรมแบบโปรเจกต์สอนทีละขั้นพวกนี้ดีไหม คือถึงจะเริ่มหลายรอบแต่ไม่เคยอ่านจบ พอถึงกลางเล่มแล้วมันทำให้ฉันมีเครื่องมือพอจะกลับไปทำงานของตัวเองได้หรือเปล่า
    • ตอนมหาวิทยาลัย ฉันเคยลอง Haskell ครั้งแรกในวิชาประมาณ “ภาพรวมของกระบวนทัศน์การเขียนโปรแกรม” และทรมานกับมันมากจริง ๆ ตอนนั้นฉันเขียนโปรแกรมมาหลายปีแล้ว เลยแทบไม่อยากเชื่อว่าตัวเองจะไร้ความสามารถขนาดนั้นกับการทำเรื่องที่เคยรู้สึกว่าเป็นพื้นฐานมานาน
      แต่ฉันคิดว่ามันไม่ใช่เรื่องสมองไม่เหมาะหรอก มันเป็นเพราะความต่างระหว่างระดับประสบการณ์ที่สั่งสมมาในภาษาแบบ imperative กับการต้องกลับไปเป็นมือใหม่อีกครั้งในสไตล์ pure functional มากกว่า
      เดี๋ยวมันจะค่อย ๆ ดีขึ้นเอง จุดที่ทำให้ฉันเริ่มสบายใจกับ functional programming คือการตระหนักว่าฉันชอบการประกอบโค้ด Bash แบบ “one-liner” ที่เว้นวรรคโล่ง ๆ แค่ไหน ถ้าข้อมูลเริ่มมาในรูปแบบหนึ่ง ฉันก็ dump มันออกมาด้วยคำสั่ง คิดขั้นตอนที่จะทำให้มันเข้าใกล้รูปแบบที่ต้องการมากขึ้น แล้ว pipe ไปยังคำสั่งถัดไป จากนั้นก็ดูอีกที ทำแบบนี้ต่อไปเรื่อย ๆ สุดท้ายก็มักจะเหลือเป็นชุดของการแปลงข้อมูลที่ไม่ไปแก้ไขข้อมูลเดิม
      เหตุผลหนึ่งที่สิ่งนี้รู้สึกสบายใน shell ก็เพราะเราเดินไปมาบน file system ทุกวันและค่อย ๆ สะสมคลังคำสั่งไว้ “ฟังก์ชัน” ที่คุ้นมือในสภาพแวดล้อมตระกูล Unix จึงใหญ่ขึ้นมากตลอดหลายปี ในสภาพแวดล้อม pure functional programming ก็ต้องทำแบบเดียวกัน เพียงแต่ต้องออกแรงเรียนรู้คำศัพท์มากขึ้นอีกหน่อย “คำสั่ง” ที่ใช้บ่อยก็จะกลายเป็นฟังก์ชันอย่าง map, fold, zip แทน grep, cat, sort
      แต่แก่นแท้จริง ๆ เหมือนกัน และเสน่ห์ของการสร้าง pipeline ก็ใช้ได้กับทั้งสองแบบเหมือนกัน คุณสร้างเป็นชิ้น ๆ ได้ และในแต่ละจิ๊กซอว์ก็ลืมขั้นก่อนหน้าไปได้เลย แล้วโฟกัสแค่ว่าข้อมูลตรงหน้าควรถูกแปลงต่ออย่างไร ความใช้บริบทต่ำนี้ทั้งสดใหม่และสบายใจ
      หวังว่าคุณจะลองดูและสนุกกับมัน พอคุณเริ่มสนุกกับการยังทำอะไรบางอย่างไม่เก่งได้ ในที่สุดคุณก็จะเก่งมันเอง
    • สงสัยว่าคุณรู้ Rust บ้างไหม ฉันเองก็ไม่ได้มีประสบการณ์กับภาษา functional มากนัก แต่ Gleam ให้ความรู้สึกคุ้นเคยเพราะมีความเป็น Rust อยู่ในตัว เลยทำให้ฉันโฟกัสที่แนวคิดได้มากกว่าวากยสัมพันธ์
      แน่นอนว่าฉันแค่ใช้มันอยู่ไม่กี่บ่าย แต่ถ้าจะฝึกสมองตัวเองให้กลับมาเข้ากับภาษา functional อีกครั้ง ฉันคงเลือก Gleam เพราะความคุ้นเคยนี่แหละ
    • แนะนำให้ลองถามใน ElixirForum ฉันไม่เคยเห็นปฏิกิริยาเป็นปฏิปักษ์แบบจริงจังเลย
      บางทีก็มีโพสต์ที่คลุมเครือจนไม่มีใครสนใจ หรือดูมีกลิ่น “ช่วยทำการบ้านให้หน่อย” เลยถูกเมิน
      แต่โพสต์ที่แสดงความอยากรู้อยากเห็นจริง ๆ เท่าที่ฉันเห็น ทุกอันมีคนตอบ
    • คำพูดแบบนี้ทำให้ฉันงงทุกที โปรแกรมเชิงวัตถุที่เต็มไปด้วย state ต่างหากที่ทำให้ฉันให้เหตุผลตามได้ยากกว่ามาก
  • ยอดเยี่ยม ใน 1.20 ดูเหมือนการคอมไพล์ umbrella app ขนาดใหญ่ของเราจะเร็วขึ้นพอสมควร

  • อยากรู้ว่าเทียบกับ Gleam แล้วเป็นอย่างไร หรือว่าตอนนี้เหตุผลที่ควรใช้ Elixir แทน Gleam คืออะไร? Phoenix โดยเฉพาะ LiveView ก็น่าจะเป็นจุดดึงดูดสำคัญของ Elixir

    • มันต่างกันตรงว่าคุณชอบ Rust หรือชอบ Erlang มากกว่า ใช้ Gleam จะให้ความรู้สึกเหมือนใช้ Rust ส่วนใช้ Elixir จะให้ความรู้สึกเหมือนใช้ Erlang
      ฉันไม่รู้สถานะปัจจุบันของ Gleam OTP แต่ครั้งสุดท้ายที่ดู มันยังไม่ค่อยดี
      ถ้าคุณไม่ได้สนใจความต่างเหล่านั้นและแคร์แค่เรื่อง type ก็ใช้ Gleam ได้ แต่ถ้าอย่างนั้นจะไม่ใช้ Rust ไปเลยล่ะ?
    • บนเว็บไซต์ของ Gleam มีเอกสารเปรียบเทียบอยู่เลย
    • Gleam ไม่มี macro และไลบรารี Elixir จำนวนมากอย่าง Phoenix หรือ Ecto ก็ใช้ macro ได้อย่างมีประสิทธิภาพมาก
      ตัวอย่างเช่น ใน Gleam การ decode/encode JSON มักจะค่อนข้างยืดยาว ใน Rust คุณ derive serde ได้ ส่วนใน Elixir แค่เรียกฟังก์ชันครั้งเดียว
      Elixir มี ecosystem ที่ mature กว่า ตัวอย่างเช่น บน Gleam คุณจะใช้ Phoenix หรือ framework อื่นของ Gleam ก็ได้ แต่ประสบการณ์มันไม่เหมือนกัน
      เหตุผลใหญ่ที่ทำให้ Gleam น่าสนใจกว่า Elixir คือเรื่อง type และตอนนี้ Elixir ก็กำลังลดช่องว่างนั้นลง อีกอย่างคือมันคอมไพล์เป็น JavaScript ได้ ซึ่งใน Elixir ก็มี Hologram ที่ทำอะไรคล้ายกัน
      โดยส่วนตัวฉันชอบ type system ของ Gleam และ syntax แบบ Rust มากกว่า แต่ตอนนี้ฉันยังรู้สึกว่า Elixir เป็นตัวเลือกที่ดีกว่าสำหรับ โปรเจกต์พัฒนาเว็บ ทั้งหมดของฉัน
    • เอาจริง ๆ ก็เพราะ Phoenix และ Ecto นั่นแหละ