2014-10-01 3 views
2

나는 새로운 lisp 프로그래머이다. 나는 머리를 감싸는 데 어려움을 겪고있다. 나는 기호를 숫자로 대체하는 일련의 방법을 통해 간소화하는 일련의 표현을 가지고 있으며 그 표현을 평가할 것입니다. 평가하기 전에 숫자에 대한 기호를 대체합니다.이 방법을 사용하면 subst-bindings 메서드에서 스택 오버플로 오류가 발생하거나 해당 메서드 내에서 deep-subst 메서드를 호출 할 수 있습니다. 재귀 적 메서드 호출에 대한 도움이나 조언은 내가 더 잘 이해할 수 있도록 도울 것입니다.Lisp 무한 재귀

(setq p1 '(+ x (* x (- y (/z 2))))) 
    (setq p2 '(+ (- z 2) (* x 5))) 
    (setq p3 '(+ 1 a)) 


    (defun deep-subst (old new l) 
     (cond 
     ((null l) 
     nil 
     ) 
     ((listp (car l)) 
     (cons (deep-subst old new (car l)) (deep-subst old new (cdr l))) 
     ) 
     ((eq old (car l)) 
     (cons new (deep-subst old new (cdr l))) 
     ) 
     (T 
     (cons (car l) (deep-subst old new (cdr l))) 
     ) 
    ) 
    ) 

    (defun subst-bindings (bindinglist exp) 
     (cond 
     ((null bindinglist) 
      exp) 
     (T 
      (subst-bindings (cdr bindinglist)(deep-subst (car (car bindinglist)) (cdr (car bindinglist)) exp)) 
     ) 
     ) 
    ) 

    (defun simplify (exp) 
     (cond 
     ((listp exp) 
      (simplify-triple (car exp) (simplify (car(cdr exp)))(simplify (car (cdr (cdr exp))))) 
     (T 
      exp)))) 

    (defun evalexp (binding-list exp) 
     (simplify (subst-bindings binding-list exp)) 
    ) 
     (evalexp '((x 2) (z 8)) p1) ;Where I call evalexp from and gives me the stack overflow error 
+1

받은 오류 메시지와 함께 가장 작은 양의 코드와 문제를 재현하는 테스트 사례를 표시 할 수 있다면 더 많은 도움이됩니다. Common Lisp에는 trace 매크로가 포함되어 있으므로'deep deep-subst() '를 실행하면 deep-subst에 대한 모든 호출을 볼 수 있으므로 문제를 쉽게 발견 할 수 있습니다. –

+0

나는 추적을 시도 할 것이고, 나는 또한 문제를보기 위해 필요하지 않거나 도움이되지 않은 코드를 꺼냈다. 코드의 마지막 줄은 evalexp를 호출하는 예제 테스트 케이스입니다. – Branbron

+1

좀 더 디버깅하고 싶을 것 같습니다. 이 문제는 대치 함수에서 유일하게 * 나타나지 않습니다. 예를 들어 http://pastebin.com/NWHPK5PF는 문제없이 실행됩니다 (결과는 예상 한 것이 아닐 수 있으며 bindinglist는'((x. 2) (z. 8))')?) . 이는 단순화 될 때 무언가가 잘못되었다는 것을 암시한다. –

답변

3

문제는 추적 증거로 단순화 기능을 낳는다 below-- 내 코드는 우리가 기능에 대해 살펴 경우

(trace simplify) 

(evalexp '((x 2) (z 8)) p1) 
0: (SIMPLIFY (+ (2) (* (2) (- Y (/Z 2))))) 
    1: (SIMPLIFY (2)) 
     2: (SIMPLIFY NIL) 
     3: (SIMPLIFY NIL) 
      4: (SIMPLIFY NIL) 
      5: (SIMPLIFY NIL) 
       6: (SIMPLIFY NIL) 
       7: (SIMPLIFY NIL) 
        8: (SIMPLIFY NIL) 
        9: (SIMPLIFY NIL) 
         10: (SIMPLIFY NIL) 
         11: (SIMPLIFY NIL) 
          12: (SIMPLIFY NIL) 
          13: (SIMPLIFY NIL) 
           14: (SIMPLIFY NIL) 
           15: (SIMPLIFY NIL) 
            16: (SIMPLIFY NIL) 
            17: (SIMPLIFY NIL) 
             18: (SIMPLIFY NIL) 

그리고

(defun simplify (exp) 
     (cond 
      ((listp exp) 
      (simplify-triple 
       (car exp) 
       (simplify (car(cdr exp))) 
       (simplify (car (cdr (cdr exp))))) 
      (T 
      exp)))) 

우리는 것을 알 수 있습니다 재귀는 함수 listp을 기반으로합니다. listp이 true를 반환하면 simplify을 매개 변수로 두 번 호출하는 simplify-triple이 호출됩니다. 우리가 추적에서 볼 수 있듯이 nil을 반복해서 호출하고 (listp nil)을 테스트하면 empty list을 나타내는 이되므로 T을 반환하므로 끝없는 재귀를 유도합니다.

if (조건부에 걸쳐서) 재귀를 기반으로해야합니다.

+0

다른 값으로 반환 값을 확인하는 방법을 알려 드리겠습니다. 이해해 주셔서 감사합니다! – Branbron

+0

'(and (listp exp) exp)'와 같은 것을 사용하면'nil'을'and'로 쓰면'nil'을 부울 false로 해석합니다. – Sim

+1

list는'endp '와 함께있다. – Svante