लिस्प कस्टम तुलना फ़ंक्शन

मान लें कि मैं एक नई कक्षा foo को परिभाषित करता हूं:

(defclass foo ()
  ((bar :initarg :bar ...)
   (baz :initarg :baz ...)
   ...))

और मैं foo के लिए एक कस्टम तुलनित्र बनाना चाहता हूं, जैसे कि:

(defun foo-equalp (foo1 foo2)
  (equalp (bar foo1)))

क्या foo-equalp फ़ंक्शन को foo वर्ग में जोड़ने के लिए एक बेहतर, अधिक स्पष्ट तरीका होगा?

मैं # 'foo-equalp को : test तर्क के रूप में Remote-DUPLICATES जैसे फ़ंक्शंस के लिए तर्क नहीं दे रहा था, लेकिन यहां तक ​​कि अगर संभव नहीं है, मैं अभी भी जानना चाहूंगा कि इस समारोह को परिभाषित करने के लिए एक और बेवकूफ लिस्प तरीका है या नहीं।

0
@ जोशुआ टेलर: क्या आप cdr.eurolisp.org/document/8/cleqcmp.html से अवगत हैं ? मैंने सीडीआर 8 के कार्यान्वयन को एक साथ रखा है, लेकिन इसे अभी तक प्रकाशित नहीं किया है (इसे साफ़ करने और इसे सबमिट करने की आवश्यकता है)।
जोड़ा लेखक Paul Nathan, स्रोत
@ जोशुआ टेलर: github.com/pnathan/generic-comparability (मैंने सीडीआर 2 कार्यान्वयन पर भी काम किया , लेकिन यह कम बेक्ड है)।
जोड़ा लेखक Paul Nathan, स्रोत
ऐसा लगता है कि आप एक समानता भविष्यवाणी करना चाहते हैं कि एक सामान्य कार्य है जिसमें विशेष तरीकों को जोड़ा जा सकता है (जैसे कि आप जावा में .equals() विशेषज्ञ कैसे कर सकते हैं)। दुर्भाग्यवश, "सामान्य" भविष्यवाणी ( eq , eql , बराबर , equp ) सामान्य कार्यों में से कोई भी नहीं है, इसलिए, इस तरह के एक सामान्य कार्य को लिखना बहुत कठिन नहीं है, फिर भी आपको इसे निकालें , आदि जैसे लाइब्रेरी फ़ंक्शंस में पास करना होगा, क्योंकि यह उन लाइब्रेरी फ़ंक्शंस के लिए डिफ़ॉल्ट तुलना नहीं होगा ।
जोड़ा लेखक Joshua Taylor, स्रोत
@ पॉलनाथन मैं सीडीआर रिपोजिटरी से अवगत था, लेकिन मैंने पहले उस विशेष को नहीं पढ़ा था। यह एक अच्छा विचार की तरह दिखता है। मैं निश्चित रूप से एक उत्तर उभारा होगा जिसने इसका उपयोग किया है। :) मुझे एहसास है कि आपने कहा है कि आपने इसे अभी तक प्रकाशित नहीं किया है, लेकिन क्या यह अभी तक किसी भी राज्य में ऑनलाइन उपलब्ध है?
जोड़ा लेखक Joshua Taylor, स्रोत

1 उत्तर

अगर मैं आपका प्रश्न समझता हूं तो सामान्य फ़ंक्शन यहां सहायता कर सकता है

(defgeneric foo-equalp (foo1 foo2))

(defmethod foo-equalp ((foo1 foo) (foo2 foo))
  (and (equal (bar foo1) (bar foo2))
       (equal (baz foo1) (baz foo2))))

और अब जब आप उन वस्तुओं के साथ foo-equp को कॉल करते हैं जो प्रकार foo नहीं हैं तो आपको यह त्रुटि मिलती है।

There is no applicable method for the generic function
  #
when called with arguments
  (1 2).

या आप सब कुछ वापस लौटने के लिए चाहते हैं

(defmethod foo-equalp ((foo1 t) (foo2 t))
  nil)

यहां हम टी पर विशेषज्ञ हैं जो सभी ऑब्जेक्ट्स का सेट है । जब आप एक विधि को कॉल करते हैं तो सामान्य lisp हमेशा तर्कों के लिए 'निकटतम/सबसे विशिष्ट' प्रकार का मिलान चुनता है (उह जो वर्णन का एक भयानक उलझन है .. मुझे और कॉफी चाहिए, लिंक को देखें क्योंकि यह शानदार है :) )

  • आपको वास्तव में टी का विशेषज्ञ होने की आवश्यकता नहीं है क्योंकि यह डिफ़ॉल्ट है लेकिन मैं यह दिखाने के लिए शामिल करना चाहता था कि क्या हो रहा था।

The following are snippets from Practical Common Lisp (which is linked at the top of this answer)

एक सामान्य कार्य एक सार ऑपरेशन को परिभाषित करता है, जिसका नाम निर्दिष्ट करता है   और एक पैरामीटर सूची लेकिन कोई कार्यान्वयन नहीं। वास्तविक कार्यान्वयन   एक सामान्य कार्य के तरीकों से प्रदान किया जाता है।

     

तरीके इंगित करते हैं कि वे किस प्रकार के तर्कों को संभाल सकते हैं   जेनेरिक फ़ंक्शन द्वारा परिभाषित आवश्यक पैरामीटर को विशेषज्ञता देना।

     

उदाहरण के लिए, एक सामान्य फ़ंक्शन ड्रा के लिए, आप एक विधि को परिभाषित कर सकते हैं   जो ऑब्जेक्ट्स के लिए आकृति पैरामीटर का माहिर हैं जो उदाहरण हैं   वर्ग सर्कल जबकि अन्य विधि वस्तुओं के लिए आकार माहिर हैं   जो वर्ग त्रिकोण के उदाहरण हैं।

3
जोड़ा
जब आप विरासत और/या विधि संयोजनों का उपयोग करके इसे कई तरीकों से विस्तारित करने की योजना बनाते हैं तो सामान्य कार्यों का उपयोग करें। अन्यथा यह अधिक हो सकता है।
जोड़ा लेखक Rainer Joswig, स्रोत
चीयर्स, मैं हमेशा किस तकनीक को चुनने के लिए थोड़ा आलसी रहा हूं। अंगूठे के नियम के रूप में यह अच्छा लगा।
जोड़ा लेखक Baggers, स्रोत