Как вернуть управление из функции в lisp - PullRequest
1 голос
/ 28 сентября 2010
(defun returnFirstCharacter(p)

(if (symbolp p) (char (symbol-name p) 0) nil)
)

 (defun returnRestCharacters (p)
(let ()
    (intern (subseq(string p) 1))
)         
)

 (defun val (x a)
  (cond ((null a) nil)
        ((equal (car(cdr a)) x) (cdr (cdar a)))
        (t (val x (cdr a)))
    )
 )



 (defun match (pattern data)
(cond 
    ((equal pattern data) t)
    ((match2 pattern data nil))
    (t nil)
)
 )

  (defun match2 (p d a)
(cond

    ( (null p)(cond 
                    ((null a) t)
                    (t a)
                )
    )

    ((numberp p) (cond 
                        ((equal p d) t) 
                        (t nil)
                    )
    ) 

    (  (symbolp p) (cond
                        ((alpha-char-p (returnFirstCharacter p))
                                    (let ()(if (equal p d) (match2 nil nil a) nil)))
                        ((equal (returnFirstCharacter p) #\=)
                                    (let ()
                                            (if (and  (returnRestCharacters p) (null (val (returnRestCharacters p) a)))
                                                (match2 nil nil (cons (
                                                                                list  = (returnRestCharacters p)  d)  a)
                                                )
                                                (let ()
                                                    (if (and  (returnRestCharacters p) (equal (val (returnRestCharacters p) a) (car d))) 
                                                        (match2 (cdr p) (cdr d) a) nil)
                                                )
                                            )
                                    )
                        )
                    )
    )
    (   (listp p) 
                    (cond 
                        ((equal (list-length p) (list-length d))
                            (let ()
                            (   if (equal p d) 
                                    (match2 nil nil a)  
                                    (let ()
                                        (append (match2 (car p) (car d) a)(match2 (cdr p) (cdr d) a) )
                                    )


                            )
                            )
                        )
                    )
    )

)
)

У меня match2, вызываемый дважды сам по себе. Я хочу, чтобы происходили рекурсивные вызовы.В тот момент, когда вызов match2 возвращает либо true, либо nil, программа завершается. Я хочу, чтобы управление было передано обратно к предыдущему match2, который его вызвал.

Как вы можете видеть, я дважды вызывал match2.(listp p) это условие в match2 мне нужно сделать рекурсию. Как это сделать

1 Ответ

1 голос
/ 28 сентября 2010

Это похоже на часть блока COND.Имея это в виду, я добавил обратно COND и переформатировал код, чтобы сделать его немного более очевидным.

(cond ((alpha-char-p (returnFirstCharacter p))
       (let () (if (equal p d) (match2 nil nil a) nil)))
      ((equal (returnFirstCharacter p) #\=)
       (let ()
         (if (and (returnRestCharacters p)
                  (null (val (returnRestCharacters p) a)))
             (match2 nil nil (cons (list '= (returnRestCharacters p) d) a))
             (let ()
               (if (and (returnRestCharacters p) 
                        (equal (val (returnRestCharacters p) a)
                               (car d))) 
                   (match2 (cdr p) (cdr d) a) nil))))))

Во-первых, вы вызываете MATCH2 из хвостовой позиции,так что не очевидно, что вы подразумеваете под «передачей контроля назад к предыдущему совпадению2».Когда произойдет вызов MATCH2, как написано, возвращаемое значение будет просто распространяться по цепочке вызовов, поскольку вы ничего не делаете с возвращаемым значением.

Во-вторых, вы используете пустые блоки LET дляочевидная причина (первый IF вызывает MATCH2, если условие истинно, в противном случае переходит к следующему IF).Ни в том, ни в другом случае у вас нет нескольких выражений, требующих оценки, так что вы могли бы просто пропустить блоки LET.Кроме того, использование PROGN немного более привычно, чем использование пустого блока LET (не имеет значения для компилятора, но имеет значение для читателя).

Вероятно, это поможет, если вы замените сегмент кодавыше с полным определением функции MATCH2 и добавлено «простое английское» описание того, что, по вашему мнению, должно быть сделано.

Редактировать : с опубликованным кодом целиком (и с отвратительным форматированием),в MATCH2 есть только один случай, когда существует концепция «вернись и сделай что-нибудь», и это два вызова, которые являются аргументами для APPEND, в самом конце.Есть по крайней мере один фрагмент кода, который, вероятно, вызовет ошибки во время выполнения (и определенно предупреждения времени компиляции), с =, используемым в качестве переменной (если в другом месте нет динамического inding, это, вероятно, должно быть '=).

Вы все еще не объяснили, что должен делать код.Если вы сядете и напишете то, что, как вы ожидаете, будет делать код, в пошаговой манере, возможно, вы поймете, в чем дело.

...