อ่าน 22 นาที
นิม (ภาษาโปรแกรม)
Nim เป็น ภาษาโปรแกรมระบบ ระดับสูง แบบ คอมไพล์ได้ อเนกประสงค์ รองรับ หลาย พาราดิกม์ กำหนด ประเภทแบบคงที่ [ 9 ] ได้รับการออกแบบและพัฒนาโดยทีมงานที่นำโดย Andreas Rumpf Nim...
นิม (ภาษาโปรแกรม)
| นิม | |
|---|---|
โลโก้มงกุฎนิม | |
| กระบวนทัศน์ | หลายกระบวนทัศน์ : คอมไพล์ , พร้อมกัน , ขั้น ตอน , คำสั่ง , ฟังก์ชัน , เชิงวัตถุ , เมตา |
| ออกแบบโดย | แอนเดรียส รัมป์ฟ |
| นักพัฒนา | ทีมนิมหลาง[ 1 ] |
| ปรากฏครั้งแรก | 2008 |
| เวอร์ชันเสถียร | 2.2.10 [ 2 ] |
| วินัยในการพิมพ์ | คงที่[ 3 ]แข็งแกร่ง [ 4 ]อนุมานได้โครงสร้าง |
| ขอบเขต | คำศัพท์ |
| ภาษาการใช้งาน | ปาสคาล (2005–2008) นิม (2008–ปัจจุบัน, ดำเนินงานด้วยตนเอง) |
| แพลตฟอร์ม | IA-32 , x86-64 , ARM , Aarch64 , RISC-V , PowerPC ... [ 5 ] |
| โอเอส | ข้ามแพลตฟอร์ม[ 6 ] |
| ใบอนุญาต | ใบอนุญาต MIT [ 7 ] |
| นามสกุลไฟล์ | .nim, .nims, .nimble |
| เว็บไซต์ | nim-lang |
| ได้รับอิทธิพลจาก | |
| Ada , Modula-3 , Lisp , C++ , Object Pascal , Python , Oberon , Rust , ParaSail [ 8 ] | |
Nimเป็นภาษาโปรแกรมระบบระดับสูงแบบคอมไพล์ได้อเนกประสงค์รองรับหลายพาราดิกม์กำหนดประเภทแบบคงที่[ 9 ]ได้รับการออกแบบและพัฒนาโดยทีมงานที่นำโดย Andreas Rumpf Nim มีเป้าหมายที่จะเป็น "มีประสิทธิภาพ แสดงออกได้ดี และสง่างาม" [ 10 ]และรองรับ พาราดิกม์การเขียนโปรแกรมแบบเม ตาโปรแกรมมิงฟังก์ชันการส่งข้อความ [ 11 ] แบบขั้นตอนและแบบเชิงวัตถุ Nim มีคุณสมบัติต่างๆ เช่นการสร้างโค้ดในเวลาคอมไพล์ประเภทข้อมูลเชิงพีชคณิตและอินเทอร์เฟซฟังก์ชันภายนอก (FFI) สำหรับการเชื่อมต่อกับC , C++ , Objective-CและJavaScriptนอกจากนี้ยังรองรับการคอมไพล์ไปยังภาษาเหล่านี้ในรูปแบบตัวแทนระดับกลางด้วย
คำอธิบาย
Nim เป็นภาษาที่มีการกำหนดประเภทแบบคงที่[ 12 ]รองรับ คุณสมบัติ เมตาโปรแกรม มิ่งในเวลาคอมไพล์ เช่น มาโครทางไวยากรณ์และมาโครการเขียนเทอมใหม่ [ 13 ] มาโครการเขียนเทอมใหม่ช่วยให้ การใช้งาน ไลบรารีของโครงสร้างข้อมูลทั่วไป เช่น bignums และเมทริกซ์ สามารถใช้งานได้อย่างมีประสิทธิภาพและผสานรวมทางไวยากรณ์ ราวกับว่าเป็นสิ่งอำนวยความสะดวกในภาษา[ 14 ]รองรับตัววนซ้ำและสามารถใช้เป็นเอนทิตีระดับแรกได้[ 13 ]เช่นเดียวกับฟังก์ชัน ทำให้สามารถใช้วิธีการเขียนโปรแกรมเชิงฟังก์ชัน ได้ รองรับการเขียนโปรแกรมเชิงวัตถุ โดย การสืบทอดและการเรียกใช้หลายรายการฟังก์ชันสามารถเป็นแบบเจเนริกและโอเวอร์โหลดได้ และเจเนริก ได้รับการปรับปรุงเพิ่มเติมโดยการสนับสนุน คลาสประเภทของNim รองรับ การโอเวอร์โหลดตัวดำเนินการด้วย[ 13 ] Nim มีกลยุทธ์การจัดการหน่วยความจำที่ปรับแต่งได้หลายแบบ รวมถึงการรวบรวมขยะแบบติดตามการนับการอ้างอิงและระบบแบบแมนนวลทั้งหมดโดยค่าเริ่มต้นคือการนับการอ้างอิง แบบกำหนดได้ พร้อมการเพิ่มประสิทธิภาพผ่านความหมายของการย้ายและการรวบรวมวงจรผ่านการลบแบบทดลอง[ 15 ]
[Nim] ... นำเสนอการออกแบบที่แปลกใหม่ที่สุดซึ่งผสมผสานระหว่างPascalและPythonและคอมไพล์เป็นโค้ด C หรือ JavaScript [ 16 ]
— แอนดรูว์ บินสต็อก บรรณาธิการบริหารของวารสารดร. ด็อบส์ปี 2014
ณ เดือนสิงหาคม พ.ศ. 2566 Nim คอมไพล์เป็น C, C++, JavaScript, Objective-C, [ 17 ]และ LLVM [ 18 ]
ประวัติศาสตร์
| สาขา | เวอร์ชั่น | วันที่วางจำหน่าย[ 19 ] |
|---|---|---|
| 0.x | 0.10.2 | 29 ธันวาคม 2014 |
| 0.11.2 | 4 พฤษภาคม 2558 | |
| 0.12.0 | 27 ตุลาคม 2558 | |
| 0.13.0 | 18 มกราคม 2559 | |
| 0.14.2 | 9 มิถุนายน 2559 | |
| 0.15.2 | 23 ตุลาคม 2559 | |
| 0.16.0 | 8 มกราคม 2560 | |
| 0.17.2 | 7 กันยายน 2017 | |
| 0.18.0 | 1 มีนาคม 2018 | |
| 0.19.6 | 13 พฤษภาคม 2562 | |
| 0.20.2 | 17 มิถุนายน 2562 | |
| 1.0 | 1.0.0 | 23 กันยายน 2019 |
| 1.0.10 | 27 ตุลาคม 2020 | |
| 1.2 | 1.2.0 | 2020-04-03 |
| 1.2.18 | 9 กุมภาพันธ์ 2022 | |
| 1.4 | 1.4.0 | 16 ตุลาคม 2020 |
| 1.4.8 | 25 พฤษภาคม 2021 | |
| 1.6 | 1.6.0 | 19 ตุลาคม 2021 |
| 1.6.20 | 16 เมษายน 2567 | |
| 2.0 | 2.0.0 | 1 สิงหาคม 2023 |
| 2.0.16 | 22 เมษายน 2568 | |
| 2.2 | 2.2.0 | 2024-10-02 |
| 2.2.10 | 24 เมษายน 2569 | |
ตำนาน: ไม่ได้รับการสนับสนุน ได้รับการสนับสนุน เวอร์ชั่นล่าสุด | ||
| สำหรับแต่ละสาขา 0.x จะแสดงเฉพาะเวอร์ชันย่อยล่าสุดเท่านั้นสำหรับสาขาที่ใหม่กว่า จะแสดงทั้งเวอร์ชันย่อยแรกและเวอร์ชันย่อยล่าสุด | ||
Andreas Rumpf เป็นผู้ออกแบบและผู้พัฒนา Nim คนแรก เขาได้รับประกาศนียบัตรด้านวิทยาการคอมพิวเตอร์จากมหาวิทยาลัยเทคนิคไคเซอร์สเลาเทิร์นประเทศเยอรมนีความสนใจในการวิจัยของเขารวมถึงระบบเรียลไทม์แบบแข็งระบบฝังตัวการสร้างคอมไพเลอร์และปัญญาประดิษฐ์[ 20 ]
การพัฒนาเบื้องต้นของ Nim เริ่มขึ้นในปี 2548 ภายใต้ชื่อNimrodและเปิดตัวสู่สาธารณะในปี 2551 [ 21 ] : 4–11
คอมไพเลอร์ Nim เวอร์ชันแรกเขียนด้วยภาษา Pascalโดยใช้คอมไพเลอร์Free Pascal [ 22 ]ในปี 2551 คอมไพเลอร์เวอร์ชันที่เขียนด้วยภาษา Nim ได้ถูกเผยแพร่[ 23 ]คอมไพเลอร์นี้เป็นซอฟต์แวร์โอเพนซอร์สฟรีและได้รับการพัฒนาโดยชุมชนอาสาสมัครที่ทำงานร่วมกับ Andreas Rumpf [ 24 ]ภาษาดังกล่าวได้รับการเปลี่ยนชื่ออย่างเป็นทางการจากNimrodเป็นNimเมื่อมีการเผยแพร่เวอร์ชัน 0.10.2 ในเดือนธันวาคม 2557 [ 25 ]เมื่อวันที่ 23 กันยายน 2562 เวอร์ชัน 1.0 ของ Nim ได้ถูกเผยแพร่ ซึ่งแสดงให้เห็นถึงความสมบูรณ์ของภาษาและชุดเครื่องมือ เมื่อวันที่ 1 สิงหาคม 2566 เวอร์ชัน 2.0 ของ Nim ได้ถูกเผยแพร่ ซึ่งแสดงให้เห็นถึงความสมบูรณ์ ความเสถียร และการเปลี่ยนไปใช้โมเดลหน่วยความจำ ARC/ORC [ 26 ]
การออกแบบภาษา
ไวยากรณ์
ไวยากรณ์ของ Nim คล้ายกับของPython [ 27 ] บล็อกโค้ดและคำสั่งซ้อนกันจะถูกระบุโดยใช้ช่องว่างตามกฎออฟไซด์ คำหลัก หลายคำเหมือนกับคำที่เทียบเท่าใน Python ซึ่งส่วนใหญ่เป็นคำหลักภาษาอังกฤษ ในขณะที่ภาษาโปรแกรมอื่นๆ มักใช้เครื่องหมายวรรคตอน ด้วยเป้าหมายที่จะปรับปรุงภาษาที่มีอิทธิพล แม้ว่า Nim จะรองรับ ไวยากรณ์แบบ เยื้องเหมือน Python แต่ก็เพิ่มความยืดหยุ่นเพิ่มเติม ตัวอย่างเช่นคำสั่ง เดียว อาจครอบคลุมหลายบรรทัดหากมีเครื่องหมายจุลภาคหรือตัวดำเนินการไบนารีอยู่ที่ท้ายแต่ละบรรทัด Nim ยังรองรับตัวดำเนินการที่ผู้ใช้กำหนดเองด้วย
ต่างจาก Python, Nim ใช้ระบบการกำหนดประเภทข้อมูลแบบคงที่ (static typing) ระบบประเภทของ Nim ช่วยให้การแปลงประเภทข้อมูลการแคสต์ทำได้ง่าย และมีไวยากรณ์สำหรับการเขียนโปรแกรมแบบเจเนริก ที่สำคัญ Nim มีคลาสประเภท (type classes) ที่สามารถใช้แทนประเภทข้อมูลได้หลายประเภท และมีคลาสประเภทดังกล่าวให้ใช้งานได้ทันที คลาสประเภทช่วยให้สามารถทำงานกับประเภทข้อมูลหลายประเภทได้ราวกับว่าเป็นประเภทข้อมูลเดียว ตัวอย่างเช่น:
openarray– แสดงถึงอาร์เรย์ที่มีขนาดแตกต่างกัน ลำดับ และสตริงSomeSignedInt– แสดงถึงชนิดข้อมูลจำนวนเต็มที่มีเครื่องหมายทั้งหมดSomeInteger– แสดงถึงชนิดข้อมูลจำนวนเต็มทั้งหมด ไม่ว่าจะเป็นจำนวนเต็มมีเครื่องหมายหรือไม่ก็ตามSomeOrdinal– แสดงถึงชนิดข้อมูลพื้นฐานที่นับได้และเรียงลำดับได้ทั้งหมด ยกเว้นจำนวนที่ไม่ใช่จำนวนเต็ม
ตัวอย่างโค้ดนี้แสดงวิธีการใช้งาน typeclasses ในภาษา Nim:
# มาประกาศฟังก์ชันที่รับตัวเลขชนิดใดก็ได้และแสดงค่าทศนิยมของตัวเลขนั้นกัน# ใน Nim ฟังก์ชันที่มีผลข้างเคียงเรียกว่า "proc" proc timesTwo ( i : SomeNumber ) = echo i * 2# มาเขียนฟังก์ชันอีกฟังก์ชันหนึ่งที่รับประเภทลำดับใดๆ ก็ได้ และส่งคืนค่า# สองเท่าของค่าที่ป้อนเข้ามาในรูปแบบเดิม หากเป็นตัวเลขหรือส่งคืนค่าที่ป้อนเข้ามาเองในกรณีอื่นๆ# เราใช้ Type(T) ทั่วไป และระบุว่าต้องเป็น Ordinal เท่านั้นfunc twiceIfIsNumber [ T : SomeOrdinal ] ( i : T ): T = when T is SomeNumber : # `when` คือ `if` ที่ประเมินระหว่างการคอมไพล์result = i * 2 # คุณสามารถเขียน `return i * 2` ได้เช่นกันelse : # หาก Ordinal ไม่ใช่ตัวเลข จะถูกแปลงเป็น int # คูณด้วยสอง และแปลงกลับเป็นประเภทพื้นฐานresult = ( i . int * 2 ). TechotwiceIfIsNumber(67)# Passes an int to the functionecho twiceIfIsNumber(67u8) # Passes an uint8echotwiceIfIsNumber(true)# Passes a bool (Which is also an Ordinal)
อิทธิพล
ตามที่ผู้สร้างภาษากล่าวไว้ Nim ถูกสร้างขึ้นเพื่อรวมส่วนที่ดีที่สุดของระบบการพิมพ์ Ada ความยืดหยุ่น ของ PythonและระบบมาโครLisp ที่ทรงพลัง [ 28 ]
นิมได้รับอิทธิพลจากลักษณะเฉพาะของภาษาที่มีอยู่เดิม ซึ่งรวมถึงสิ่งต่อไปนี้:
- Modula-3 : พอยเตอร์แบบติดตามและแบบไม่ติดตาม
- ภาษา Pascal แบบออบเจ็กต์ : ชุดบิตที่ปลอดภัยต่อชนิดข้อมูล ( ชุดของอักขระ ), ไวยากรณ์คำสั่ง case, ชื่อชนิดข้อมูลและชื่อไฟล์ต่างๆ ในไลบรารีมาตรฐาน
- Ada : ประเภทช่วงย่อย, ประเภทที่แตกต่างกัน, ตัวแปรที่ปลอดภัย – ออบเจ็กต์เคส
- C++ : การโอเวอร์โหลดตัวดำเนินการ , การเขียนโปรแกรมแบบเจเนริก
- Python : กฎล้ำหน้า
- Lisp : ระบบมาโคร , การจัดการ AST , ความเป็นเอกรูป
- โอเบรอน : เครื่องหมายการส่งออก
- C# : async/await , lambda macros
- ParaSail : การเขียนโปรแกรมแบบไม่มีตัวชี้[ 8 ]
ไวยากรณ์การเรียกฟังก์ชันแบบเดียวกัน
Nim รองรับไวยากรณ์การเรียกฟังก์ชันแบบเดียวกัน (UFCS) [ 29 ]และความเท่าเทียมกันของตัวระบุ ซึ่งให้ความยืดหยุ่นในการใช้งานในระดับสูง
ตัวอย่างเช่น แต่ละบรรทัดเหล่านี้จะพิมพ์"hello world"เหมือนกัน เพียงแต่ใช้ไวยากรณ์ที่แตกต่างกัน:
echo "hello world" echo ( "hello world" ) "hello world" . echo () "hello world" . echo echo ( "hello" , " world" ) "hello" . echo ( " world" ) "hello" . echo " world"ความเท่าเทียมกันของตัวระบุ
Nim แทบจะไม่คำนึงถึงรูปแบบเลยตัวระบุ สองตัว จะถือว่าเท่ากันหากแตกต่างกันเพียงแค่การใช้ตัวพิมพ์ใหญ่และเครื่องหมายขีดล่าง ตราบใดที่อักขระตัวแรกเหมือนกัน นี่เป็นการเปิดใช้งานการผสมผสานรูปแบบต่างๆ ในไลบรารี ผู้ใช้คนหนึ่งสามารถเขียนไลบรารีโดยใช้ snake_case เป็นข้อกำหนด และผู้ใช้คนอื่นสามารถใช้ไลบรารีนั้นในรูปแบบ camelCase ได้โดยไม่มีปัญหา[ 30 ]
const useHttps = true assert useHttps == useHttps assert useHTTPS == useHttps assert use_https == useHttpsการหยุด
คุณสมบัติ การจำกัดขอบเขตช่วยให้สามารถใช้ชื่อใดก็ได้สำหรับตัวแปรหรือฟังก์ชัน แม้ว่าชื่อเหล่านั้นจะเป็นคำสงวนสำหรับคำหลักก็ตาม ตัวอย่างของการจำกัดขอบเขตคือความสามารถในการกำหนดตัวแปรชื่อifโดยไม่ขัดแย้งกับคำหลักifการใช้งานของ Nim ทำได้โดยใช้เครื่องหมายแบ็กติ๊ก ทำให้สามารถใช้คำสงวนใดก็ได้เป็นตัวระบุ[ 31 ]
ประเภทType = object ` int` : intlet ` object ` = Type (` int `: 9 ) assert ` object ` is Type assert ` object `.` int ` == 9var ` var ` = 42 ให้` ให้` = 8 ยืนยัน` var ` + ` ให้` == 50const ` assert ` = true assert ` assert `คอมไพเลอร์
โดยค่าเริ่มต้นคอมไพเลอร์ Nim จะสร้าง โค้ด C ที่รวดเร็วและได้รับการปรับให้เหมาะสม โดยจะเลื่อนการคอมไพล์เป็นโค้ดออบเจ็กต์ไปยังคอมไพเลอร์ C ภายนอก [ 32 ]เพื่อใช้ประโยชน์จากการปรับให้เหมาะสมและความสามารถในการพกพาของคอมไพเลอร์ที่มีอยู่ รองรับคอมไพเลอร์ C หลายตัว รวมถึงClang , Microsoft Visual C++ (MSVC), MinGWและGNU Compiler Collection (GCC) นอกจากนี้ คอมไพเลอร์ Nim ยังสามารถสร้าง โค้ด C++ , Objective-CและJavaScriptเพื่อให้สามารถเชื่อมต่อกับอินเทอร์เฟซการเขียนโปรแกรมแอปพลิเคชัน ( API ) ที่เขียนด้วยภาษาเหล่านั้น ได้อย่างง่ายดาย [ 9 ]นักพัฒนาสามารถเขียนใน Nim จากนั้นคอมไพล์เป็นภาษาใดก็ได้ที่รองรับ นอกจากนี้ยังช่วยให้สามารถเขียนแอปพลิเคชันสำหรับiOSและAndroidได้อีกด้วย ยังมี แบ็กเอนด์ LLVM ที่ไม่เป็นทางการ ซึ่งช่วยให้สามารถใช้คอมไพเลอร์ Nim ในลักษณะแบบสแตนด์อะโลนได้[ 18 ]
คอมไพเลอร์ Nim เป็นแบบโฮสต์ตัวเองหมายความว่ามันถูกเขียนขึ้นด้วยภาษา Nim [ 33 ]คอมไพเลอร์รองรับการคอมไพล์ข้ามแพลตฟอร์ม ดังนั้นจึงสามารถคอมไพล์ซอฟต์แวร์สำหรับระบบปฏิบัติการที่รองรับได้ ไม่ว่าจะเป็นเครื่องพัฒนาใดก็ตาม ซึ่งมีประโยชน์สำหรับการคอมไพล์แอปพลิเคชันสำหรับระบบฝังตัว และสำหรับสถาปัตยกรรมคอมพิวเตอร์ที่ไม่ธรรมดาและหายาก
ตัวเลือกคอมไพเลอร์
โดยค่าเริ่มต้น คอมไพเลอร์ Nim จะสร้างบิลด์ดีบัก[ 34 ] ด้วยตัวเลือกนี้สามารถสร้างบิลด์รีลีสได้ ซึ่งได้รับการปรับให้เหมาะสมเพื่อความเร็วและมีการตรวจสอบรันไทม์น้อยลง-d:release[ 34 ]ด้วยตัว เลือกนี้-d:dangerสามารถปิดใช้งานการตรวจสอบรันไทม์ทั้งหมดได้ หากต้องการความเร็วสูงสุด[ 34 ]
การจัดการหน่วยความจำ
Nim รองรับกลยุทธ์การจัดการหน่วยความจำหลายแบบ รวมถึงดังต่อไปนี้: [ 35 ]
--mm:arc– การนับการอ้างอิงอัตโนมัติ(ARC) พร้อม การเพิ่มประสิทธิภาพ ความหมายของการย้ายเสนอฮีปที่ใช้ร่วมกัน ให้ประสิทธิภาพที่กำหนดได้อย่างสมบูรณ์สำหรับระบบเรียลไทม์ที่เข้มงวด[ 36 ]วงจรการอ้างอิงอาจทำให้เกิดการรั่วไหลของหน่วยความจำ: สามารถจัดการสิ่งเหล่านี้ได้โดยการระบุคำอธิบายประกอบ{.acyclic.}pragma ด้วยตนเองหรือโดยการใช้--mm:orc.--mm:orc– เหมือนกัน--mm:arcแต่เพิ่มตัวรวบรวมวงจร ("O") โดยอิงจาก "การลบทดลอง" [ 37 ]ตัวรวบรวมวงจรจะวิเคราะห์เฉพาะประเภทที่อาจเป็นวงจรเท่านั้น--mm:refc– ตัวเก็บขยะมาตรฐานที่ใช้การนับการอ้างอิง แบบเลื่อนออกไป พร้อมด้วยตัวเก็บขยะสำรองแบบทำเครื่องหมายและกวาดอย่างง่ายเพื่อเก็บรอบการทำงาน ฮีปเป็นแบบเฉพาะเธรด--mm:markAndSweep– ระบบจัดการหน่วยความจำ แบบง่ายๆ ที่ใช้หลักการทำเครื่องหมายและกวาด (mark-and-sweep ) ฮีปจะทำงานเฉพาะในแต่ละเธรด--mm:boehm– ระบบเก็บขยะของBoehmให้บริการกองขยะแบบใช้ร่วมกัน--mm:go– ตัวจัดการขยะของภาษาGoซึ่งมีประโยชน์สำหรับการทำงานร่วมกันกับภาษา Goมีฮีปที่ใช้ร่วมกัน--mm:none– ไม่มีกลยุทธ์การจัดการหน่วยความจำหรือตัวเก็บขยะ (garbage collector ) หน่วยความจำที่จัดสรรไว้จะไม่ถูกปล่อยให้ว่างเลย เว้นแต่จะถูกปล่อยให้ว่างด้วยตนเองโดยโค้ดของนักพัฒนา
ตั้งแต่ Nim 2.0 เป็นต้นไป ORC จะเป็น GC เริ่มต้น[ 26 ]
เครื่องมือพัฒนา
มัดรวม
แพ็กเกจการติดตั้ง Nim มาพร้อมกับเครื่องมือมากมาย ได้แก่:
ว่องไว
Nimble เป็นตัวจัดการแพ็กเกจ มาตรฐาน ที่ Nim ใช้ในการบรรจุโมดูล Nim [ 38 ]เดิมทีพัฒนาโดย Dominik Picheta ซึ่งเป็นนักพัฒนาหลักของ Nim ด้วย Nimble ได้รับการรวมเข้าเป็นตัวจัดการแพ็กเกจอย่างเป็นทางการของ Nim ตั้งแต่วันที่ 27 ตุลาคม 2015 ซึ่งเป็นเวอร์ชัน v0.12.0 [ 39 ]
แพ็กเกจ Nimble ถูกกำหนดโดย.nimbleไฟล์ ซึ่งมีข้อมูลเกี่ยวกับเวอร์ชันแพ็กเกจ ผู้เขียน ใบอนุญาต คำอธิบาย การพึ่งพา และอื่นๆ[ 21 ] : 132 ไฟล์เหล่านี้รองรับไวยากรณ์ Nim บางส่วนที่เรียกว่า NimScript โดยมีข้อจำกัดหลักคือการเข้าถึง FFI สคริปต์เหล่านี้อนุญาตให้เปลี่ยนแปลงขั้นตอนการทดสอบ หรือเขียนงานที่กำหนดเองได้
รายการแพ็กเกจจะถูกจัดเก็บไว้ในไฟล์ JavaScript Object Notation ( JSON ) ซึ่งสามารถเข้าถึงได้โดยอิสระในที่เก็บ nim-lang/packages บน GitHub ไฟล์ JSON นี้จะช่วยให้ Nimble สามารถจับคู่ชื่อแพ็กเกจกับ URL ของที่เก็บ Git หรือ Mercurial ได้
Nimble มาพร้อมกับคอมไพเลอร์ Nim ดังนั้นจึงสามารถทดสอบสภาพแวดล้อมของ Nimble ได้โดยการรันnimble -vคำสั่งนี้ คำสั่งนี้จะแสดงหมายเลขเวอร์ชัน วันที่และเวลาในการคอมไพล์ และ แฮช Gitของ nimble Nimble ใช้แพ็กเกจ Git ซึ่งต้องมีอยู่เพื่อให้ Nimble ทำงานได้อย่างถูกต้อง บรรทัดคำสั่งของ Nimble ใช้เป็นอินเทอร์เฟซสำหรับการติดตั้ง การลบ (ถอนการติดตั้ง) และการอัปเกรด-แก้ไขแพ็กเกจโมดูล[ 21 ] : 130–131
ซี2นิม
c2nim เป็นคอมไพเลอร์แบบซอร์สโค้ดต่อซอร์สโค้ด (ทรานส์คอมไพเลอร์หรือทรานสไพเลอร์) ที่ออกแบบมาเพื่อใช้กับ เฮดเดอร์ C / C++เพื่อช่วยสร้างการผูก Nim ใหม่[ 40 ]ผลลัพธ์คือโค้ด Nim ที่มนุษย์อ่านได้ ซึ่งออกแบบมาเพื่อแก้ไขด้วยตนเองหลังจากกระบวนการแปลเสร็จสิ้น
โคช
koch เป็นสคริปต์การบำรุงรักษาที่ใช้ในการสร้าง Nim และจัดเตรียมเอกสาร HTML [ 41 ]
นิมเกรป
nimgrep เป็นเครื่องมือทั่วไปสำหรับการจัดการข้อความ ใช้ในการค้นหา regex, รูปแบบ peg และเนื้อหาของไดเร็กทอรี และสามารถใช้แทนที่งานต่างๆ ได้ รวมอยู่ด้วยเพื่อช่วยในการค้นหาตัวระบุที่ไม่คำนึงถึงสไตล์ของ Nim [ 42 ]
นิมซักเกสต์
nimsuggest เป็นเครื่องมือที่ช่วยให้โปรแกรมแก้ไขซอร์สโค้ดใดๆ สามารถสอบถาม.nimไฟล์ซอร์สเพื่อรับข้อมูลที่เป็นประโยชน์ เช่น คำจำกัดความของสัญลักษณ์หรือคำแนะนำสำหรับการเติมคำ[ 43 ]
นิมินสต์
niminst เป็นเครื่องมือสำหรับสร้างตัวติดตั้งโปรแกรม Nim [ 44 ] โดยจะสร้างตัวติดตั้ง .msi สำหรับ Windows ผ่าน Inno Setup และสคริปต์การติดตั้งและถอนการติดตั้งสำหรับLinux , macOSและBerkeley Software Distribution (BSD)
นิมเพรตตี้
nimpretty เป็นโปรแกรมจัดรูปแบบโค้ดต้นฉบับให้สวยงาม ใช้สำหรับจัดรูปแบบโค้ดตามคู่มือสไตล์ Nim อย่างเป็นทางการ[ 45 ]
พินัยกรรม
Testamentเป็นเครื่องมือรันการทดสอบหน่วยอัตโนมัติขั้นสูงสำหรับทดสอบด้วยภาษา Nim ใช้ในการพัฒนาโปรแกรมด้วยภาษา Nim โดยมีคุณสมบัติในการทดสอบแบบแยกกระบวนการ สร้างสถิติเกี่ยวกับกรณีทดสอบ รองรับเป้าหมายหลายรายการและการจำลอง Dry-Run มีระบบบันทึกข้อมูล สามารถสร้างรายงาน HTML สามารถข้ามการทดสอบจากไฟล์ และอื่นๆ อีกมากมาย
เครื่องมืออื่นๆ ที่น่าสนใจ
เครื่องมือสำคัญบางอย่างที่ไม่ได้รวมอยู่ในชุดการแจกจ่าย Nim ได้แก่:
เลือกฉัน
choosenimได้รับการพัฒนาโดย Dominik Picheta ผู้สร้างตัวจัดการแพ็กเกจ Nimble เป็นเครื่องมือที่ช่วยให้สามารถติดตั้งและใช้งานคอมไพเลอร์ Nim หลายเวอร์ชันได้ โดยจะดาวน์โหลดคอมไพเลอร์ Nim เวอร์ชันเสถียรหรือเวอร์ชันพัฒนาใดๆ จากบรรทัดคำสั่ง ทำให้สามารถสลับไปมาระหว่างเวอร์ชันต่างๆ ได้อย่างง่ายดาย[ 46 ]
นิมปี้
nimpyเป็นไลบรารีที่ช่วยให้สามารถผสานรวม Python เข้ากับโปรแกรม Nim ได้อย่างสะดวก[ 47 ]
พิกซี่
Pixieเป็นไลบรารีกราฟิก 2 มิติที่มีฟีเจอร์มากมาย คล้ายกับCairoหรือSkiaมันใช้ การเร่งความเร็ว SIMDเพื่อเพิ่มความเร็วในการจัดการภาพอย่างมาก รองรับรูปแบบภาพหลายรูปแบบ การผสมผสาน การมาสก์ การเบลอ และสามารถใช้ร่วมกับ ไลบรารี Boxyเพื่อทำการเรนเดอร์แบบเร่งความเร็วด้วยฮาร์ดแวร์ได้
นิมเทอรอป
nimteropเป็นเครื่องมือที่มุ่งเน้นการสร้างตัวห่อ C/C++ โดยอัตโนมัติซึ่งจำเป็นสำหรับอินเทอร์เฟซฟังก์ชันภายนอกของ Nim [ 48 ]
ห้องสมุด
ห้องสมุดบริสุทธิ์/ไม่บริสุทธิ์
ไลบรารีบริสุทธิ์ คือโมดูลที่เขียนด้วยภาษา Nim เท่านั้น โดยไม่มีส่วนเชื่อมต่อเพื่อเข้าถึงไลบรารีที่เขียนด้วยภาษาโปรแกรมอื่นๆ
ไลบรารีที่ไม่บริสุทธิ์ คือโมดูลของโค้ด Nim ที่ขึ้นอยู่กับไลบรารีภายนอกซึ่งเขียนด้วยภาษาโปรแกรมอื่น เช่น ภาษา C
ไลบรารีมาตรฐาน
ไลบรารีมาตรฐานของ Nim ประกอบด้วยโมดูลสำหรับงานพื้นฐานทั้งหมด รวมถึง: [ 49 ]
- ระบบและโมดูลหลัก
- คอลเลกชันและอัลกอริธึม
- การจัดการสตริง
- การจัดการเวลา
- บริการระบบปฏิบัติการทั่วไป
- ห้องสมุดคณิตศาสตร์
- โปรโตคอลอินเทอร์เน็ตและการสนับสนุน
- การร้อยด้าย
- ตัวแยกวิเคราะห์
- โดคูทิลส์
- การประมวลผล XML
- เครื่องมือสร้างโค้ด XML และ HTML
- การแฮช
- รองรับฐานข้อมูล (PostgreSQL, MySQL และ SQLite)
- ตัวห่อหุ้ม (Win32 API, POSIX)
การใช้ไลบรารีอื่นๆ
โปรแกรม Nim สามารถใช้ไลบรารีใดก็ได้ที่สามารถใช้ในโปรแกรม C , C++ หรือ JavaScript ได้ มี การเชื่อมต่อภาษาสำหรับไลบรารีจำนวนมาก รวมถึงGTK [ 50 ] [ 51 ] Qt QML [ 52 ] wxWidgets [ 53 ] SDL 2 [ 54 ] [ 55 ] Raylib [ 56 ] Godot [ 57 ] UE5 [ 58 ] Cairo [ 59 ] OpenGL [ 60 ] Vulkan [ 61 ] Windows API ( WinAPI ) [ 62 ] zlib libzip OpenSSL และcURL [ 63 ] Nim ทำงานร่วมกับฐานข้อมูลPostgreSQL MySQLและSQLite
มีเครื่องมือโอเพนซอร์สอยู่หลายระดับการสนับสนุน ซึ่งสามารถใช้เชื่อมต่อ Nim กับภาษาLua [ 64 ] Julia [ 65 ] Rust [ 66 ] C # [ 67 ]และPython [ 68 ]หรือแปลงNim เป็นTypeScript [ 69 ]
ตัวอย่าง
สวัสดีโลก
โปรแกรม"Hello, World!"ในภาษานิม:
echo ( "Hello, World!" ) # สามารถเรียกใช้โปรซีเดอร์ได้โดยไม่ต้องมีวงเล็บecho "Hello, World!"อีกรูปแบบหนึ่งของการแสดงข้อความ "Hello World" สามารถทำได้โดยการเรียกใช้writeฟังก์ชันด้วยstdoutสตรีม:
stdout.write ( "Hello, World! \n " ) write ( stdout , " Hello, World! \ n " )ฟิโบนาชชี
ตัวอย่างการใช้งานฟังก์ชันฟิโบนาชี่ หลายรูปแบบ โดยแสดงให้เห็นถึงการส่งคืนค่าโดยปริยาย พารามิเตอร์เริ่มต้น ตัววนซ้ำ การเรียกซ้ำ และลูป while:
proc fib ( n : Natural ): Natural = if n < 2 : return n else : return fib ( n - 1 ) + fib ( n - 2 ) func fib2 ( n : int , a = 0 , b = 1 ): int = if n == 0 : a else : fib2 ( n - 1 , b , a + b ) iterator fib3 : int = var a = 0 var b = 1 while true : yield a swap a , b b += aแฟกทอเรียล
โปรแกรมคำนวณแฟกทอเรียลของจำนวนเต็มบวกโดยใช้วิธีการวนซ้ำ โดยแสดงการจัดการข้อผิดพลาดด้วย try/catch และลูป for:
import std / strutilsvar n = 0 try : stdout . write "ป้อนจำนวนเต็มบวก: " n = stdin . readline . parseInt except ValueError : raise newException ( ValueError , "คุณต้องป้อนจำนวนบวก" )var fact = 1 for i in 2 .. n : fact = fact * iเอคโค แฟคต์โดยใช้โมดูล math จากไลบรารีมาตรฐานของ Nim:
import std / math echo fac ( x )การกลับสตริง
ตัวอย่างง่ายๆ ที่แสดงให้เห็นถึงตัวแปรผลลัพธ์โดยปริยายและการใช้ตัววนซ้ำ
proc reverse ( s : string ): string = for i in countdown ( s . high , 0 ): result . add s [ i ]let str1 = "กลับด้านข้อความนี้!" echo "ผลลัพธ์ที่กลับด้าน: " , reverse ( str1 )หนึ่งในคุณสมบัติที่แปลกใหม่ของ Nim คือตัวแปรโดยresultปริยาย ทุกขั้นตอนใน Nim ที่มีประเภทการคืนค่าที่ไม่ใช่ void จะมีตัวแปรผลลัพธ์โดยปริยายซึ่งแสดงถึงค่าที่จะส่งคืน ในลูป for เราจะเห็นการเรียกใช้ซึ่งcountdownเป็นตัววนซ้ำ หากละเว้นตัววนซ้ำ คอมไพเลอร์จะพยายามใช้itemsตัววนซ้ำหากมีการกำหนดไว้สำหรับประเภทที่ระบุ
ส่วนติดต่อผู้ใช้แบบกราฟิก
การใช้งานGTK 3ร่วมกับการตรวจสอบโครงสร้างของ GObject ผ่าน โมดูล gintro :
import gintro /[ gtk , glib , gobject , gio ]proc appActivate ( app : Application ) = let window = newApplicationWindow ( app ) window . title = "แอปพลิเคชัน GTK3 พร้อมการตรวจสอบ gobject" window . defaultSize = ( 400 , 400 ) showAll ( window )proc main = let app = newApplication ( "org.gtk.example" ) connect ( app , "activate" , appActivate ) discard run ( app )หลัก()โค้ดนี้ต้องการโมดูล gintro ในการทำงาน ซึ่งไม่ได้เป็นส่วนหนึ่งของไลบรารีมาตรฐาน ในการติดตั้งโมดูล gintro และโมดูลอื่นๆ อีกมากมาย คุณสามารถใช้เครื่องมือ nimble ซึ่งเป็นส่วนหนึ่งของ Nim ได้ ในการติดตั้งโมดูล gintro ด้วย nimble ให้ทำดังนี้:
ติดตั้ง gintro อย่างคล่องแคล่ว
รูปแบบการเขียนโปรแกรม
การเขียนโปรแกรมเชิงฟังก์ชัน
การเขียนโปรแกรมเชิงฟังก์ชันได้รับการสนับสนุนใน Nim ผ่านฟังก์ชันระดับเฟิร์สคลาสและโค้ดที่ไม่มีผลข้างเคียงผ่านnoSideEffectpragma หรือfuncคีย์เวิร์ด[ 70 ] Nim จะทำการ วิเคราะห์ ผลข้างเคียงและแจ้งข้อผิดพลาดในการคอมไพล์สำหรับโค้ดที่ไม่ปฏิบัติตามข้อตกลงในการไม่ก่อให้เกิดผลข้างเคียงเมื่อคอมไพล์ด้วยคุณสมบัติทดลองstrictFuncsซึ่งวางแผนไว้ว่าจะกลายเป็นค่าเริ่มต้นในเวอร์ชันต่อๆ ไป[ 71 ]
แตกต่างจาก ภาษา การเขียนโปรแกรมเชิงฟังก์ชัน โดยสมบูรณ์ Nim เป็น ภาษาการเขียนโปรแกรม แบบหลายกระบวนทัศน์ดังนั้น ข้อจำกัด ของการเขียนโปรแกรมเชิงฟังก์ชันจึงเป็นการเลือกใช้งานตามแต่ละฟังก์ชัน
ฟังก์ชันชั้นหนึ่ง
Nim รองรับฟังก์ชันระดับเฟิร์สคลาสโดยอนุญาตให้จัดเก็บฟังก์ชันไว้ในตัวแปรหรือส่งผ่านแบบไม่ระบุชื่อเป็นพารามิเตอร์เพื่อเรียกใช้โดยฟังก์ชันอื่น[ 72 ] โมดูล นี้std/sugarให้ไวยากรณ์ที่ง่ายขึ้นสำหรับฟังก์ชันที่ไม่ระบุชื่อในการประกาศประเภทและการสร้างอินสแตนซ์
import std /[ sequtils , sugar ]let powersOfTwo = @[ 1 , 2 , 4 , 8 , 16 , 32 , 64 , 128 , 256 ]proc filter [ T ] ( s : openArray [ T ] , pred : T -> bool ): seq [ T ] = result = newSeq [ T ] () for i in 0 .. < s . len : if pred ( s [ i ] ): result . add ( s [ i ] )echo powersOfTwo.filter ( proc ( x : int ): bool = x > 32 ) # รูปแบบการเขียนโค้ดที่ช่วยให้ เขียนได้ ง่ายขึ้น โดยมีให้ใน รูปแบบมาโครจาก std/sugar echo powersOfTwo.filter ( x = > x > 32 )proc greaterThan32 ( x : int ): bool = x > 32 echo powersOfTwo . filter ( greaterThan32 )ผลข้างเคียง
ผลข้างเคียงของฟังก์ชันที่ระบุด้วยnoSideEffectpragma จะถูกตรวจสอบ และคอมไพเลอร์จะปฏิเสธการคอมไพล์ฟังก์ชันที่ไม่ตรงตามเงื่อนไขเหล่านั้น ผลข้างเคียงใน Nim ได้แก่ การเปลี่ยนแปลงค่า การเข้าถึงหรือแก้ไขสถานะทั่วโลก โค้ดแบบอะซิงโครนัส โค้ดแบบมัลติเธรด และ IO การเปลี่ยนแปลงค่าพารามิเตอร์อาจเกิดขึ้นกับฟังก์ชันที่รับพารามิเตอร์ ประเภท varหรือrefซึ่งคาดว่าจะไม่สามารถคอมไพล์ได้strictFuncsในอนาคตด้วยฟังก์ชันทดลองในปัจจุบัน[ 73 ] คำหลัก นี้funcแนะนำทางลัดสำหรับnoSideEffectpragma [ 74 ]
funcbinarySearch[T](a:openArray[T];elem:T):int# ย่อมาจาก...procbinarySearch[T](a:openArray[T];elem:T):int{.noSideEffect.} {.experimental: "strictFuncs".}typeNode=refobjectle,ri:Nodedata:stringfunclen(n:Node):int=# ถูกต้อง: len ไม่มีผลข้างเคียงvarit=nwhileit!=nil:incresultit=it.rifuncmut(n:Node)=letm=n# is the statement that connected the mutation to the parameterm.data="yeah"# the mutation is here# Error: 'mut' can have side effects# an object reachable from 'n' is potentially mutated
การประกอบฟังก์ชัน
ไวยากรณ์การเรียกฟังก์ชันแบบเดียวกันช่วยให้สามารถเชื่อมโยงฟังก์ชันต่างๆ เข้าด้วยกันได้ซึ่งอาจแสดงให้เห็นได้ดีที่สุดด้วยstd/sequtilsไลบรารี[ 75 ]
import std /[ sequtils , sugar ]let numbers = @[ 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 7 , 6 , 5 , 4 , 3 , 2 , 1 ] # a และ b เป็นตัวระบุพิเศษในมาโคร foldr echo numbers . filter ( x => x > 3 ). deduplicate . foldr ( a + b ) # 30ประเภทข้อมูลเชิงพีชคณิตและการจับคู่รูปแบบ
Nim รองรับประเภทผลิตภัณฑ์ผ่านทางobjectประเภท และรองรับประเภทผลรวมผ่านทางตัวแปรออบเจ็กต์ : การแสดงผลดิบของยูเนียนที่มีแท็กโดยมีแท็กประเภทที่แจงนับซึ่งต้องจับคู่ได้อย่างปลอดภัยก่อนจึงจะสามารถเข้าถึงฟิลด์ของตัวแปรได้[ 76 ]ประเภทเหล่านี้สามารถประกอบกันได้ทางพีชคณิตการจับคู่รูปแบบโครงสร้างมีให้ใช้งาน แต่ถูกจำกัดไว้ในมาโครในไลบรารีของบุคคลที่สามต่างๆ[ 77 ]
นำเข้าตารางมาตรฐานtype Value = uint64 Ident = string ExprKind = enum Literal , Variable , Abstraction , Application Expr = ref object case kind : ExprKind of Literal : litIdent : Value of Variable : varIdent : Ident of Abstraction : paramAbs : Ident funcAbs : Expr of Application : funcApp , argApp : Exprfunc eval ( expr : Expr , context : var Table [ Ident , Value ] ): Value = case expr . kind of Literal : return expr . litIdent of Variable : return context [ expr . varIdent ] of Application : case expr . funcApp . kind of Abstraction : context [ expr . funcApp . paramAbs ] = expr . argApp . eval ( context ) return expr . funcAbs . eval ( context ) else : raise newException ( ValueError , "Invalid expression!" ) else : raise newException ( ValueError , "Invalid expression!" )การเขียนโปรแกรมเชิงวัตถุ
แม้ว่า Nim จะเป็นภาษาเชิงคำสั่งและเชิงฟังก์ชันเป็นหลัก แต่ก็รองรับคุณสมบัติต่างๆ ที่ช่วยให้สามารถใช้แนวคิดเชิงวัตถุได้[ 78 ] [ 79 ]
การกำหนดชนิดย่อยและการสืบทอด
Nim รองรับการสืบทอดแบบจำกัดโดยใช้ref objectsคีย์เวิร์ด[of 79 ]เพื่อเปิดใช้งานการสืบทอด วัตถุเริ่มต้น ("root") ใดๆ จะต้องสืบทอดมาจาก การ สืบทอดมีประโยชน์จำกัดภายในโค้ด Nim ที่เป็นสำนวน: ยกเว้นข้อยกเว้นที่สำคัญ[ 80 ]RootObj
ประเภทAnimal = วัตถุอ้างอิงของRootObj ชื่อ: สตริงอายุ: จำนวนเต็มประเภทDog = วัตถุอ้างอิงของAnimal ประเภทCat = วัตถุอ้างอิงของAnimalvar animals : seq [ Animal ] = @[] animals . add ( Dog ( name : "Sparky" , age : 10 )) animals . add ( Cat ( name : "Mitten" , age : 10 ))สำหรับสัตว์: ยืนยันa ของสัตว์ความสัมพันธ์ของประเภทย่อยยังสามารถสอบถามได้ด้วยofคำหลัก[ 79 ]
การเรียกเมธอดและการห่อหุ้มข้อมูล
ไวยากรณ์การเรียกฟังก์ชันที่เป็นมาตรฐานของ Nim ช่วยให้สามารถเรียกฟังก์ชันทั่วไปได้ด้วยไวยากรณ์ที่คล้ายกับการเรียกเมธอดในภาษาโปรแกรมอื่นๆ ซึ่งใช้งานได้กับ "getter" และ Nim ยังมีไวยากรณ์สำหรับการสร้าง "setter" ด้วยเช่นกัน วัตถุสามารถเปิดเผยต่อสาธารณะได้ในแต่ละฟิลด์ ซึ่งช่วยให้เกิดการห่อหุ้มข้อมูล (encapsulation)
type Socket * = ref object host : int # ส่วนตัว ไม่มีเครื่องหมายส่งออก# ฟังก์ชันสำหรับดึงที่อยู่โฮสต์proc host * ( s : Socket ): int = s . host# ตัวกำหนดค่าที่อยู่โฮสต์proc `host=` * ( s : var Socket , value : int ) = s . host = valuevar s : Socket new s assert s . host == 0 # เหมือนกับ host(s), s.host() s . host = 34 # เหมือนกับ `host=`(s, 34)การจัดส่งแบบไดนามิก
การเรียกใช้แบบคงที่เป็นที่นิยมมากกว่า มีประสิทธิภาพมากกว่า และเป็นมาตรฐานแม้กระทั่งในรูทีนที่ดูเหมือนเมธอด[ 79 ]อย่างไรก็ตาม หากต้องการเรียกใช้แบบไดนามิก Nim ก็มีmethodคีย์เวิร์ดสำหรับเปิดใช้งานการเรียกใช้แบบไดนามิกบนประเภทอ้างอิง
import std / strformatประเภทPerson = วัตถุอ้างอิงของRootObj ชื่อ: สตริงStudent = วัตถุอ้างอิงของPerson Teacher = วัตถุอ้างอิงของPersonmethod introduce ( a : Person ) = raise newException ( CatchableError , "Method without implementation override" )method introduce ( a : Student ) = echo & "ฉันเป็นนักเรียนชื่อ {a.name}!"method introduce ( a : Teacher ) = echo & "ฉันเป็นครูชื่อ {a.name}!" let people : seq [ Person ] = @[ Teacher ( name : "Alice" ), Student ( name : "Bob" ) ] for person in people : person . introduce ()เมตาโปรแกรมมิ่ง
แม่แบบ
Nim รองรับการแทนที่แบบง่ายบนโครงสร้างต้นไม้ไวยากรณ์นามธรรมผ่านทางเทมเพลตของมัน
template genType ( name , fieldname : untyped , fieldtype : typedesc ) = type name = object fieldname : fieldtypegenType ( Test , foo , int )var x = Test ( foo : 4566 ) echo ( x . foo ) # 4566ฟังก์ชันนี้genTypeจะถูกเรียกใช้ในขั้นตอนการคอมไพล์ และTestจะมีการสร้างประเภทข้อมูลขึ้นมา
ยาสามัญ
ภาษาโปรแกรม Nim รองรับการเขียนโปรแกรมแบบเจเนริกทั้งแบบมีข้อจำกัดและไม่มีข้อจำกัด เจเนริกสามารถใช้ในขั้นตอนการทำงาน เทมเพลต และมาโครได้ ตัวTระบุเจเนริกแบบไม่มีข้อจำกัด (ในตัวอย่างนี้) จะถูกกำหนดไว้หลังชื่อของรูทีนในวงเล็บเหลี่ยม ส่วนเจเนริกแบบมีข้อจำกัดสามารถวางไว้บนตัวระบุเจเนริก หรือบนพารามิเตอร์โดยตรงก็ได้
proc addThese [ T ] ( a , b : T ): T = a + b echo addThese ( 1 , 2 ) # 3 (ชนิด int) echo addThese ( uint8 1 , uint8 2 ) # 3 (ชนิด uint8)# เราไม่ต้องการเสี่ยงกับการลบจำนวนที่ไม่มีเครื่องหมาย! proc subtractThese [ T : SomeSignedInt | float ] ( a , b : T ): T = a - b echo subtractThese ( 1 , 2 ) # -1 (ของชนิด int)import std / sequtils# เจเนริกแบบจำกัดยังสามารถกำหนดโดยตรงให้กับพารามิเตอร์ได้ด้วยproc compareThese [ T ] ( a , b : string | seq [ T ] ): bool = for ( i , j ) in zip ( a , b ): if i != j : return falseเราสามารถชี้แจงเพิ่มเติมเกี่ยวกับประเภทที่ขั้นตอนจะยอมรับได้โดยการระบุคลาสประเภท (ในตัวอย่างข้างต้นSomeSignedInt) [ 81 ]
มาโคร
มาโครสามารถเขียนโค้ดบางส่วนใหม่ได้ในระหว่างการคอมไพล์ มาโครของ Nim มีประสิทธิภาพและสามารถดำเนินการกับโครงสร้างต้นไม้ไวยากรณ์นามธรรมก่อนหรือหลังการตรวจสอบความหมายได้[ 82 ]
นี่คือตัวอย่างง่ายๆ ที่สร้างมาโครเพื่อเรียกใช้โค้ดสองครั้ง:
นำเข้าstd / macrosมาโครสองครั้ง( อาร์กิวเมนต์: ไม่ระบุประเภท): ไม่ระบุประเภท= ผลลัพธ์= คำพูดทำ: ` อาร์กิวเมนต์` ` อาร์กิวเมนต์`ส่งเสียง"Hello world!" สองครั้ง มาโครtwiceในตัวอย่างนี้รับคำสั่ง echo ในรูปแบบของโครงสร้างต้นไม้ไวยากรณ์นามธรรม (abstract syntax tree) เป็นอินพุต ในตัวอย่างนี้ เราตัดสินใจที่จะส่งคืนโครงสร้างต้นไม้ไวยากรณ์นี้โดยไม่มีการดัดแปลงใดๆ แต่เราทำเช่นนั้นสองครั้ง จึงเป็นที่มาของชื่อมาโคร ผลลัพธ์คือ โค้ดจะถูกเขียนใหม่โดยมาโครให้มีลักษณะดังโค้ดต่อไปนี้ในระหว่างการคอมไพล์:
echo "Hello world!" echo "Hello world!"อินเทอร์เฟซฟังก์ชันภายนอก (FFI)
FFI ของ Nim ใช้สำหรับเรียกฟังก์ชันที่เขียนด้วยภาษาโปรแกรมอื่น ๆ ที่สามารถคอมไพล์ได้ ซึ่งหมายความว่าไลบรารีที่เขียนด้วยภาษา C, C++, Objective-C และ JavaScript สามารถนำมาใช้ในซอร์สโค้ดของ Nim ได้ ควรทราบว่า JavaScript และไลบรารี C, C++ หรือ Objective-C ไม่สามารถรวมกันในโปรแกรมเดียวกันได้ เนื่องจากไม่เข้ากันกับ JavaScript เท่ากับที่เข้ากันได้ดีกับภาษาอื่น ๆ ทั้ง C++ และ Objective-C นั้นมีพื้นฐานมาจากและเข้ากันได้กับ C แต่ JavaScript นั้นไม่เข้ากัน เนื่องจากเป็นภาษาแบบไดนามิกฝั่งไคลเอ็นต์ที่ใช้บนเว็บ[ 21 ] : 226
โปรแกรมต่อไปนี้แสดงให้เห็นถึงความง่ายดายในการใช้โค้ด C ภายนอกโดยตรงใน Nim
proc printf ( formatstr : cstring ) {.header : "<stdio.h>", varargs.}printf ( "%s %d \n " , "foo" , 5 )ในโค้ดนี้printfฟังก์ชันจะถูกนำเข้าในภาษานิม แล้วจึงนำไปใช้งาน
ตัวอย่างพื้นฐานการใช้ 'console.log' โดยตรงสำหรับ เป้าหมายการคอมไพล์ JavaScript :
proc log ( args : any ) {.importjs : "console.log(@)", varargs.} log ( 42 , "z" , true , 3.14 )โค้ด JavaScript ที่สร้างโดยคอมไพเลอร์ Nim สามารถเรียกใช้งานได้ด้วยNode.jsหรือเว็บเบราว์เซอร์
ความขนาน
ในการเปิดใช้งานการทำงานแบบมัลติเธรดใน Nim โปรแกรมจะต้องถูกคอมไพล์โดยใช้--threads:onพารามิเตอร์บรรทัดคำสั่ง แต่ละเธรดจะมีฮีปที่จัดการโดยระบบจัดการขยะแยกต่างหาก และการแชร์หน่วยความจำจะถูกจำกัด ซึ่งช่วยเพิ่มประสิทธิภาพและป้องกันสภาวะการแข่งขันของเธรด
นำเข้าstd / locksvar thr : array [ 0 .. 4 , Thread [ tuple [ a , b : int ]]] L : Lockproc threadFunc ( interval : tuple [ a , b : int ] ) {.thread.} = for i in interval . a .. interval . b : acquire ( L ) # ล็อก stdout echo i release ( L )initLock ( L )สำหรับi ตั้งแต่0 ถึงสูง( thr ): สร้างเธรด( thr [ i ] , threadFunc , ( i * 10 , i * 10 + 5 )) เข้าร่วมเธรด( thr )นอกจากนี้ Nim ยังมีchannelsโมดูลที่ช่วยให้การส่งข้อมูลระหว่างเธรดทำได้ง่ายขึ้น
import std / osประเภทCalculationTask = object id * : int data * : intCalculationResult = object id * : int result * : intvar task_queue : Channel [ CalculationTask ] var result_queue : Channel [ CalculationResult ]proc workerFunc () {.thread.} = result_queue . open ()ในขณะที่เงื่อนไขเป็นจริง: var task = task_queue.recv ( ) result_queue.send ( CalculationResult ( id : task.id , result : task.data * 2 ) )var workerThread : Thread [ void ] createThread ( workerThread , workerFunc )task_queue.open ( ) task_queue.send ( CalculationTask ( id : 1 , data : 13 ) ) task_queue.send ( CalculationTask ( id : 2 , data : 37 ) )ในขณะที่เงื่อนไขเป็นจริงให้แสดงข้อความ"ได้รับผลลัพธ์: " , repr ( result_queue . recv ())ความพร้อมกัน
การรับส่งข้อมูลแบบอะซิงโครนัสได้รับการสนับสนุนผ่านasyncdispatchโมดูลในไลบรารีมาตรฐานหรือchronosไลบรารี ภายนอก [ 83 ]ไลบรารีทั้งสองเพิ่ม ไวยากรณ์ async/awaitผ่านระบบมาโคร โดยไม่จำเป็นต้องมีการสนับสนุนภาษาพิเศษ ตัวอย่างของ เซิร์ฟเวอร์ HTTP แบบอะซิงโครนัส :
import std /[ asynchttpserver , asyncdispatch ] # สามารถใช้ chronos แทน asyncdispatch ได้เช่นกัน# โดยไม่ต้องเปลี่ยนแปลงอะไรเพิ่มเติมvar server = newAsyncHttpServer ( ) proc cb ( req : Request ) {.async.} = await req.respond ( Http200 , " Hello World" )waitFor server.serve ( Port ( 8080 ) , cb )ชุมชน
ออนไลน์
Nim มีชุมชนที่ใช้งานอยู่บนฟอรัมอย่างเป็นทางการที่โฮสต์และพัฒนาเอง[ 84 ]นอกจากนี้ โครงการยังใช้ Git repository, bug tracker, RFC tracker และ wiki ที่โฮสต์โดยGitHubซึ่งชุมชนมีส่วนร่วมกับภาษา[ 85 ]นอกจากนี้ยังมีห้องแชทออนไลน์อย่างเป็นทางการที่เชื่อมโยงระหว่าง IRC , Matrix , Discord , GitterและTelegram [ 86 ]
อนุสัญญา
การประชุม Nim ครั้งแรก หรือ NimConf จัดขึ้นเมื่อวันที่ 20 มิถุนายน 2020 โดยจัดขึ้นในรูปแบบดิจิทัลเนื่องจากสถานการณ์ COVID-19พร้อมกับการเปิดรับการบรรยายจากผู้ร่วมให้ข้อมูลในรูปแบบวิดีโอYouTube [ 87 ]การประชุมเริ่มต้นด้วยภาพรวมของภาษาโดยนักพัฒนา Nim Andreas Rumpf และ Dominik Picheta หัวข้อการนำเสนอประกอบด้วยการบรรยายเกี่ยวกับเฟรมเวิร์กเว็บการพัฒนาแอปพลิเคชันบนมือถือ อุปกรณ์ Internet of Things ( IoT) และการพัฒนาเกมรวมถึงการบรรยายเกี่ยวกับการเขียน Nim สำหรับGame Boy Advance [ 88 ] NimConf 2020 มีให้รับชมในรูปแบบเพลย์ลิสต์ YouTube [ 89 ] NimConf 2021 จัดขึ้นในปีถัด มาโดยจัดขึ้นในรูปแบบดิจิทัลเช่นกัน และมีการบรรยายเกี่ยวกับการพัฒนาเกม REPLs ระบบปฏิบัติการแบบเรียลไทม์ Nim ในอุตสาหกรรมการแมปอ็อบเจ็กต์เชิงสัมพันธ์ ( ORM ) การทดสอบ แบบฟัซซิ่งการออกแบบภาษาและไลบรารีกราฟิก[ 90 ]
นอกจากงานประชุมอย่างเป็นทางการแล้ว Nim ยังได้รับการนำเสนอในงานประชุมอื่นๆ อีกมากมาย มีการนำเสนอเกี่ยวกับ Nim ในงานO'Reilly Open Source Convention (OSCON) ในปี 2015 [ 91 ] [ 92 ] [ 93 ] มี ผู้บรรยาย 4 คนเป็นตัวแทนของ Nim ในงาน FOSDEM 2020 รวมถึงผู้สร้างภาษา Andreas Rumpf [ 94 ]ในงาน FOSDEM 2022 Nim ได้จัดห้องสำหรับนักพัฒนาของตนเองแบบเสมือนจริงเนื่องจาก การระบาด ของCOVID-19 [ 95 ]มีการบรรยายเกี่ยวกับการทำงานพร้อมกันการเขียนโปรแกรมฝังตัวการเขียนโปรแกรมสำหรับGPUระบบเอนทิตี- คอมโพเนนต์ การพัฒนาเกมกลไกกฎ การทำงานร่วมกับ Python และ เมตาโปรแกรมมิ่ง[ 96 ]
ดูเพิ่มเติม
ลิงก์ภายนอก
- เว็บไซต์อย่างเป็นทางการ

- นิมบนGitHub
- ข้อมูลเกี่ยวกับ NimบนStack Overflow
- การเขียนโปรแกรมคอมพิวเตอร์ด้วยภาษาโปรแกรม Nim – บทนำอย่างง่าย โดย Stefan Salewski
สรุปเนื้อหา
ข้อมูลสำคัญจากบทความ
ข้อมูลสำคัญเกี่ยวกับ นิม (ภาษาโปรแกรม)
Nim เป็น ภาษาโปรแกรมระบบ ระดับสูง แบบ คอมไพล์ได้ อเนกประสงค์ รองรับ หลาย พาราดิกม์ กำหนด ประเภทแบบคงที่ [ 9 ] ได้รับการออกแบบและพัฒนาโดยทีมงานที่นำโดย Andreas Rumpf Nim...
คำอธิบาย
Nim เป็นภาษาที่มีการกำหนดประเภทแบบคงที่ [ 12 ] รองรับ คุณสมบัติ เมตาโปรแกรม มิ่งในเวลาคอมไพล์ เช่น มาโครทางไวยากรณ์และ มาโครการเขียนเทอมใหม่ [ 13 ] มาโคร การเขียนเทอมใหม่ช่วยให้ การใช้งาน ไลบรารี ของโครงสร้างข้อมูลทั่วไป เช่น bignums และเมทริกซ์...
ประวัติศาสตร์
Andreas Rumpf เป็นผู้ออกแบบและผู้พัฒนา Nim คนแรก เขาได้รับประกาศนียบัตรด้านวิทยาการคอมพิวเตอร์จาก มหาวิทยาลัยเทคนิคไคเซอร์สเลาเทิร์น ประเทศ เยอรมนี ความสนใจในการวิจัยของเขารวมถึง ระบบเรียลไทม์แบบแข็ง ระบบ ฝังตัว การ สร้างคอมไพเลอร์ และ ปัญญา ประดิษฐ์ [ 20 ]
ไวยากรณ์
ไวยากรณ์ของ Nim คล้ายกับของPython [ 27 ] บล็อก โค้ดและคำสั่งซ้อนกันจะถูกระบุโดยใช้ ช่องว่าง ตาม กฎออฟไซด์ คำหลัก หลาย คำ เหมือนกับคำที่เทียบเท่าใน Python ซึ่งส่วนใหญ่เป็นคำหลักภาษาอังกฤษ ในขณะที่ภาษาโปรแกรมอื่นๆ มักใช้เครื่องหมายวรรคตอน...