2016-07-15 62 views
1

前言:我目前考虑的是在LISP显然教冷凝当然,我从来没有在我的生活LISP工作,所以我必须学会在语言周末。我提前为严重的代码道歉。我只是熟悉LISP的语法来获得代码的工作,而不是更多。的Common Lisp(SBCL):从内部返回值循环

我目前正在上解决了地图着色问题的程序。此代码采用一个序列,其中每个子序列的第一个元素是一个状态,第二个元素表示一个颜色。例如:“((A R)(B G)(C G)(d Y)(E B)(F B)),然后进行检查以确保没有状态具有的颜色,因为它是由约束的状态下(由约束列表中定义的)相同。我知道可能有很多更干净更简单的方法来做到这一点,但是我现在正在努力的是让我的dolist循环在if语句满足时立即返回值T.到目前为止,我一直无法得到的功能只返回一个值,而不得不求助于变量设置为true,并等待循环,以便使代码工作完成的这实在是太丑/错误的方法。我已经尝试过使用return并且只在if语句内部有T,但是在这两种情况下,循环都会完成而不是返回一个值,我不知道为什么。

(setq constraint '((A (B C E)) (B (A E F)) (C (A E F)) (D (F)) (E (A B C F)) (F (B C D E)))) 

(defun check_constraint (f s) 
    (setf ans nil) 
    (dolist (state constraint) 
     (if (eq (first state) f) 
      (if (search (list s) (second state)) 
       (setf ans T) ;;where I want it to just return T 
      ) 
     ) 
    ) 
    ans 
) 

;;ex: ((A R) (B R) (C B) (D R) (E B) (F G)) 
(defun check_conflict (lst) 
    (setf anb nil) 
    (dolist (state lst) 
     (dolist (neighbor (remove state lst)) 
      (if (check_constraint (first state) (first neighbor)) 
       (if (eq (second state) (second neighbor)) 
        (setf anb T)) ;;where I want it to just return T 
      ) 
     ) 
    ) 
    anb 
) 

编辑:我结束了刚刚修复这与递归。现在的代码更清洁,但我仍然很想知道我的问题是什么。这是递归代码。

(setq constraint '((A (B C E)) (B (A E F)) (C (A E F)) (D (F)) (E (A B C F)) (F (B C D E)))) 

(defun check_constraint (lst f s) 
    (COND 
     ((null lst) nil) 
     ((search (list (car (car lst))) f) 
      (if (search s (second (car lst))) T)) 
     (t (check_constraint (cdr lst) f s)) 
    ) 
) 

(defun check_neighbor (check lst) 
    (COND 
     ((null lst) nil) 
     ((check_constraint constraint (list (car check)) (list (first (first lst)))) 
      (if (eq (second check) (second (car lst))) T)) 
     (t (check_neighbor check (cdr lst))) 
    ) 
) 

;;(check_state '((A R) (B R) (C B) (D R) (E B) (F G))) 
(defun check_state (lst) 
    (COND 
     ((null lst) nil) 
     ((check_neighbor (car lst) (cdr lst)) T) 
     (t (check_state (cdr lst))) 
    ) 
) 
+0

有很多口齿不清方言的,你不说哪个。在大多数方言中,都有一个特殊的形式'return',可以用来从更高层次的形式返回一个值。不幸的是,它适用于哪种形式是方言之间不同的事情之一。因此,在那一点上使用'(return T)'可以处理我所知道的大多数方言[并且可以避免使用变量'ans'和'anb',并且在循环之后只有'NIL']。 – MAP

+0

@MAP这是常见的lisp,试图说明,我无法在SBCL中使用它。 – Metasyntactic

回答

4

首先是一些样式问题。您应该使用DEFVAR or DEFPARAMETER来声明全局变量。这些名称也应该用星号表示,表明它们是全球性的(或实际上是特殊的)。

(defparameter *constraint* 
    '((A (B C E)) 
    (B (A E F)) 
    (C (A E F)) 
    (D (F)) 
    (E (A B C F)) 
    (F (B C D E)))) 

的事物命名Lisp的惯例是字(CHECK-CONSTRAINT而不是CHECK_CONSTRAINT)之间使用破折号。你也应该喜欢全字变量名称,而不是缩写(LIST而不是LST)。封闭的括号不应该写在他们自己的行上。

那么实际问题。您可以使用RETURN从名为NIL的块返回值。循环建立这样一个块,所以你可以写像

(defun check-constraint (first second) 
    (dolist (state *constraint*) 
    (when (and (eq first (first state)) 
       (member second (second state))) 
     (return t)))) 

这是更好的第一功能使用WHEN,而不是IF时,有只有当时的分支。我还使用AND将两个IF组合成一个。由于你在使用SEARCH的列表中包装S,我想你可能想用MEMBER代替(尽管我不确定,因为我不完全知道代码应该做什么)。如果它错了,你可以改变它。

你或许也可以将它简化为

(defun check-constraint (first second) 
    (member second (second (find first *constraint* :key #'first)))) 

在第二个函数有两个循环。如果你使用RETURN从内部返回,那么你最终会继续外部循环并忽略返回值。所以你必须使用RETURN-FROM从函数返回而不是内部循环。

(defun check-conflict (list) 
    (dolist (state list) 
    (dolist (neighbor (remove state list)) 
     (when (and (check-constraint (first state) (first neighbor)) 
       (eq (second state) (second neighbor))) 
     (return-from check-conflict t))))) 
+0

这是完美的!感谢您花时间带我浏览一些样式问题。我一直在急着尽快地选择它,课程资源有限。这是非常丰富的信息。 – Metasyntactic