Scheme vs Common Lisp: คุณลักษณะใดที่ทำให้โครงการของคุณแตกต่าง? [ปิด]


155

ไม่มีปัญหาการขาดแคลนคำถาม "Scheme vs Common Lisp" ที่คลุมเครือทั้งใน StackOverflow และบนเว็บไซต์นี้ดังนั้นฉันต้องการทำให้สิ่งนี้มีความสำคัญยิ่งขึ้น คำถามสำหรับคนที่มีรหัสในทั้งสองภาษา:

ในขณะที่การเขียนโค้ดใน Scheme องค์ประกอบเฉพาะของประสบการณ์การเขียนโปรแกรม Lisp แบบใดที่คุณพลาดมากที่สุด หรือในทางกลับกันในขณะที่เข้ารหัสใน Common LISP คุณพลาดอะไรไปจากการเข้ารหัสใน Scheme

ฉันไม่ได้หมายถึงคุณสมบัติทางภาษา ต่อไปนี้เป็นสิ่งที่ถูกต้องทั้งหมดที่ควรพลาดรวมถึงคำถามที่เกี่ยวข้อง:

  • ห้องสมุดเฉพาะ
  • คุณสมบัติเฉพาะของสภาพแวดล้อมการพัฒนาเช่น SLIME, DrRacket เป็นต้น
  • คุณสมบัติของการใช้งานเฉพาะเช่นความสามารถของ Gambit ในการเขียนบล็อกของรหัส C ลงในที่มาของโครงการของคุณโดยตรง
  • และแน่นอนคุณสมบัติด้านภาษา

ตัวอย่างของคำตอบที่ฉันหวังไว้:

  • "ฉันพยายามที่จะใช้ X ใน Common LISP และถ้าฉันมีความต่อเนื่องระดับเฟิร์สคลาสของ Scheme ฉันจะทำแค่ Y ทั้งหมด แต่แทนที่จะทำ Z ซึ่งมันเจ็บปวดมากกว่า"
  • "การเขียนสคริปต์กระบวนการสร้างในโครงการ Scheme ของฉันเจ็บปวดขึ้นเรื่อย ๆ เมื่อต้นกำเนิดของฉันเติบโตขึ้นและฉันเชื่อมโยงในไลบรารี C มากขึ้นเรื่อย ๆ สำหรับโครงการต่อไปของฉันฉันย้ายกลับไปที่ Common Lisp"
  • "ฉันมีรหัสฐาน C ++ ขนาดใหญ่ที่มีอยู่และสำหรับฉันความสามารถในการฝังการโทร C ++ โดยตรงในรหัส Gambit Scheme ของฉันนั้นคุ้มค่ากับข้อบกพร่องใด ๆ ที่ Scheme อาจเทียบกับ Common Lisp แม้จะขาดการสนับสนุน SWIG"

ดังนั้นฉันจึงหวังเรื่องสงครามมากกว่าความรู้สึกทั่วไปเช่น "Scheme เป็นภาษาที่ง่ายกว่า" เป็นต้น


25
เป็นคำถามที่ยอดเยี่ยม ฉันอยากรู้เกี่ยวกับเรื่องนี้เอง; หวังว่าจะมีบางคนที่มีความเชี่ยวชาญในทั้งสองภาษายินดีที่จะให้ข้อมูลเชิงลึกบางอย่าง
Robert Harvey

1
@ Josh K - เป็นคำตอบที่ชัดเจน แต่ไม่จำเป็นต้องมีคำตอบสุดท้าย ยกเว้นว่าฉันเดิมพันจะมีอย่างใดอย่างหนึ่งเพราะบางคนจะออกมาพร้อมกับคำตอบที่ยอดเยี่ยมจนทุกคนเป็นเหมือนโอ้โห!
ลนนาตรอน

4
@ Josh: บางทีคุณอาจไม่คุ้นเคยกับ Scheme และ Common LISP ทั้งสองภาษามีพลังอย่างมากในสิทธิของตนเอง แต่ก็ยังไม่ได้รับการยอมรับอย่างมาก ทำไมนี้ อาจเป็นเพราะมีภาษาถิ่นมากมาย คุณเลือกอันไหน การเปรียบเทียบการเรียงลำดับนี้อาจจะให้ความกระจ่างมากและ OP ได้เขียนคำถามอย่างรอบคอบเพื่อ จำกัด ขอบเขตของคำตอบซึ่งในมุมมองของฉันนั้นมีความเฉพาะเจาะจงและสามารถตอบได้
Robert Harvey

13
คนอย่าปิดคำถามเพียงเพราะคุณไม่ชอบหรือไม่สามารถเกี่ยวข้องกับมัน เห็นได้ชัดว่าเป็นคำถาม "ของจริง"; หากคุณไม่พบเหตุผลที่ดีกว่าในการปิดมันคุณไม่ควรลงคะแนนให้ปิด
Robert Harvey

4
คุณสามารถส่งอีเมลถึง Richard Stallman เพื่อรับคำตอบของเขา
wassimans

คำตอบ:


100

ระดับปริญญาตรีของฉันอยู่ในวิทยาศาสตร์ความรู้ความเข้าใจและปัญญาประดิษฐ์ จากนั้นฉันมีช่วงแนะนำหนึ่งคอร์สกับ LISP ฉันคิดว่าภาษาน่าสนใจ (เหมือนใน "หรูหรา") แต่ไม่ได้คิดอะไรมากมายจนกระทั่งฉันได้พบกับกฎข้อที่สิบของ Greenspun ในภายหลัง:

โปรแกรม C หรือ Fortran ที่ซับซ้อนเพียงพอใด ๆ มี ad hoc ที่ระบุอย่างไม่เป็นทางการระบุข้อผิดพลาดและการใช้งานช้าของครึ่งหนึ่งของ Common LISP

ประเด็นของ Greenspun คือ (บางส่วน) ที่โปรแกรมที่ซับซ้อนจำนวนมากมีล่ามในตัว แทนที่จะสร้างล่ามให้เป็นภาษาเขาแนะนำว่ามันอาจเหมาะสมกว่าที่จะใช้ภาษาอย่าง Lisp ที่มีตัวแปล (หรือคอมไพเลอร์) อยู่แล้ว

ตอนนั้นฉันทำงานกับแอพที่ค่อนข้างใหญ่ซึ่งทำการคำนวณที่ผู้ใช้กำหนดโดยใช้ล่ามที่กำหนดเองสำหรับภาษาที่กำหนดเอง ฉันตัดสินใจลองเขียน core ใน Lisp ใหม่อีกครั้งเพื่อทดลองขนาดใหญ่

ใช้เวลาประมาณหกสัปดาห์ รหัสเดิมคือ ~ 100,000 บรรทัดของ Delphi (ตัวแปร Pascal) ใน Lisp ที่ลดลงเหลือ 10,000 บรรทัด ที่น่าแปลกใจมากขึ้นคือความจริงที่ว่า Lisp engine เร็วกว่า 3-6 เท่า และโปรดจำไว้ว่านี่เป็นผลงานของ Neophyte Lisp! ประสบการณ์ทั้งหมดนั้นค่อนข้างเปิดตาสำหรับฉัน เป็นครั้งแรกที่ฉันเห็นความเป็นไปได้ของการรวมการแสดงและการแสดงออกในภาษาเดียว

ต่อมาเมื่อฉันเริ่มทำงานในโครงการที่ทำเว็บฉันได้คัดเลือกภาษาหลายภาษา ฉันรวม Lisp และ Scheme ไว้ด้วยกัน ในที่สุดผมเลือกโครงการ implementation-- Chez โครงการ ฉันมีความสุขมากกับผลลัพธ์

โครงการ Web-based เป็นที่มีประสิทธิภาพสูง"เครื่องยนต์ตัวเลือก" เราใช้ Scheme ในหลากหลายวิธีตั้งแต่การประมวลผลข้อมูลไปจนถึงการสืบค้นข้อมูลไปจนถึงการสร้างหน้า ในหลาย ๆ จุดเราเริ่มต้นด้วยภาษาที่แตกต่างกัน แต่จบลงด้วยการย้ายไปที่ Scheme ด้วยเหตุผลที่ฉันจะอธิบายสั้น ๆ ด้านล่าง

ตอนนี้ฉันสามารถตอบคำถามของคุณได้ (อย่างน้อยก็ในบางส่วน)

ในระหว่างการออดิชั่นเราได้พิจารณาการใช้งาน Lisp และ Scheme ที่หลากหลาย ในด้านเสียงกระเพื่อมเราดู (ฉันเชื่อว่า) Allegro CL, CMUCL, SBCL และ LispWorks ในด้านโครงการเรามองไปที่ (ฉันเชื่อ) Bigloo, Chicken, Chez, Gambit (การเลือกภาษาเป็นเวลานานมาแล้วนั่นเป็นเหตุผลว่าทำไมฉันถึงค่อนข้างขุ่นมัวฉันสามารถขุดโน้ตได้ถ้ามันสำคัญ)

ทันทีที่เรากำลังมองหา a) เธรดพื้นฐานและ b) การสนับสนุน Linux, Mac และ Windows สองเงื่อนไขนี้รวมกันทำให้ทุกคนล้มเหลว แต่ (ฉันคิดว่า) Allegro และ Chez ออกมาดังนั้นเพื่อที่จะดำเนินการประเมินผลต่อไปเราต้องคลายข้อกำหนดหลายเธรด

เรารวบรวมชุดโปรแกรมขนาดเล็กและใช้พวกมันสำหรับการประเมินและทดสอบ ที่เปิดเผยจำนวนปัญหา ตัวอย่างเช่นการใช้งานบางอย่างมีข้อบกพร่องที่ทำให้การทดสอบบางอย่างไม่สามารถทำงานจนเสร็จ การใช้งานบางอย่างไม่สามารถรวบรวมรหัสในเวลาทำงาน การใช้งานบางอย่างไม่สามารถรวมรหัสที่คอมไพล์แบบรันไทม์เข้ากับโค้ดที่คอมไพล์ล่วงหน้าได้ การใช้งานบางอย่างมีนักสะสมขยะซึ่งดีกว่า (หรือแย่กว่า) อย่างชัดเจนกว่าของผู้อื่น เป็นต้น

สำหรับความต้องการของเรามีเพียงสามการใช้งานเชิงพาณิชย์ - Allegro, Chez และ Lispworks - ผ่านการทดสอบเบื้องต้นของเรา ในสาม Chez เท่านั้นที่ผ่านการทดสอบทั้งหมดด้วยสีที่บินได้ ในขณะที่ฉันคิดว่า Lispworks ไม่มีเธรดดั้งเดิมบนแพลตฟอร์มใด ๆ (ฉันคิดว่าพวกเขาทำในตอนนี้) และฉันคิดว่า Allegro มีเธรดพื้นฐานในบางแพลตฟอร์มเท่านั้น นอกจากนี้อัลเลโกรมีค่าธรรมเนียมการ "เรียกใช้" แบบเรียกใช้งานซึ่งฉันไม่ชอบมาก ฉันเชื่อว่า Lispworks ไม่มีค่าธรรมเนียมรันไทม์และ Chez มีการจัดการที่ตรงไปตรงมา (และสมเหตุสมผลมาก) (และมันจะเตะเท่านั้นถ้าคุณใช้คอมไพเลอร์ในเวลาทำงาน)

มีการผลิตชิ้นส่วนของรหัสที่ค่อนข้างสำคัญทั้ง Lisp และ Scheme ที่นี่มีบางจุดเปรียบเทียบและความคมชัด:

  • สภาพแวดล้อมเสียงกระเพื่อมเป็นผู้ใหญ่มากขึ้น คุณได้รับมากกว่าสำหรับเจ้าชู้ (ต้องบอกว่ารหัสเพิ่มเติมก็เท่ากับข้อบกพร่องมากขึ้น)

  • สภาพแวดล้อม Lisp ยากต่อการเรียนรู้ คุณต้องใช้เวลามากขึ้นในการมีความเชี่ยวชาญ Common Lisp เป็นภาษาที่ยิ่งใหญ่ - และนั่นคือก่อนที่คุณจะไปถึงห้องสมุดที่การติดตั้งเชิงพาณิชย์เพิ่มเข้ามานั้น (ต้องบอกว่ากรณีไวยากรณ์ของ Scheme นั้นลึกซึ้งและซับซ้อนกว่าสิ่งใด ๆ ใน Lisp)

  • สภาพแวดล้อมเสียงกระเพื่อมอาจค่อนข้างยากในการสร้างระบบไบนารีคุณจำเป็นต้อง "เขย่า" รูปภาพของคุณเพื่อลบบิตที่ไม่ต้องการและหากคุณไม่ออกกำลังกายโปรแกรมของคุณอย่างถูกต้องในระหว่างขั้นตอนนั้น . ในทางตรงกันข้ามกับ Chez เรารวบรวมไฟล์ระดับบนสุดที่รวมไฟล์อื่น ๆ ทั้งหมดที่มันต้องการและเราเสร็จแล้ว

ฉันพูดก่อนหน้านี้ว่าเราลงเอยด้วยการใช้ Scheme ในหลาย ๆ ที่ที่เราไม่ได้ตั้งใจ ทำไม? ฉันนึกถึงเหตุผลสามข้อที่อยู่บนหัวของฉัน

อันดับแรกเราเรียนรู้ที่จะไว้วางใจ Chez (และผู้พัฒนาของ Cadence) เราถามมากจากเครื่องมือและมันก็ส่งมอบอย่างสม่ำเสมอ ตัวอย่างเช่น Chez มีข้อบกพร่องเล็กน้อยในอดีตและตัวจัดการหน่วยความจำนั้นดีมาก

ประการที่สองเราเรียนรู้ที่จะรักการแสดงที่เราได้รับจากเชซ เราใช้บางสิ่งที่รู้สึกเหมือนภาษาสคริปต์ - และเราได้รับความเร็วโค้ดเนทีฟจากภาษานั้น สำหรับบางสิ่งที่ไม่สำคัญ - แต่มันไม่เคยเจ็บและบางครั้งมันช่วยได้มาก

สามเราเรียนรู้ที่จะรักสิ่งที่เป็นนามธรรม ฉันไม่ได้หมายถึงมาโคร แต่อย่างใด ฉันหมายถึงสิ่งต่าง ๆ เช่นการปิด, lambdas, tail-call, เป็นต้นเมื่อคุณเริ่มคิดในแง่เหล่านั้นภาษาอื่น ๆ ดูเหมือนจะค่อนข้าง จำกัด โดยการเปรียบเทียบ

โครงการสมบูรณ์แบบหรือไม่ ไม่มี มันเป็นการแลกเปลี่ยน ประการแรกมันช่วยให้นักพัฒนาแต่ละคนมีประสิทธิภาพมากขึ้น - แต่มันยากขึ้นสำหรับนักพัฒนาที่จะงงโค้ดของกันและกันเพราะป้ายบอกทางที่ภาษาส่วนใหญ่มี (เช่นสำหรับลูป) หายไปใน Scheme (เช่นมีวิธีการนับล้านที่ต้องทำ สำหรับห่วง) ประการที่สองมีกลุ่มนักพัฒนาที่เล็กกว่ามากที่จะพูดคุยจ้างจากยืมจาก ฯลฯ

สรุปแล้วฉันคิดว่าฉันพูดว่า: Lisp และ Scheme มีความสามารถบางอย่างที่ไม่สามารถใช้งานได้จากที่อื่น ความสามารถนั้นคือการแลกเปลี่ยนดังนั้นจึงควรมีความสามารถที่เหมาะสมในกรณีของคุณโดยเฉพาะ ในกรณีของเราปัจจัยที่กำหนดว่าจะไปกับ Lisp หรือ Scheme นั้นเกี่ยวข้องกับคุณลักษณะพื้นฐานมากเพียงใด (การสนับสนุนแพลตฟอร์ม, เธรดแพลตฟอร์ม, การรวบรวมเวลาทำงาน, การให้สิทธิ์ใช้งานเวลา) มากกว่าที่ทำกับคุณสมบัติภาษาหรือไลบรารี อีกครั้งในกรณีของเราที่เป็นการแลกเปลี่ยนด้วย Chez เราได้รับคุณสมบัติหลักที่เราต้องการ แต่เราสูญเสียห้องสมุดที่กว้างขวางในสภาพแวดล้อม Lisp เชิงพาณิชย์

นอกจากนี้เพื่อกล่าวย้ำอีกครั้ง: เรามองดู Lisps และ Schemes ต่างๆเมื่อนานมาแล้ว พวกเขาทั้งหมดได้รับการพัฒนาและปรับปรุงตั้งแต่


1
ว้าวนั่นน่าจะเป็นโค้ด Delphi ที่น่ากลัวจริงๆถ้ามันจัดการได้ช้ากว่าการใช้ Lisp ถึง 3-6 เท่า! :(
Mason Wheeler

2
+1: สิ่งที่น่าสนใจที่สุดเกี่ยวกับโพสต์นี้คือความจริงที่ว่าคุณเปลี่ยนจาก Lisp เป็น Scheme หลังจากทำโครงการสำคัญใน Lisp (หรือบางทีฉันเพิ่งถูกซุ่มซ่อนใน comp.lang.lisp ยาวเกินไป.)
ลาร์รีโคลแมน

25
"ว้าวนั่นน่าจะเป็นโค้ด Delphi ที่น่ากลัวจริงๆถ้ามันจัดการได้ช้ากว่าการใช้ Lisp 3-6 เท่า" ใช่ฉันจะนับว่าเป็นความล้มเหลวของฉันที่ไม่อธิบายได้ดีกว่า การนำ Lisp ไปใช้นั้นสามารถแปลงนิพจน์ผู้ใช้เป็นนิพจน์ Lisp ซึ่งเป็นกระบวนการที่ง่ายนิดหน่อยจากนั้นก็รวบรวมนิพจน์ Lisp ให้เป็นรหัสเนทีฟ (ด้วยการเพิ่มประสิทธิภาพเต็มที่) นั่นคือความหมายของกฎข้อที่สิบของ Greenspun
Michael Lenaghan

1
คำตอบที่ยอดเยี่ยม! ฉันจะเลือกอย่างน้อยก็จนกว่าสิ่งที่ดีกว่าจะปรากฏขึ้น :) คำถามหนึ่ง: คุณบอกว่าคุณได้ตัดสินใจที่จะไปกับ Chez Scheme ตามสถานะของสนาม "เมื่อนานมาแล้ว" คุณสามารถระบุปีได้ไหม
SuperElectric

11
จุดนั้นการใช้ LISP นั้นสามารถรวบรวมอะไรบางอย่างลงไปในโค้ดของเครื่องแทนที่จะใช้ล่ามนั้นมีความละเอียดและมีประโยชน์ หนังสือ "Let Over Lambda" ชี้ให้เห็นว่านี่เป็นเหตุผลว่าทำไมแพคเกจ LISP regexp แบบพกพาทั่วไปซึ่งโคลนไวยากรณ์ไวยากรณ์ PERL regexp ดีกว่า PERL โดยปัจจัยที่สำคัญ PERL ด้านข้างมีล่าม regexp แพ็คเกจ LISP ทั่วไปรวบรวม regexps ลงไปที่รหัส
John R. Strohm

37

ฉันมักจะไม่ชอบวางลิงค์เป็นคำตอบ แต่ฉันเขียนบทความในบล็อกในสิ่งนี้ มันไม่ได้ละเอียดถี่ถ้วน แต่จะได้รับประเด็นสำคัญ ๆ

http://symbo1ics.com/blog/?p=729

แก้ไข : นี่คือประเด็นหลัก:

  1. การมีอยู่ : lisps ทั้งสองเกิดขึ้นหลังจาก lisps อื่น ๆ โครงการใช้เส้นทางที่น้อยที่สุดซึ่งเป็นจริง CL ใช้เส้นทางพิสดาร
  2. กรณี : โดยทั่วไปโครงการเป็นกรณี ๆ ไป CL ไม่ใช่ (แม้ว่าจะเป็น) บางครั้งก็พลาดไป แต่ความจริงแล้วมันถกเถียงกันอยู่ (โดยฉัน)
  3. NAMES : ชื่อของสัญลักษณ์ใน CL นั้นแปลกและสับสนหลายครั้ง TERPRI, PROGNฯลฯ โครงการมักจะมีชื่อที่เหมาะสมมาก นี่คือสิ่งที่พลาดใน CL
  4. ฟังก์ชั่น : CL มีเนมสเปซฟังก์ชันแยกต่างหาก สิ่งนี้ไม่ควรพลาดใน Scheme การมีเนมสเปซเดียวมักจะช่วยให้การเขียนโปรแกรมฟังก์ชั่นสะอาดมากซึ่งมักจะยากหรืออึดอัดใจใน CL แต่มีค่าใช้จ่าย --- บางครั้งคุณต้องทำให้งงชื่อเช่น " list" ถึง " lst" ใน Scheme
  5. MACROS : ฉันคิดถึงมาโครสกปรกระดับต่ำที่สุดใน Scheme ใช่syntax-rulesเป็นเรื่องปกติและน่าสนใจจนกว่าคุณจะแฮ็คบางสิ่งออกไป ในทางกลับกันแมโครที่ถูกสุขลักษณะจะพลาดใน CL การไม่มีวิธีมาตรฐานในการทำเช่นนั้นหมายถึงการสร้างวงล้อใหม่
  6. ความน่าเชื่อถือ : บ่อยครั้งที่ CL นั้นพกพาได้มากกว่าแม้ว่าทั้งสองภาษาจะได้มาตรฐาน CL มีขนาดใหญ่กว่าดังนั้นจึงมีคุณสมบัติมาตรฐานเพิ่มเติมให้ใช้โดยไม่ต้องมีไลบรารีภายนอก นอกจากนี้ยังหมายถึงสิ่งที่ขึ้นอยู่กับการใช้งานมากขึ้นสามารถทำได้อย่างสะดวก นอกจากนี้ Scheme ยังทนทุกข์ทรมานจากการใช้งานกว่าล้านล้านส่วนใหญ่ไม่เข้ากัน สิ่งนี้ทำให้ CL เป็นที่ต้องการอย่างมาก
  7. LIBRARIES : เกี่ยวข้องกับประเด็นสุดท้ายของฉันมาก โครงการมี SRFIs แต่ไม่ได้รับการยอมรับในระดับสากล ไม่มีวิธีพกพาในการทำงานกับห้องสมุด CL ในทางกลับกันก็มีวิธี และ Quicklisp เป็นของขวัญจากพระเจ้า (Xach) ซึ่งเป็นที่เก็บไลบรารีสำหรับใช้งาน
  8. การดำเนินการ : โครงการประสบกับการใช้งานจำนวนมาก ไม่มีการนำมาตรฐานไปปฏิบัติจริง ในทางกลับกัน CL มีประสิทธิภาพสูงหรือการใช้งานที่เฉพาะเจาะจง (ประสิทธิภาพสูง: SBCL, เชิงพาณิชย์: Allegro, ฝังตัว: ECL, แบบพกพา: CLISP, Java: ABCL, ... )

ในขณะที่ฉันได้พูดคุยกับคนแรกเพียงเล็กน้อยเท่านั้นมันควรจะชัดเจนว่าฉันคิดถึงอะไรและไม่ทำ

[ฉันขอโทษถ้าสิ่งเหล่านี้กว้างเกินไป ดูเหมือนว่าคุณอาจต้องการรายละเอียดที่เฉพาะเจาะจงมากขึ้น มีบางอย่างในโพสต์]


สรุปทีเซอร์สั้น ๆ (จริง ๆ ) เป็นอย่างไรบ้าง ^^
Dave O.

2
กรุณาอินไลน์ไฮไลท์ คำตอบควรจะยืนตัวเอง

1
@Dave O. และ @ Thorbjørn Ravn Andersen: เพิ่มข้อมูลสรุปตามที่ร้องขอ ขอบคุณ
Quadrescence

2
"เส้นทางบาร็อค"! ช่างเป็นวิธีที่ยอดเยี่ยมมาก
ทำเครื่องหมาย C

Common Lisp เป็นแบบตรงตามตัวพิมพ์ใหญ่ - เล็ก แต่แปลงอินพุตเป็นตัวพิมพ์ใหญ่ก่อนที่จะประเมิน คุณสามารถรับตัวอักษรตัวเล็กในสัญลักษณ์โดยการอ้างอิงพวกเขา ปัญหาชื่อเป็นเพราะโครงการกำจัดชื่อเก่าที่ไม่ดีและ CL ไม่ได้
David Thornley

25

ฉันเพิ่งเริ่มโครงการบ้านโดยใช้ห้องสมุดที่มีรุ่น C และรุ่น Java ฉันต้องการใช้ Lisp สำหรับโครงการและฉันใช้เวลาประมาณหนึ่งเดือนระหว่างการใช้ Common Lisp, Scheme หรือ Clojure ฉันมีประสบการณ์บางอย่างกับทั้งสาม แต่เฉพาะโครงการของเล่น ฉันจะเล่าให้คุณฟังเกี่ยวกับประสบการณ์ของฉันกับพวกเขาแต่ละคนก่อนที่จะบอกคุณว่าฉันเลือกได้ที่ไหน

PLT Racket มี IDE ที่ดีที่ไม่เพียง แต่ให้คุณประเมินนิพจน์จากเครื่องมือแก้ไขเท่านั้น แต่ยังช่วยให้คุณพิมพ์วงเล็บแทน parens สลับไปยัง parens ตามความเหมาะสม แร็กเก็ตยังมีไลบรารี่จำนวนมากที่มีการติดตั้งและพร้อมให้ดาวน์โหลดอีกมากมาย ดีบักเกอร์ที่มองเห็นก็มีประโยชน์เช่นกัน

My Common Lisp Implementation (SBCL) ไม่มี IDE แต่เป็นธรรมเนียมที่มีการใช้งาน CL แบบโอเพ่นซอร์สเพื่อใช้ Emacs และ SLIME การรวมกันนี้มีประสิทธิภาพมาก นอกเหนือจากความสามารถในการประเมินนิพจน์เมื่อคุณพิมพ์ลงในไฟล์ต้นฉบับแล้วยังมี REPL ที่มีคำสั่งแก้ไขทั้งหมดของ emacs ที่พร้อมใช้งานเพื่อให้การคัดลอกโค้ดสามารถทำได้อย่างมีประสิทธิภาพทั้งสองวิธี แม้แต่วัตถุที่แสดงในบัฟเฟอร์ REPL สามารถคัดลอกและวางได้ Alt+(และAlt+)มีประสิทธิภาพสำหรับการจัดการกับวงเล็บและเยื้องที่ตรงกัน

คุณสมบัติทั้งหมดของ Emacs ข้างต้นมีให้สำหรับ Clojure ประสบการณ์การแก้ไขของฉันกับ Clojure คล้ายกับ Lisp Java interop ทำงานได้ดีและฉันต้องการทำโครงการ Clojure เมื่อครบกำหนดแล้ว

ฉันสามารถเข้าถึงห้องสมุดโดยใช้ทั้งสาม (Common LISP, แร็กเก็ตและ Clojure) แต่ฉันลงเอยด้วยการเลือก Common LISP สำหรับโครงการ ปัจจัยการตัดสินใจคือ FFI นั้นง่ายต่อการใช้งานใน Common LISP มากขึ้น CFFI มีคู่มือที่ดีมากพร้อมรหัสตัวอย่างและคำอธิบายโดยละเอียดของแต่ละวิธี ฉันสามารถห่อ 20 C ฟังก์ชั่นในช่วงบ่ายและไม่ต้องสัมผัสรหัสตั้งแต่

ปัจจัยอื่นคือฉันคุ้นเคยกับ Common LISP มากกว่ากับ Clojure หรือ R6RS Scheme ฉันได้อ่านหนังสือ Common Common LISP และ Graham ส่วนใหญ่แล้วและฉันก็คุ้นเคยกับ Hyperspec ยังไม่ได้รหัส "lispy" มาก แต่ฉันแน่ใจว่าจะเปลี่ยนเมื่อฉันได้รับประสบการณ์มากขึ้น


ขอบคุณสำหรับรายละเอียด! ฉันเข้าใจคุณอย่างถูกต้องหรือไม่ว่าคุณคิดว่า FFI ของ SBCL นั้นใช้งานง่ายกว่า Clojure ถ้าเป็นเช่นนั้นฉันจะประหลาดใจมากที่คุณสามารถเรียกวิธีการของ Java โดยตรงจาก Clojure โดยไม่ต้องปิดมัน (หรือคุณต้องโทรหารหัสเนทีฟด้วย)
SuperElectric

6
@SuperElectric: การเรียกวิธีการ "Java" จาก Clojure นั้นเป็นเรื่องเล็กน้อย การเรียกใช้วิธีการ Java ที่อยู่ในไลบรารีที่ดาวน์โหลดมา: ไม่มาก ฉันใช้เวลามากขึ้นในการรับ classpath และสายการนำเข้ามากกว่าที่ฉันใช้เพื่อให้ C วิธีแรกของฉันทำงานได้จาก SBCL กับ CFFI แต่ฉันไม่ใช่ผู้เชี่ยวชาญเกี่ยวกับ Java ดังนั้นการสะสมไมล์ของคุณอาจแตกต่างกัน
Larry Coleman

21

ฉันเขียนโปรแกรมทั้ง CL และ Racket

ตอนนี้ฉันกำลังพัฒนาเว็บไซต์ใน Common LISP และฉันได้เขียนชุดโปรแกรมภายในสำหรับนายจ้างคนก่อนหน้าของฉันใน Racket

สำหรับรหัสใน บริษัท ฉันเลือก Racket (หรือที่รู้จักในชื่อ PLT Scheme) เพราะนายจ้างเป็นร้าน Windows และฉันไม่สามารถให้ LispWorks จ่ายค่าจ้างได้ การใช้ CL แบบโอเพ่นซอร์สที่ดีเพียงอย่างเดียวสำหรับ Windows คือ (และยังคงเป็น) CCL ซึ่งต้องการการสนับสนุน SSE ในโปรเซสเซอร์ นายจ้างราคาถูกกำลังใช้ฮาร์ดแวร์ยุคหิน แม้ว่านายจ้างจะมีฮาร์ดแวร์ที่ดี แต่ GUI GUI เดียวที่เกิดขึ้นใน Common LISP ก็คือ McCLIM ซึ่งทำงานได้กับ Unix เท่านั้น แร็กเก็ตมีห้องสมุด GUI ที่ดีที่ทำงานได้ทั้ง Unix และ Windows ซึ่งเป็นสิ่งสำคัญสำหรับความสำเร็จของโครงการของฉัน

ฉันใช้เวลากว่าหนึ่งปีในการแก้ไขด้วยโปรแกรมแก้ไข DrRacket ดั้งเดิม EMACS ไม่สามารถเปลี่ยน Racket ใน GUI เป็นที่รู้จักกันในชื่อ MrEd ในรูปแบบด้อยกว่าบน Windows ฉันต้องทำโดยไม่สามารถประเมินการแสดงออกที่เคอร์เซอร์ด้วยการกดแป้นเดียว แต่ฉันต้องเลือก S-expression ด้วยตนเองคัดลอกคลิกบนหน้าต่าง REPL (เนื่องจากไม่มีการกดแป้นพิมพ์เพื่อสลับไปที่มัน) แล้ววาง S-expression ฉันต้องทำโดยไม่มีตัวแก้ไขที่สามารถแสดงข้อโต้แย้งที่คาดหวังของฟังก์ชันหรือแมโครที่ฉันใช้ DrRacket ไม่สามารถทดแทน SLIME ได้

นายจ้างใช้ฐานข้อมูลที่เป็นกรรมสิทธิ์พร้อมกับ XML API ที่ซับซ้อนซึ่งจำเป็นต้องโหลดข้อมูลที่ไม่จำเป็นซึ่งดูเหมือนว่าจะสามารถตอบแบบสอบถามคิวรี่ SELECT ได้ ฉันตัดสินใจใช้ HTMLPrag ทั้งคู่เพื่อปล่อย XML ไปยัง API นี้และแยกการตอบสนอง มันใช้งานได้ดีมาก

ฉันต้องเรียนรู้ระบบมาซิงเกิ้ล "syntax-case" ที่ซับซ้อนของแร็กเกตเพื่อเขียนมาโครที่จะทำให้ฉันสามารถโต้ตอบกับ XML API ที่ซับซ้อนได้โดยพิมพ์ฟอร์มที่ดูเหมือน SQL ส่วนนี้จะง่ายกว่านี้ถ้าฉันมี DEFMACRO ในการกำจัดของฉัน อย่างไรก็ตามผลลัพธ์สุดท้ายยังคงราบรื่นแม้ว่ามันจะพยายามมากขึ้นเพื่อให้บรรลุ

นอกจากนี้ฉันต้องทำโดยไม่มีมาโคร Lisp ของ Common Lisp แร็กเก็ตเริ่มให้ทางเลือกเฉพาะหลังจากที่ฉันเขียนโค้ดส่วนใหญ่แล้วและทางเลือกยังคงแย่กว่าเมื่อเทียบกับ LOOP (แม้ว่าทีมพัฒนาของแร็กเก็ตจะยืนยันว่าดีกว่า - พวกเขาคิดผิด) ฉันลงเอยด้วยการเขียนแบบฟอร์ม LET จำนวนมากที่ใช้ "รถยนต์" และ "cdr" เพื่อทำซ้ำในรายการต่างๆ

เมื่อพูดถึงรถยนต์และ cdr ไม่มีอะไรน่าผิดหวังไปกว่าการตีความของ Scheme ว่า (car '()) ว่าเป็นข้อผิดพลาด ฉันใช้ประโยชน์จากความไวตัวพิมพ์เล็กและใช้งาน CAR และ CDR ซึ่งมีความหมายของ Common LISP อย่างไรก็ตามการแยก '() และ #f ทำให้มีประโยชน์น้อยกว่าในการส่งคืน' () เป็นค่าเริ่มต้น

ฉันยังได้ทำการติดตั้ง UNWIND-PROTECT อีกครั้งและคิดค้นระบบรีสตาร์ทของฉันเองเพื่อเติมเต็มช่องว่างที่แร็กเก็ตวางไว้ ชุมชน Racket จำเป็นต้องเรียนรู้ว่าการรีสตาร์ทนั้นมีประโยชน์มากและใช้งานง่าย

ฟอร์ม let-values ​​ของแร็กเกตนั้นมีความละเอียดมากเกินไปดังนั้นฉันจึงใช้งาน MULTIPLE-VALUE-BIND สิ่งนี้มีความจำเป็นอย่างยิ่งเนื่องจาก Racket ต้องการให้คุณรับค่าทั้งหมดที่สร้างขึ้นไม่ว่าคุณจะใช้หรือไม่ก็ตาม

ต่อมาฉันพยายามเขียนไคลเอนต์ XML XML ของ eBay ใน Common LISP เพียงเพื่อจะพบว่ามันไม่มีอะไรอย่าง HTMLPrag HTMLPrag มีประโยชน์ frickin ฉันสิ้นสุดที่ทำโครงการในแร็กเก็ต ฉันทำการทดลองด้วยโปรแกรมอำนวยความสะดวกการเขียนโปรแกรมของแร็คเก็ตเท่านั้นที่จะค้นพบว่าฉันเป็นโปรแกรมเมอร์คนเดียวในโลกที่พบว่ารหัสตัวอักษรที่เขียนขึ้นอย่างถูกต้องยากที่จะแก้ไขได้ยากกว่ารหัสธรรมดาหรือรหัสความรู้

โครงการใหม่ของฉันกำลังทำอยู่ใน Common LISP ซึ่งเป็นตัวเลือกที่เหมาะสมเพราะชุมชน Racket ไม่เชื่อในความเท่าเทียมซึ่งเป็นสิ่งจำเป็นสำหรับโครงการนี้ สิ่งเดียวที่ฉันคิดว่าฉันอาจจะพลาดจากแร็กเก็ตคือการต่อเนื่อง อย่างไรก็ตามฉันสามารถทำสิ่งที่ฉันต้องการได้โดยใช้การรีสตาร์ทและในการมองย้อนกลับไปอาจจะทำได้ด้วยการปิดอย่างง่าย


2
ฉันไม่ได้ลองด้วยตัวเอง แต่ฉันเห็นโพสต์บล็อกจากผู้ที่ใช้โปรแกรมแร็กเก็ตบรรทัดคำสั่งกับ Emacs ตัวอย่างเช่น: bc.tech.coop/scheme/scheme-emacs.htm
Larry Coleman

5
ในความเป็นธรรมดูเหมือนว่าคุณมาถึง Scheme ที่ต้องการเขียน CL แทนที่จะพยายามเข้าใกล้สิ่งต่าง ๆ จาก POV โครงการที่มีสำนวน ตัวอย่างเช่นรูปแบบไม่สนับสนุนการกลับเป็นซ้ำมากกว่าการใช้ลูปหรือไม่
เลื่อน

@ArtB โครงการไม่เพียง แต่ขอแนะนำให้เรียกซ้ำก็ต้องใช้มันเพื่อให้ของหลักสูตรโครงการดังกล่าวข้างต้นมาใช้จำนวนมากทั้งจากการเรียกซ้ำ และนั่นเป็นเพียงการเพิ่มการทำซ้ำ (คุณต้องรวมสำเนาการเรียกซ้ำในทุกสาขาของcondฟอร์ม) และข้อบกพร่อง (ฉันเขียนการทดสอบการยกเลิกลูปอย่างถูกต้องในเวลานั้นหรือไม่) แม้กระทั่งทุกวันนี้ฉันก็ได้รับความประทับใจ แร็กเก็ตนั้นมีไว้สำหรับนักเรียนไม่ใช่โปรแกรมเมอร์มืออาชีพ ทุกครั้งที่ฉันได้ยินใครบางคนนอกจากฉันใช้มันพวกเขากำลังใช้ภาษาย่อย "นักเรียนเริ่มต้น" และสำหรับชั้นเรียน
ทิ้งบัญชี

หากคุณกำลังทำซ้ำรหัสผ่าน CONDs คุณกำลังบอกว่าคุณต้องการฟังก์ชั่นอื่นหรือไม่?
เลื่อน

@ArtB ฟังก์ชั่นที่จะเรียกใช้ฟังก์ชัน loop ที่มีอาร์กิวเมนต์ต่างกันหรือไม่? นั่นคงจะไร้ประโยชน์ คุณเห็นว่าการทำซ้ำในรหัส Scheme ของใครก็ตาม มีแม้กระทั่งตัวอย่างในซอร์สโค้ดของแร็กเกต
ทิ้งบัญชี

5

แบบแผนถูกออกแบบด้วยการรวบรวมแยกในใจ ผลที่ตามมาคือพลังของมาโครมักจะถูก จำกัด อย่างรุนแรงแม้จะมีส่วนขยายที่อนุญาตให้ defmacro สไตล์ Lisp แบบธรรมดาแทนที่จะเป็นระบบแมโครที่ไม่ถูกสุขลักษณะ มันเป็นไปไม่ได้เสมอที่จะกำหนดแมโครที่กำหนดแมโครอื่นไว้สำหรับใช้ในบรรทัดถัดไปของรหัสทันที และความเป็นไปได้ดังกล่าวเป็นสิ่งจำเป็นสำหรับการใช้คอมไพเลอร์ eDSL ที่มีประสิทธิภาพ

ไม่ต้องพูดถึงว่าการใช้งาน Scheme ที่มีมาโครที่ถูกสุขลักษณะ R5RS เพียงอย่างเดียวนั้นมีประโยชน์สำหรับฉันไม่มากนักเนื่องจากรูปแบบ metaprogramming ของฉันไม่สามารถแปลได้อย่างถูกสุขลักษณะ

โชคดีที่มีการใช้งาน Scheme (เช่นแร็กเก็ต) ที่ไม่มีข้อ จำกัด ดังกล่าว


1
สวัสดีฉันเพิ่งเริ่มเปียกด้วย Scheme เมื่อเร็ว ๆ นี้โดยใช้ Racket คุณจะให้ตัวอย่างที่รวดเร็วของการใช้มาโครที่ไม่ถูกสุขลักษณะใน Racket หรือไม่? ประเภทของมาโครที่มีให้ดูเหมือนว่าเป็นหนึ่งในจุดที่ถกเถียงกันอย่างถึงพริกถึงขิงที่สุดระหว่าง CL และ Scheme
orange80

@ orange80 วิธีหนึ่งคือใช้docs.racket-lang.org/mzlib/mzlib_defmacro.htmlและแน่นอนว่าในโหมด R6RS มีวิธีที่ จำกัด น้อยกว่า
SK-logic

@ SK- ตรรกะคุณกำลังทำอะไรกับมาโครที่ไม่มีความสุขมาก?
เลื่อน

1
@ArtB ฉันใช้ eDSL ในฐานะคอมไพเลอร์ซึ่งอาจทำอะไรได้มากมายกับ AST ต้นทาง สุขอนามัยเป็นสิ่งที่น่ารำคาญอย่างยิ่ง คุณสามารถดูวิธีการทำงาน: github.com/combinatorylogic/mbase
SK-logic
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.