简体   繁体   中英

"set-elts: contract violation. expected: set? , given: x" in Scheme

Friend gave me this problem to solve as a way for me to learn Scheme: E::= (λ VE) | (EE) | V with V=variable and write a Scheme function freeVariables which takes the free variables. For example:

Input = (freeVariables '(λ f (λ x (f ((t g) g)))))
Output = (t g)

However I have the code complete as shown below with logic done. But this is what happens when I add an input:

Input = (freeVariables'(λ f (λ x (f ((t g) g)))))
Output = set-elts: contract violation
  expected: set?
  given: x

What exactly is wrong with the code I have created? What does the output above mean? And are there any possible fixes? Everything is below Code, logic behind it and debugger.

#lang scheme
(require data/set)
(define (freeVariables exp)
  (cond [(null? exp) '()]
        [(symbol? exp) (list exp)]
        [(eq? (car exp) 'λ)
         (let ((variables (cadr exp))
               (body (caddr exp)))
           (set-difference (freeVariables body) variables))]
        [else (apply append (map freeVariables exp))]))

So the logic would work is this:

  • If exp is null = return empty list
  • If exp is a variable = return a list containing the variable -If the first element of exp is the symbol λ, then exp represents a lambda term. Then bind the variables in the lambda term to variables and the body of the lambda term to body, and we return the difference between the free variables in the body and the variables in the lambda term with usage of set-difference to remove bound variables from free variables in body.
  • Else exp must be a function application and append the results.

Debugger: 在此处输入图像描述

Thank you and kind regards

Input = (freeVariables'(λ f (λ x (f ((t g) g)))))
Output = set-elts: contract violation
   expected: set?
   given: x

The grammar in the question only allows for (λ x...) λ-expressions, with just one parameter.

This means you have a variable x , not a list of variables , to handle.

Thus, write

        (let ((var (cadr exp))   ; singular
           ....

to get that variable, and if you need to have a list of symbols to pass to set-difference , you need to create that list, using (list var) instead of your variables .

The error message indicates that a "contract" has been violated, ie a piece of code's expectations about one of its argument's type have not been met.

Specifically it says that a function set-elts , apparently called somehow by set-difference , expects one of its arguments to answer to the predicate set? , but it does not.

It also indicates x as the culprit, which is just a symbol inside your test expression. In your case, set? probably means lists, ie (list 'x) could pass the muster. If not, try (list->seteq (list var)) .

Another problem with your code is its use of append , which breaks the abstraction. Use set-union instead.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM