-1
(define (delete-list my-list element)
  (if (null? my-list)
      '()
      (if (eqv? (car my-list) element)
          (cdr my-list)
          (append (list (car my-list))
                  (delete-list (cdr my-list) element)))))

(delete-list '('aaa 'bbb) 'aaa)
; ==> ('aaa 'bbb)

Why doesn't this code output ('bbb)? How to solve this problem?

sds
  • 58,617
  • 29
  • 161
  • 278

3 Answers3

3
  1. you need to search for 'aaa, not aaa
  2. you need to test for equality

Example:

(define (delete-list my-list element)
  (if (null? my-list)
      '()
      (if (equal? (car my-list) element)
          (cdr my-list)
          (append (list (car my-list))
                  (delete-list (cdr my-list) element)))))

?  (delete-list '('aaa 'bbb) ''aaa)
=> ((quote bbb))
Rainer Joswig
  • 136,269
  • 10
  • 221
  • 346
3

Scheme has 3 general equality predicates procedures. eq? that checks pointer equalness, eqv? that checks for the same value for the primitive types numbers, and chars. equal? checks if the values look the same.

A list '(a b) is a complex structure so (eq? '(a b) '(a b)) ; ==> #f *1 while (equal? '(a b) '(a b)) ; ==> #t. This your procedure needs to use equal? if you are comparing lists.

A quote creates a structure. Thus the code 'x means (quote x) and '(a b) means (quote (a b)) regardless if it happens inside data or in code. The evaluator will stop at the first so '('aaa 'bbb) becomes (quote ((quote aaa) (quote bbb))) and since only the first quote is code the result is the data ((quote aaa) (quote bbb)) that the implementation might visualize as ('aaa 'bbb). To create a element in the last list you need the evaluated result to be (quote aaa) ('aaa) so you need to pass ''aaa. As you might have understood the evaluated value 'aaa is the list data (quote aaa) and you need equal? to test them:

(eqv? ''aaa ''aaa)   ; ==> #f *1
(equal? ''aaa ''aaa) ; ==> #t

Other things

As a style thing since you using nested if you could flatten the feel by using one cond instead.

When adding one element to the beginning of a list you should use cons: (cons 'a '(b c)) is more concise than (append (list 'a) '(b c)) which eventually does (cons (car (list 'a)) '(b c))

With those added, I have this:

(define (delete-list my-list element)
  (cond
    ((null? my-list) '())
    ((equal? (car my-list) element) (cdr my-list))
    (else (cons (car my-list)
                (delete-list (cdr my-list) element)))))

(delete-list '('aaa 'bbb 'ccc 'bbb) ''bbb)
; ==> ('aaa 'ccc 'bbb)

(delete-list '(aaa bbb ccc bbb) 'bbb)
; ==> (aaa ccc bbb)

Note that your design only removes the first occurencs, as demonstrated in my test.

*1 constant data might get reused. Thus some implementations return #t on (eq? ''aaa ''aaa) since constant data cannot be changed so it is safe for an implementation to reuse the one value. Some implementations does this only when compiled but recreates the constant data when interpreted.

Sylwester
  • 47,942
  • 4
  • 47
  • 79
  • Thank you very much ! I can understand what you explain to me. But I want to know how to convert doble single quote to single quote. – 土井公宏 Jun 16 '19 at 11:54
  • 1
    @土井公宏 I saw that on a different answer that you wanted `(delete-list (list (list 'quote 'aaa) (list 'quote 'bbb)) 'aaa) ; ==> ('bbb)`. You do understand that you are no longer loooking to `aaa` but `(list 'quote element)`? I'm wondering if perhaps your assignment has a typo or that your copying of it got one. – Sylwester Jun 16 '19 at 13:08
1

You don't need to quote stuff inside a quote. So just use '(aaa bbb) as your input.

river
  • 1,028
  • 6
  • 16