代码之家  ›  专栏  ›  技术社区  ›  robertpostill

使用自定义谓词定义racket契约

  •  1
  • robertpostill  · 技术社区  · 6 年前

    我刚刚开始学习合同(通过exercism.io),因此我签订了一份合同:

    [step1 (-> (and/c number?
                      less-than-one-hundred?)
                string?)]
    

    认为 我的意思是,这个函数的值小于100(这是一个定义为:

    (define (less-than-one-hundred? n)
      (< n 100))
    

    但是当我这样调用函数时:

    (step1 100)
    

    没有违反合同。我做错了什么?

    2 回复  |  直到 6 年前
        1
  •  2
  •   Alex Knauth    6 年前

    下面是一个具体的例子,说明Soegaard的答案是什么:

    #lang racket
    
    (provide (contract-out
              [step1 (-> (and/c number?
                                less-than-one-hundred?)
                         string?)]))
    
    (define (less-than-one-hundred? n)
      (< n 100))
    
    (define (step1 x) "")
    

    使用-step1.rkt

    #lang racket
    
    (require "def-step1.rkt")
    
    (step1 100)
    

    这会像您预期的那样导致合同违约,尤其是 use-step1.rkt ,一个不同于 def-step1.rkt 合同来源地:

    step1: contract violation
      expected: less-than-one-hundred?
      given: 100
      in: an and/c case of
          the 1st argument of
          (->
           (and/c number? less-than-one-hundred?)
           string?)
      contract from: .../def-step1.rkt
      blaming: .../use-step1.rkt
       (assuming the contract is correct)
    
        2
  •  2
  •   soegaard    6 年前

    合同仅在模块边界上强制执行。 这意味着如果您的表达式 (step1 100)

    step1 用一个合同,然后在另一个模块中导入 步骤1