2013-02-05 13 views
8

के बारे में उलझन में मैंने रैकेट/सूची में count के साथ उपयोग के लिए true? फ़ंक्शन को परिभाषित किया।रैकेट अनुबंध

(define (true? expr) 
    (and (boolean? expr) expr #t)) 

मैंने देखा मैं इसे संख्यात्मक तर्क प्रदान कर सकता है और मेरे समारोह खुशी से #f लौट आते हैं।

> (true? 6) 
#f 

तो, मैंने सोचा कि मैं गैर बूलियन तर्क अनुबंध उल्लंघन करते हुए एक त्रुटि वापसी बनाने के लिए एक रैकेट अनुबंध का उपयोग कर पता लगाने जाएगा। अनुबंध मैं अभी भी रैकेट आरईपीएल में ऊपर के रूप में समान व्यवहार प्राप्त जोड़ने के बाद

(provide (contract-out 
      [true?   (-> boolean? boolean?)])) 

हालांकि,: तो मैं अपनी फ़ाइल के टोपे पर इस कोड डाल दिया। मुझे समझ में नहीं आता कि यह कैसे हो सकता है। मैं क्या खो रहा हूँ?

+2

ध्यान दें कि आपके विशेष संदर्भ के लिए, आप 'मूल्य' का उपयोग करने में सक्षम हो सकते हैं, क्योंकि रैकेट' # f' को छोड़कर सब कुछ सच मानता है। उदा .: '(मूल्यों की गणना करें '(कितने # एफ सच # एफ # एफ चीजें # एफ))' – dyoo

उत्तर

20

अनुबंध आमतौर पर मॉड्यूल के बीच लागू किए जाते हैं। तो आपको इसे बाहरी परिप्रेक्ष्य से आजमाने की ज़रूरत होगी। हालांकि, आरईपीएल आपके द्वारा काम कर रहे मॉड्यूल के अंदर से लागू होता है।

बाहर से परीक्षण करने का एक आसान तरीका test submodule का उपयोग करना है। उदाहरण के लिए:

#lang racket 

(define (true? expr) 
    (and (boolean? expr) expr #t)) 

(provide (contract-out 
      [true?   (-> boolean? boolean?)])) 

(module* test racket/base 
    (require (submod "..") 
      rackunit) 
    (check-true (true? #t)) 
    (check-false (true? #f)) 
    (check-exn exn:fail:contract? (lambda() (true? 3)))) 

बदलें अनुबंध और DrRacket में फिर से चलाने के लिए, और तुम यहाँ प्रभाव में अपने अनुबंध को देखना चाहिए, क्योंकि यहां test मॉड्यूल अनुबंध के एक बाहरी ग्राहक के रूप में इलाज किया जा रहा है।


वैकल्पिक रूप से, कि require पहले एक और फ़ाइल बनाने, और फिर आप वहां भी ठेके के प्रभाव देख सकते हैं। पहली फ़ाइल true-test.rkt कहा जाता है, तो आप एक और मॉड्यूल बना सकते हैं, और उसके बाद:

#lang racket 
(require "true-test.rkt") 
(true? 42) ;; And _this_ should also raise a contract error. 
13

डैनी Yoo एक शानदार जवाब दिया। मैं बस उस पर विस्तार करना चाहता था और ध्यान दें कि रैकेट आपको आपके अनुबंध को लागू करने के लिए अधिक लचीलापन देता है (यानी, अनुबंध सीमा कहां रखना है)।

-> (define/contract (true? expr) 
    (-> boolean? boolean?) 
    (and (boolean? expr) expr #t)) 

जो अनुबंध true? की परिभाषा और सभी अन्य कोड के बीच की जाँच स्थापित करेगा: उदाहरण के लिए, आप define/contract फार्म का उपयोग कर सकते हैं

-> (true? "foo") 
; true?: contract violation 
; expected: boolean? 
; given: "foo" 
; in: the 1st argument of 
;  (-> boolean? boolean?) 
; contract from: (function true?) 
; blaming: top-level 
; at: readline-input:1.18 
; [,bt for context] 

मैं define/contract विशेष रूप से उपयोगी लगता है मैं कुछ परीक्षण करना चाहते हैं, तो आरईपीएल में अनुबंध से संबंधित, जहां मेरे पास हमेशा एक मॉड्यूल नहीं होता है। हालांकि, contract-out डिफ़ॉल्ट अनुशंसा है क्योंकि मॉड्यूल सीमाओं पर अनुबंधों की जांच करना आमतौर पर एक अच्छा विकल्प होता है।

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