ฉันมีมาโครที่ต้องขยายในทุก ๆ อินสแตนซ์ของการใช้งานคอมไพล์เวลา มีวิธีที่ฉันสามารถระบุให้เป็นเช่นนั้นโดยไม่ต้องผ่าน codebase และตัดสายแต่ละอย่างด้วยeval-when-compile
หรือไม่
ฉันมีมาโครที่ต้องขยายในทุก ๆ อินสแตนซ์ของการใช้งานคอมไพล์เวลา มีวิธีที่ฉันสามารถระบุให้เป็นเช่นนั้นโดยไม่ต้องผ่าน codebase และตัดสายแต่ละอย่างด้วยeval-when-compile
หรือไม่
คำตอบ:
แมโครทั้งหมดที่เข้าถึงได้โดย byte-compiler จะถูกขยายระหว่างการคอมไพล์ "Reachable" หมายถึงไม่มีการอ้างถึง
เนื้อความของdefun
s, defmacro
s, lambda
s ทั้งหมดถูกคอมไพล์ด้วยไบต์เมื่อไฟล์ต้นฉบับที่มีอยู่นั้นถูกคอมไพล์ด้วยไบต์ ใช่แล้วแมโครใด ๆ ในตัวพวกมันจะถูกขยายออกไปตราบใดที่มันไม่ได้อยู่ในเครื่องหมายคำพูด ( '
) ความผิดพลาดที่พบบ่อยมากคือการห่อlambda
ในใบเสนอราคาและในความเป็นจริงที่ว่าทำไมคุณควรไม่เคยพูดของคุณlambda
s
นี่เป็นหนึ่งในข้อได้เปรียบที่ยิ่งใหญ่ของมาโครตราบใดที่เขียนได้ดีก็ไม่มีผลกระทบต่อประสิทธิภาพการทำงานของรันไทม์ ข้อได้เปรียบอื่น ๆ คือพลังและความเก่งกาจของพวกเขาแน่นอน ข้อเสียคือคุณต้องจัดการกับไวยากรณ์ไม่ใช่วัตถุดังนั้นจึงมีพื้นที่เหลือเฟือสำหรับปัญหาบางอย่างที่ไม่คาดคิดบางอย่างไม่สามารถหลีกเลี่ยงได้
ดังที่ Malabarba ได้อธิบายไปแล้วมาโครจะถูกขยายในระหว่างการคอมไพล์ไบต์ หากไฟล์ไม่ได้คอมไพล์มาโครจะถูกขยายเมื่อโหลดไฟล์ (กระตือรือร้นที่จะขยายมาโคร)
อย่าวางใจในสิ่งนี้ มันเป็นสไตล์ที่แย่มาก โดยทั่วไปคุณไม่สามารถคาดหวังว่ารหัสที่ใช้มาโครของคุณจะถูกรวบรวมจริงและโดยทั่วไปคุณควรเรียกใช้รหัสน้อยที่สุดเท่าที่จะเป็นไปได้ในระหว่างการรวบรวม โดยเฉพาะให้ใช้มาโครแทบจะไม่นานหากไม่มีวิธีอื่น ในฐานะที่เป็นกฎง่ายๆให้ใช้มาโครเฉพาะสำหรับไวยากรณ์และไม่ต้องมีความหมาย (หรือฟังก์ชันการทำงาน)
มาโครเป็นสิ่งที่เป็นนามธรรม การขยายตัวของพวกเขาจะถูกเขียนโค้ดลงในรหัสเป้าหมายในเวลารวบรวมและไม่สามารถเปลี่ยนย้อนหลังได้ รหัสเป้าหมายในภายหลังขึ้นอยู่กับการใช้งานเฉพาะของแมโครในเวลาที่ขยาย โดยเฉพาะมันขึ้นอยู่กับAPI ภายในทั้งหมดที่ใช้ในร่างกายแมโคร
ดังนั้นคุณไม่สามารถเปลี่ยนแปลง API นี้หรือสิ่งใดก็ตามที่การขยายมาโครอาศัยอยู่โดยไม่ทำลายโค้ดใด ๆ ที่คอมไพล์มาโครของคุณ
นิยมใช้แมโครสำหรับการทำงานปูถนนไปยังนรกพึ่งพา