กำลังโหลดแพ็คเกจ Quicklisp เพื่อใช้ในไฟล์เสียงกระเพื่อมอื่น

ฉันได้ดาวน์โหลดโครงการซอฟต์แวร์ขนาดใหญ่ FriCAS ซึ่งฉันได้รวบรวมจากแหล่งที่มาและใช้ SBCL นี่เป็นเพียงเรื่องของการใช้ GNU .configure - ฉันเป็นมือใหม่ Lisp ที่สมบูรณ์

อย่างไรก็ตาม เพื่อที่จะเพิ่มฟังก์ชันการทำงานเพิ่มเติม ฉันจึงได้ติดตั้ง Quicklisp และแพ็คเกจพิเศษบางอย่างโดยปฏิบัติตามคำแนะนำอย่างระมัดระวัง จนถึงตอนนี้ดีมาก

นี่คือปัญหาของฉัน: ฉันกำลังพยายามรวบรวมไฟล์เสียงกระเพื่อมภายนอกเพื่อใช้ในระบบ ฉันจำเป็นต้องทำให้คอมไพเลอร์มองเห็น Quicklisp และแพ็คเกจของมันได้ ดังนั้นฉันจึงคัดลอกไฟล์ .sbclrc ไปไว้ที่ด้านบนสุดของไฟล์เสียงกระเพื่อม:

#-quicklisp
(let ((quicklisp-init (merge-pathnames "quicklisp/setup.lisp"
                                       (user-homedir-pathname))))
  (when (probe-file quicklisp-init)
    (load quicklisp-init)))

ฉันได้ติดตามเรื่องนี้ด้วย

(eval-when (:compile-toplevel)
  (ql:quickload "f2cl-lib"))

ฉันได้ติดตั้ง f2cl-lib ด้วย Quicklisp แล้ว อย่างไรก็ตาม คอมไพเลอร์ของฉัน (ภายใน FriCAS) จะยกเลิกทันที

; caught ERROR:
;   READ error during COMPILE-FILE:
;   
;     Package QL does not exist.

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


person Alasdair    schedule 24.10.2015    source แหล่งที่มา


คำตอบ (1)


ดูเหมือนคำถามที่พบบ่อย โปรดดูเอกสารประกอบสำหรับ eval-when

ตัวรวบรวมไฟล์

โปรดจำไว้ว่า ตัวคอมไพลเลอร์ไฟล์ จะคอมไพล์แบบฟอร์มและไม่ได้ดำเนินการใดๆ มันแค่สร้างโค้ดสำหรับดำเนินการในภายหลัง โดยทั่วไป. แม้ว่าใน Common Lisp จะมีข้อยกเว้นบางประการสำหรับกฎนี้ ตัวอย่างเช่น มาโคร ที่ใช้ในซอร์สโค้ด จะถูกเรียกใช้โดย คอมไพเลอร์ไฟล์ แต่ Common Lisp ยังช่วยให้เราสามารถบอก ตัวคอมไพเลอร์ไฟล์ ให้รันโค้ดในเวลาคอมไพล์ นั่นเป็นหนึ่งในกรณีการใช้งานของ eval-when

ตัวอย่างของคุณทำให้ง่ายขึ้น

หากคุณมีไฟล์:

(load "file-which-creates-package-foo")

(eval-when (:compile-toplevel)
  (foo:bar)) 

จากนั้น คอมไพเลอร์ไฟล์ จะสร้างโค้ดสำหรับการโหลดไฟล์ แต่จะไม่โหลดไฟล์

ต่อไป ตัวคอมไพเลอร์ไฟล์ จะเห็นรูปแบบที่สอง โดยที่ ตัวคอมไพเลอร์ไฟล์ ได้รับคำสั่งให้รันคำสั่ง ณ เวลาคอมไพล์ (และเฉพาะที่ เวลาคอมไพล์) ดังนั้น (foo:bar) จะถูกดำเนินการ ณ เวลาคอมไพล์ แต่ที่แย่กว่านั้น: เนื่องจากยังไม่ได้ดำเนินการโหลดโค้ด จึงไม่ทราบแพ็คเกจ FOO และแบบฟอร์ม (foo:bar) จะถูกอ่าน ณ เวลาคอมไพล์ ผู้อ่านบ่นแล้วที่ เวลาคอมไพล์< /em> ว่าไม่มีแพ็คเกจ FOO อยู่

การใช้ EVAL-WHEN

สิ่งที่คุณต้องทำคือบอก ตัวคอมไพเลอร์ไฟล์ ให้โหลดสิ่งที่ต้องการระหว่างการคอมไพล์ ไฟล์นี้มีแบบฟอร์ม eval-when อยู่แล้ว ดังนั้นควร ให้คำแนะนำแก่คุณ: ใช้ eval-when มี สถานการณ์ สามประการ:

  • :compile-toplevel -> คอมไพเลอร์ไฟล์รันแบบฟอร์มที่แนบมา
  • :load-toplevel -> คอมไพเลอร์ไฟล์สร้างโค้ดเพื่อให้โค้ดถูกเรียกใช้งานเมื่อโหลดโค้ด
  • :execute

ตรวจสอบให้แน่ใจว่ามีการกล่าวถึง สถานการณ์ เหล่านั้น เมื่อโค้ดควรถูกเรียกใช้งาน

วิธีแก้ปัญหาที่เป็นไปได้

จึงมีวิธีแก้ปัญหาที่เป็นไปได้:

  • ดังที่กล่าวข้างต้น ให้ใช้ EVAL-WHEN เพื่อให้สามารถรันแบบฟอร์มโดย คอมไพเลอร์ไฟล์
  • เขียนโค้ดการโหลดลงในไฟล์แยกต่างหากและคอมไพล์/โหลดไฟล์นี้ก่อนที่คุณจะใช้แพ็คเกจ นอกจากนี้ยังสามารถเพิ่มไฟล์นี้ลงใน ระบบ เพื่อให้ไฟล์นั้นจะถูกโหลดโดยการคอมไพล์ระบบ ก่อนที่จะคอมไพล์โค้ดที่ใช้
person Rainer Joswig    schedule 24.10.2015
comment
ขอบคุณมากสำหรับการตอบกลับโดยละเอียดของคุณ - ซึ่งส่วนใหญ่ฉันสามารถเข้าใจได้ ฉันรู้สึกว่า Lisp นั้นยากเกินไปสำหรับคนร้ายไร้ความสามารถอย่างฉัน ฉันจะพยายามอีกสักหน่อยแล้วยอมแพ้อย่างสง่างาม - person Alasdair; 24.10.2015
comment
@Alasdair: เป็นไปได้ที่จะเรียนรู้สิ่งนั้นและสถานที่อย่าง stackoverflow สามารถช่วยแก้ไขปัญหาการเขียนโปรแกรมได้ FriCAS/Axiom เป็นซอฟต์แวร์ที่ซับซ้อนมากและการขยายการใช้งานทำให้จำเป็นต้องเรียนรู้บางอย่าง นอกจากนี้ยังมีรายชื่อผู้รับจดหมายสำหรับ FriCAS ซึ่งอาจได้รับความช่วยเหลือเพิ่มเติมในการขยายเวลา - person Rainer Joswig; 24.10.2015
comment
โอ้ ใช่แล้ว ฉันสร้างความรำคาญให้กับตัวเองอย่างมากในรายการส่งเมล FriCAS! - person Alasdair; 24.10.2015