Elixir v1.20: ตอนนี้เป็นภาษาแบบค่อยเป็นค่อยไปที่มีระบบชนิดข้อมูล
(elixir-lang.org)- การอนุมานชนิดข้อมูลและการตรวจสอบชนิดข้อมูลแบบค่อยเป็นค่อยไป (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 ความคิดเห็น
ความคิดเห็นจาก Hacker News
อาจเป็นเพียงประสบการณ์ส่วนตัว แต่รู้สึกว่าถ้าไม่ใช่ภาษาที่มี type มาตั้งแต่ต้น มันก็ทำงานได้ไม่ดีเท่า ภาษาที่เป็น static type อย่างแท้จริง
ฉันทำงานเป็นนักพัฒนา Elixir มืออาชีพมาราว 10 ปี และรอคอยให้มี type มานานมาก ดีใจจริง ๆ ที่ครั้งนี้การเริ่มต้นนั้นเกิดขึ้นจริงแล้ว
แต่อยากรู้ว่าสถานะที่เข้ามาใน v1.20 นี้เทียบกับ Dialyzer แบบไม่มีสเปกเป็นอย่างไร เท่าที่เข้าใจ แนวทาง success typing ของ Dialyzer ใกล้เคียงกับ “ถ้ามีชุดอาร์กิวเมนต์ที่ใช้แล้วทำงานได้แม้เพียงชุดเดียว ก็จะไม่เตือน” มากกว่า “ถ้ามีชุดอาร์กิวเมนต์ที่อาจล้มเหลวก็จะเตือน” และก่อนหน้านี้ฉันก็คิดว่าสิ่งที่ Elixir ทำตรงนี้น่าจะคล้ายกัน จึงไม่ค่อยรู้สึกว่า Dialyzer มีประโยชน์มากนัก
ฉันเห็นโพสต์เกี่ยวกับระบบ gradual type ของ Elixir บน HN มาหลายครั้ง แต่ไม่ได้ตามรายละเอียด อยากรู้ว่ามีใครทราบไหมว่าระบบ gradual type นี้สามารถเปลี่ยน ความซับซ้อนเชิงกำกับ ของโปรแกรมเมื่อเทียบกับโค้ดที่ไม่มี type ได้หรือไม่
เท่าที่ฉันทราบ ระบบ gradual type ส่วนใหญ่ เช่น Racket สามารถทำให้โปรแกรมช้าลงในเชิงกำกับได้ และก็มีข้อยกเว้นอยู่บ้าง [1]
[1] https://doi.org/10.1145/3314221.3314627
ระบบ gradual type ส่วนใหญ่มักแทรกการบังคับตรวจเมื่อค่าข้ามขอบเขตระหว่างโค้ดที่มี type กับไม่มี type เช่น ตรวจทุกองค์ประกอบของลิสต์ หรือห่อค่าด้วย type proxy แต่ทีม Elixir ได้เผยแพร่ผลลัพธ์ของ strong arrows เพื่อให้ได้ความถูกต้องโดยไม่ต้องมีการตรวจที่ runtime แบบนั้น และ bytecode ที่คอมไพเลอร์สร้างออกมาก็มีความหมายเชิงพฤติกรรมเหมือนกับโค้ดที่ไม่มี type ทุกประการ
น่าแดกดันที่พวกนักวิจารณ์บอกว่าจำเป็นต้องมี type ส่วนแฟน ๆ Elixir ก็บอกว่าไม่ต้องมี type และ Elixir เหมือนมีเวทมนตร์อะไรบางอย่างจนไม่เกิดบั๊กที่เกี่ยวกับ type แต่พอเพิ่ม type เข้าไป ตอนนี้มันกลับช่วยหาบั๊กได้ แล้วไม่ใช่ว่าเมื่อก่อนบอกว่าไม่จำเป็นต่อการป้องกันบั๊กหรือ? ถึงอย่างนั้นก็ถือเป็นการเปลี่ยนแปลงที่ดี ฉันเคยใช้ Elixir พอสมควรและสนุกกับมันมาก แต่ยากจะเห็นด้วยกับ การไม่มี type
https://en.wiktionary.org/wiki/Goomba_fallacy
ฉันไม่เห็นด้วยกับมุมมองนั้น แต่ก็เป็นข้ออ้างที่ป้องกันได้มากกว่าการบอกว่า “$LANGUAGE เป็นเวทมนตร์” มาก
ก่อนที่ ทฤษฎี 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 เป็นมิตรกับมือใหม่ และเวลาตอบคำถามก็มักมีการตั้งสมมติฐานว่าคนถามรู้ภาษานี้มาพอสมควรแล้ว
อย่าหลงเชื่อชื่อหนังสือ ครึ่งแรกของเล่มเป็นเรื่อง Elixir ล้วน ๆ
ตลอด 8 ปีที่ผ่านมา ทุกครั้งที่ฉันต้องกลับมาปรับตัวกับ Elixir อีกครั้ง ฉันก็ใช้หนังสือเล่มนี้ และมันได้ผลดีทุกครั้ง ไม่เคยอ่านจบเลย
เกณฑ์อย่างหนึ่งที่ฉันใช้ดูว่าหนังสือเขียนโปรแกรมแบบโปรเจกต์สอนทีละขั้นพวกนี้ดีไหม คือถึงจะเริ่มหลายรอบแต่ไม่เคยอ่านจบ พอถึงกลางเล่มแล้วมันทำให้ฉันมีเครื่องมือพอจะกลับไปทำงานของตัวเองได้หรือเปล่า
แต่ฉันคิดว่ามันไม่ใช่เรื่องสมองไม่เหมาะหรอก มันเป็นเพราะความต่างระหว่างระดับประสบการณ์ที่สั่งสมมาในภาษาแบบ imperative กับการต้องกลับไปเป็นมือใหม่อีกครั้งในสไตล์ pure functional มากกว่า
เดี๋ยวมันจะค่อย ๆ ดีขึ้นเอง จุดที่ทำให้ฉันเริ่มสบายใจกับ functional programming คือการตระหนักว่าฉันชอบการประกอบโค้ด Bash แบบ “one-liner” ที่เว้นวรรคโล่ง ๆ แค่ไหน ถ้าข้อมูลเริ่มมาในรูปแบบหนึ่ง ฉันก็ dump มันออกมาด้วยคำสั่ง คิดขั้นตอนที่จะทำให้มันเข้าใกล้รูปแบบที่ต้องการมากขึ้น แล้ว pipe ไปยังคำสั่งถัดไป จากนั้นก็ดูอีกที ทำแบบนี้ต่อไปเรื่อย ๆ สุดท้ายก็มักจะเหลือเป็นชุดของการแปลงข้อมูลที่ไม่ไปแก้ไขข้อมูลเดิม
เหตุผลหนึ่งที่สิ่งนี้รู้สึกสบายใน shell ก็เพราะเราเดินไปมาบน file system ทุกวันและค่อย ๆ สะสมคลังคำสั่งไว้ “ฟังก์ชัน” ที่คุ้นมือในสภาพแวดล้อมตระกูล Unix จึงใหญ่ขึ้นมากตลอดหลายปี ในสภาพแวดล้อม pure functional programming ก็ต้องทำแบบเดียวกัน เพียงแต่ต้องออกแรงเรียนรู้คำศัพท์มากขึ้นอีกหน่อย “คำสั่ง” ที่ใช้บ่อยก็จะกลายเป็นฟังก์ชันอย่าง map, fold, zip แทน grep, cat, sort
แต่แก่นแท้จริง ๆ เหมือนกัน และเสน่ห์ของการสร้าง pipeline ก็ใช้ได้กับทั้งสองแบบเหมือนกัน คุณสร้างเป็นชิ้น ๆ ได้ และในแต่ละจิ๊กซอว์ก็ลืมขั้นก่อนหน้าไปได้เลย แล้วโฟกัสแค่ว่าข้อมูลตรงหน้าควรถูกแปลงต่ออย่างไร ความใช้บริบทต่ำนี้ทั้งสดใหม่และสบายใจ
หวังว่าคุณจะลองดูและสนุกกับมัน พอคุณเริ่มสนุกกับการยังทำอะไรบางอย่างไม่เก่งได้ ในที่สุดคุณก็จะเก่งมันเอง
แน่นอนว่าฉันแค่ใช้มันอยู่ไม่กี่บ่าย แต่ถ้าจะฝึกสมองตัวเองให้กลับมาเข้ากับภาษา functional อีกครั้ง ฉันคงเลือก Gleam เพราะความคุ้นเคยนี่แหละ
บางทีก็มีโพสต์ที่คลุมเครือจนไม่มีใครสนใจ หรือดูมีกลิ่น “ช่วยทำการบ้านให้หน่อย” เลยถูกเมิน
แต่โพสต์ที่แสดงความอยากรู้อยากเห็นจริง ๆ เท่าที่ฉันเห็น ทุกอันมีคนตอบ
ยอดเยี่ยม ใน 1.20 ดูเหมือนการคอมไพล์ umbrella app ขนาดใหญ่ของเราจะเร็วขึ้นพอสมควร
อยากรู้ว่าเทียบกับ Gleam แล้วเป็นอย่างไร หรือว่าตอนนี้เหตุผลที่ควรใช้ Elixir แทน Gleam คืออะไร? Phoenix โดยเฉพาะ LiveView ก็น่าจะเป็นจุดดึงดูดสำคัญของ Elixir
ฉันไม่รู้สถานะปัจจุบันของ Gleam OTP แต่ครั้งสุดท้ายที่ดู มันยังไม่ค่อยดี
ถ้าคุณไม่ได้สนใจความต่างเหล่านั้นและแคร์แค่เรื่อง type ก็ใช้ Gleam ได้ แต่ถ้าอย่างนั้นจะไม่ใช้ Rust ไปเลยล่ะ?
ตัวอย่างเช่น ใน 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 เป็นตัวเลือกที่ดีกว่าสำหรับ โปรเจกต์พัฒนาเว็บ ทั้งหมดของฉัน