2017-12-26 26 views
1

Scheme에서 객체와 표현식을 취하는 함수를 만드는 질문을하고 있습니다. 예를 들어 (foo 'x '(x 10 x x 4))은 주어진 객체를 따르는 모든 객체를 반환해야하므로 위의 함수 호출은 (10 x 4)을 반환합니다. 그러나 표현에는 (foo 'y '(y (3 y 5 y y 8 9) (10 y 12 13 y 15 y) 17))과 같이 목록을 포함하여 ((3 y 5 y y 8 9) 5 y 8 12 15)을 반환해야합니다. 목록이있을 때 문제가 있습니다. 지금까지 제 코드가 있습니다. 식이 목록이 포함 된 경우 목록을 포함하는 표현식을 통한 스키마 루핑

(define (foo target expression) 
    (cond [(null? expression)] 
     [(list? (first expression)) (foo target (first expression))] 
     [(eqv? (first expression) target) (cons (first (rest expression)) (foo target (rest expression)))] 
     [(not (eqv? (first expression) target)) (foo target (rest expression))])) 

그래서, 나는 그러나, 내가 검색을 계속하기 위해 원래의 표정으로 돌아 가야하는 방법을 모른다, 재귀 적으로 그 목록에있는 함수를 호출하는 것을 시도하고있다.

내가 얻고 (foo 'y '(y (3 y 5 y y 8 9) (10 y 12 13 y 15 y) 17))를 호출 할 때 그래서 ((3 y 5 y y 8 9) 5 y 8 . #t) 그렇게 성공적으로 첫 번째 목록을 통해 루프는 그러나 그것은 그 후 중지하고

또한 표현에 두 번째 목록에 도달하지 않는다, 나는 데 다른 하나의 문제입니다 부울 결과가 끝날 때,이 줄이 cond [(null? expression)] 인 것을 알았습니다. 표현식이 끝나면 오류가 발생했기 때문에이 내용을 추가했습니다. 어떻게 해결할 수 있습니까?

답변

1

빈 목록 '()으로 끝내는 경우에만 (cons x (cons y ...이 적절한 목록이된다는 점에 유의하십시오. 따라서 (cons x (cons y ... empty))은 적절하며 (list x y ...)과 같습니다. 반대로 : (cons x (cons y ... #t)). 기본 케이스의 결과를 '()으로 수정하면 문제를 해결할 수 있습니다.

그러나 입력 목록의 요소 수가 2 개 미만일 때 테스트 할 때는 두 번째 기본 사례가 필요합니다. 이는 함수가 나중에 (first (rest expression))이라는 두 번째 요소에 액세스하려고하기 때문입니다. 따라서 이것이 유효한지 확인하려면 expression이 적어도 2 개의 요소를 유지하도록해야합니다. 귀하의 경우에는 ... (null? (rest expression)) ...으로 할 수 있습니다. 만 (first expression)을 처리,이 경우

[(list? (first expression)) (foo target (first expression))] 

,하지만 당신은 (first expression)(rest expression) 모두 처리해야합니다 한편

, 당신은 단지 그것 때문에이 라인의 발견 첫 번째 목록 요소를 반복 할 기능. 목록을 재구성 할 때 다음과 같이 죄수를 사용할 수 있습니다.

(cons (foo target (first expression)) 
     (foo target (rest expression))) 

그러나 원래 목록의 깊이를 다시 만듭니다. 원하는 출력의 예에서, 당신이 결과를 평평하게 할 것 같다, 그래서으로 더 나은 옵션은 append에게 다음과 같습니다

(define (foo obj expr) 
    (cond 
    [(null? expr) #f] 
    [(null? (rest expr)) '()] 
    [(pair? (first expr)) 
    (append (foo obj (first expr)) 
      (foo obj (rest expr)))] 
    [(equal? obj (first expr)) 
    (cons (second expr) 
      (foo obj (rest expr)))] 
    [else 
    (foo obj (rest expr))])) 

다음 당신이해야합니다 :

(append (foo target (first expression)) 
     (foo target (rest expression))) 

가 다음 다시 쓰기를 고려 :

(foo 'x '(x 10 x x 4)) 
=> '(10 x 4) 
(foo 'y '(y (3 y 5 y y 8 9) (10 y 12 13 y 15 y) 17)) 
=> '((3 y 5 y y 8 9) 5 y 8 12 15) 

는하지만 당신은해야합니다 :

(foo 'x '()) 
=> #f 
(foo 'x '(x)) 
=> '() 
+0

이 질문에 주어진 예제 중 하나는'(foo 'z'z) =>()'입니다. 어떻게 추가 할 수 있습니까? 현재'rest : contract violation expected : (와/c list? (not/c empty?)) given : z' –

+0

'[(not (list? expr)) '()]'을 추가했는데 제대로 작동하는 것 같습니까? –

+0

맞습니다. 이를 통해, 입력 표현식이리스트가 아닐 때마다 빈리스트를 출력합니다. 첫 번째 기본 케이스로 테스트되도록 주문하십시오. – assefamaru