2012-01-06 15 views
5

क्या मानक सामान्य-लिस्प फ़ंक्शंस/मैक्रोज़ का उपयोग करके पैकेज से अस्थायी रूप से कुछ पैकेज आयात करने का कोई तरीका है?सामान्य लिस्प: पैकेज से कुछ फ़ंक्शंस अस्थायी रूप से आयात करने के लिए सर्वोत्तम तरीका

मुझे कोई नहीं मिला और मुझे अपना रोल करना पड़ा। यदि मानक पहले से ही ऐसी कार्यक्षमता प्रदान करता है, तो मुझे कुछ भी कोड अप करने की आवश्यकता नहीं है, या किसी अन्य भाषा का निर्माण शुरू नहीं करना है।

(defmacro with-functions (functions the-package &body body) 
    "Allows functions in the-package to be visible only for body. 
    Does this by creating local lexical function bindings that redirect calls 
    to functions defined in the-package" 
    `(labels 
    ,(mapcar (lambda (x) `(,x (&rest args) 
           (apply (find-symbol ,(format nil "~:@(~a~)" x) 
                ,the-package) 
             args))) 
       functions) 
    ,@body)) 

उदाहरण उपयोग:

(defclass-default test-class() 
    ((a 5 "doc") 
    (b 4 "doc"))) 
#<STANDARD-CLASS TEST-CLASS> 
CL-USER> 
(with-functions (class-direct-slots slot-definition-name) 'sb-mop 
    (with-functions (slot-definition-initform) 'sb-mop 
    (slot-definition-initform 
     (car (class-direct-slots (find-class 'test-class)))))) 
5 
CL-USER> 

संपादित करें: मैक्रो को रेनर के सुझावों में से कुछ शामिल।

मैंने पैकेज में फ़ंक्शन खोजने के लिए रन-टाइम लुकअप की समय लागत पर रन-टाइम लुकअप क्षमता रखने का निर्णय लिया।

मैंने एक आयात-आयात मैक्रो लिखने की कोशिश की जो छाया-आयात और अनन्य का उपयोग करता था, लेकिन मैं इसे काम नहीं कर सका। मुझे पाठक के साथ समस्याएं थीं कि कहा गया था कि आयातित कार्यों का मूल्यांकन करने वाले कोड से पहले आयातित फ़ंक्शंस अभी तक (पढ़ने के समय पर) मौजूद नहीं था।

मुझे लगता है कि इसे छायांकन-आयात और अनन्य के साथ काम करने के लिए एक बेहतर तरीका है, क्योंकि यह बहुत साफ, तेज (हालांकि कोई रन-टाइम लुकअप क्षमता नहीं होगी) और संकुल में कार्यों और प्रतीकों के साथ काम करेगा।

मुझे यह देखने में बहुत दिलचस्पी होगी कि क्या कोई अनन्य और छायांकन-आयात का उपयोग करके आयात-आयात मैक्रो को कोड कर सकता है या नहीं।

+0

यह लेक्सिकल फ़ंक्शंस के साथ काम नहीं करता है, क्योंकि आवेदन उन्हें नामों के रूप में प्रतीकों का उपयोग करके कॉल नहीं कर सकता है। –

+0

मुझे नहीं लगता कि यह एक मैक्रो के साथ संभव है, क्योंकि मैक्रो का विस्तार होने से पहले पाठक द्वारा प्रतीकों का समाधान किया जाता है, लेकिन मैं गलत हो सकता हूं कि मैं पूरी तरह से समझ नहीं पा रहा हूं कि पाठक कैसे काम करता है। – Daimrod

+0

@ डेमरोड ऐसे मैक्रो का निर्माण करना संभव होना चाहिए, लेकिन यह बहुत मुश्किल है (और, शायद, अप्राप्य), क्योंकि आपको प्रारंभिक प्रतीक-रिज़ॉल्यूशन रणनीति से उत्पन्न होने वाले नाम विवादों को संभालना होगा। –

उत्तर

1

आप योग्य प्रतीकों (अर्थात package:symbol या package::symbol) आप आयात करना चाहते हैं और फिर unintern उनमें से एक सूची के साथ import उपयोग कर सकते हैं।

2

यह रनटाइम फ़ंक्शन को अधिक महंगा बनाता है: यह एक तर्क सूची को संसाधित करता है, पैकेज में एक प्रतीक दिखता है, प्रतीक के फ़ंक्शन सेल के माध्यम से फ़ंक्शन को कॉल करता है।

यह केवल प्रतीकों के माध्यम से काम करता है, न कि व्याख्यात्मक कार्यों। यह मामलों में कम उपयोगी बनाता है, जहां मैक्रोज़ के माध्यम से कोड उत्पन्न होता है।

इसका नाम उलझन में है। 'आयात' एक पैकेज ऑपरेशन है और संकुल केवल प्रतीकों के साथ सौदा करते हैं, कार्यों में नहीं। आप पैकेज में फ़ंक्शन आयात नहीं कर सकते हैं, केवल एक प्रतीक।

(labels ((foo() 'bar)) 
    (foo)) 

शाब्दिक समारोह नाम FOO केवल स्रोत कोड एक प्रतीक है। इसके स्रोत प्रतीक के माध्यम से फ़ंक्शन तक पहुंचने का कोई तरीका नहीं है (उदाहरण के लिए (symbol-function 'foo) का उपयोग करके)। यदि एक कंपाइलर कोड के ऊपर संकलित करेगा, तो उसे प्रतीक रखने की आवश्यकता नहीं है - इसे डिबगिंग उद्देश्यों के अलावा अन्य की आवश्यकता नहीं है। आवेदन करने के लिए आपका कॉल LABELS या FLET द्वारा बनाए गए किसी भी फ़ंक्शन को खोजने में विफल रहेगा।

आपका मैक्रो प्रतीक आयात नहीं करता है, यह स्थानीय लेक्सिकल फ़ंक्शन बाध्यकारी बनाता है।

थोड़ा समान मैक्रोज़ के लिए CL:WITH-SLOTS और CL:WITH-ACCESSORS देखें। वे रनटाइम लुकअप का समर्थन नहीं करते हैं, लेकिन कुशल संकलन की अनुमति देते हैं।

आपका मैक्रो है इस तरह (यहाँ "CLOS" का उपयोग कर एक पैकेज के रूप में, बस अपने "एसबी-एमओपी" की तरह) नहीं घोंसला:

(defpackage "P1" (:use "CL")) 
(defpackage "P2" (:use "CL")) 

(with-import (p1::class-direct-slots) 'CLOS 
    (with-import (p2::class-direct-slots) 'P1 
    (p2::class-direct-slots (find-class 'test-class)))) 

उत्पन्न कोड है:

(LABELS ((P1::CLASS-DIRECT-SLOTS (&REST ARGS) 
      (APPLY (FIND-SYMBOL "CLASS-DIRECT-SLOTS" 'CLOS) ARGS))) 
    (LABELS ((P2::CLASS-DIRECT-SLOTS (&REST ARGS) 
      (APPLY (FIND-SYMBOL "CLASS-DIRECT-SLOTS" 'P1) ARGS))) 
    (P2::CLASS-DIRECT-SLOTS (FIND-CLASS 'TEST-CLASS)))) 
+0

मुझे आपके उपयोग के मामले को समझने में परेशानी हो रही है। 'कार्य' arglist में कोई भी नहीं होना चाहिए। कार्यकर्ताओं के पास ऐसे प्रतीक होते हैं जो फ़ंक्शन नामों का प्रतिनिधित्व करते हैं, और पैकेज वह स्थान है जहां वे कार्य रहते हैं। यह स्लॉट और एक्सेस-एक्सेसर्स के समान है। मुझे लगता है कि आपके द्वारा लिखे गए कोड को इस तरह दिखना चाहिए: (आयात के साथ (कक्षा-डायरेक्ट-स्लॉट) 'बंद करें (कक्षा-डायरेक्ट-स्लॉट (खोज-श्रेणी' टेस्ट-क्लास)) –

+0

@claytontstanley: क्यों नहीं? पी 1 :: क्लास-डायरेक्ट-स्लॉट एक कानूनी फ़ंक्शन नाम है। बिना स्लॉट या एक्सेसर्स को ऐसे नामों से निपटने में कोई समस्या नहीं है। मेरा उदाहरण दिखाता है कि घोंसला वाला आयात जहां एक फ़ंक्शन उत्पन्न होता है और फिर कोई अन्य इसका उपयोग करने का प्रयास करता है, यह आपके मैक्रो के साथ संभव नहीं है। याद रखें: यदि आप कॉमन लिस्प मैक्रोज़ से निपटते हैं, तो आप केवल एक ऐसा निर्माण नहीं लिख रहे हैं जिसका उपयोग अंतिम उपयोगकर्ता द्वारा सरल तरीके से किया जाता है (जिनकी सीमा आपको दस्तावेज़ और/या जांचनी होगी), लेकिन सबकुछ भी बहुत अधिक हो सकता है अधिक जटिल कोड जो अन्य कोड (-> मैक्रोज़) द्वारा उत्पन्न होता है। –

संबंधित मुद्दे