当我运行它时,它指出列表约束是未绑定的.这是为什么? [英] When I run this, it states that the list constraints is unbound. Why is that?

查看:91
本文介绍了当我运行它时,它指出列表约束是未绑定的.这是为什么?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

(defun combinations (&rest lists) (if (car lists) (mapcan (lambda (inner-val)(mapcar (lambda (outer-val) (cons outer-val inner-val)) (car lists))) (apply #'combinations (cdr lists))) (list nil)))

组合功能为每个棒球运动员创建名称,护身符和位置的所有组合.

(defun main()
  (setq m-list (combinations '(Blacket Bluet Browning Greenfield Whitehall)'(four-lear-clover penny rabbit-foot ribbon silver-dollar) '(center-    field first-base right-field short-stop third-base)))
  (setq contraints  (list '(no Browning penny) '(no Browning silver-dollar) '(no Browning right-field) '(no Browning center-field) '(no Bluet center-field) '(no Bluet right-field) '(no Greenfield first-base) '(no Greenfield short-stop)
    '(no Greenfield third-base) '(no Whitehall center-field) '(no Whitehall right-field) '(no Greenfield four-leaf-clover) '(no Greenfield penny) '(no Whitehall four-lear-clover) '(no Whitehall penny) 
    '(no Blacket four-leaf-clover) '(no Blacket penny) '(no Blacket first-base) '(no Blacket third-base) '(no Blacket ribbon) '(no Bluet ribbon) '(no center-field rabbit-foot)))
  (loop  
   (setf n-constraint (car constraints))
   (setf m-list (remove-l m-list n-constraint))
   (setf constraints (cdr constraints))
   (when (null constraints) (return m-list))))

主要功能用于解决玩家位置和魅力都不为人知的问题.主要功能列出了球员的所有可能组合,他们的魅力和他们的棒球位置.然后,它声明一个约束列表,每个列表都声明否",并在开始时指示在否"之后的两个值都不应以任何形式组合.进行循环以便从约束列表中获取一个约束.约束的动力是清单本身. Main然后使用remove-l函数消除与约束不一致的组合.然后,Remove-l返回一个新的m-list,该列表的组合比以前少

(defun remove-l (a b)
  (setf n-list '())
  (loop 
    (setf sample (car a))
    (when (and (not (= (find (nth 1 b) sample) nil) (= (find (nth 2 b)sample) nil))) (cons sample (cons n-list nil)))
(setf a (cdr a))(when (null a) (return n-list))))

此处的remove -l函数用于返回一个具有与以前相同的大多数组合的新列表.约束列表中的一个约束用于消除某些组合.

(defvar  *data* nil) 

忽略

(defun add-player (player)
  (push player *data*))

忽略

(defun dump-data ()
  (dolist (cd *data*)
   (format t "~{~a:~10t~a~%~}~%" cd)))

忽略

解决方案

Xach已经指出了注释中的拼写错误,但是我认为我会添加一些有关您的代码的注释.

您不应使用SETQSETF定义变量.这些仅应用于将值设置为已定义的变量.对局部变量使用 LET/LET* DEFVAR/DEFPARAMETER .

遍历列表也是一件很普通的事情,它具有内置的构造: DOLIST ,在扩展的LOOP中,您可以使用FOR element IN list.

在修复了这些问题并为您的REMOVE-L添加了更好的缩进之后,它看起来像这样:

(defun remove-l (a b)
  (let ((n-list '()))
    (dolist (sample a n-list) ; That N-LIST is the return value from the loop
      (when (and (not (= (find (nth 1 b) sample)
                         nil)
                      (= (find (nth 2 b) sample)
                         nil)))
        (cons sample (cons n-list nil))))))

那仍然有一些问题.请注意,AND中只有一种形式,而NOT中却有两种形式. =用于数字相等,因此您应该使用NOT 检查是否有错误.当然,还有CONS不是破坏性的问题.您必须将其返回值设置为某个位置.就像现在一样,循环不执行任何操作.您可以使用 PUSH 将元素添加到列表中.

修复这些问题,您将得到以下内容:

(defun remove-l (a b)
  (let ((n-list '()))
    (dolist (sample a n-list)
      (when (and (not (find (nth 1 b) sample))
                 (not (find (nth 2 b) sample)))
        (push sample n-list)))))

您可以通过将两个约束分配给变量(使用LET currying 的好地方,它不是内置的,但是如果您已经安装了 Quicklisp ,则可以使用

ignore

Xach already pointed out the spelling mistake in the comments, but I figured I'd add some comments regarding your code.

You should not define variables with SETQ or SETF. Those should be used only to set values to already defined variables. Use LET/LET* for local variables, or DEFVAR/DEFPARAMETER for globals.

Looping over lists is also such a common thing to do that there are built in constructs for it: DOLIST and in extended LOOPs you can use FOR element IN list.

After fixing those and adding some better indentation to your REMOVE-L, it would look like this:

(defun remove-l (a b)
  (let ((n-list '()))
    (dolist (sample a n-list) ; That N-LIST is the return value from the loop
      (when (and (not (= (find (nth 1 b) sample)
                         nil)
                      (= (find (nth 2 b) sample)
                         nil)))
        (cons sample (cons n-list nil))))))

That still has some problems. Notice how the AND only has one form in it, and the NOT has two. = is meant for numeric equality, so you should use NOT or NULL to check if something is non-true. Then there's of course the problem that CONS is not destructive; you have to set its return value to someplace. As it is now, the loop does not do anything. You could use PUSH to add elements to a list.

Fixing those, you would have something like this:

(defun remove-l (a b)
  (let ((n-list '()))
    (dolist (sample a n-list)
      (when (and (not (find (nth 1 b) sample))
                 (not (find (nth 2 b) sample)))
        (push sample n-list)))))

You could further improve it by assigning the two constraints to variables (using either LET or DESTRUCTURING-BIND) instead of calling NTH twice per iteration. However, filtering a list is also a very common thing to do and your REMOVE-L could be easily expressed with the built-in REMOVE-IF. You could change your MAIN to something like this:

(defun main ()
  (let ((m-list ...) ; I left out the long lists. Fill them in.
        (constraints ...))
    ;; This uses LOOPs destructuring assignment. The underscore is
    ;; just an unused variable that holds the NO in each constraint.
    ;; CONSTRAINT-1 and -2 hold the two symbols.
    (loop for (_ constraint-1 constraint-2) in constraints
          do (setf m-list (remove-if (lambda (sample)
                                       ;; I used MEMBER instead of FIND.
                                       ;; It doesn't really matter, but
                                       ;; MEMBER communicates intent better.
                                       (and (member constraint-1 sample)
                                            (member constraint-2 sample)))
                                     m-list)))
    m-list))

Edit: Now that I remembered, Common Lisp also has a built in function SUBSETP to check if a list is a subset of another list (disregarding order). With that you don't need to destructure the constraint list.

(defun main ()
  (let ((m-list ...)
        (constraints ...))
    (dolist (constraint constraints m-list)
      (setf m-list (remove-if (lambda (sample)
                                (subsetp (cdr constraint)
                                         sample))
                              m-list)))))

This would be a good place to use currying, which is not built in, but if you have Quicklisp installed you can use the implementation from Alexandria or you can just write a simple one yourself:

(defun curry (function &rest arguments)
  (lambda (&rest more)
    (multiple-value-call function (values-list arguments) (values-list more))))

(defun main ()
  (let ((m-list ...)
        (constraints ...))
    (dolist (constraint constraints m-list)
      (setf m-list (remove-if (curry #'subsetp (cdr constraint))
                              m-list)))))

这篇关于当我运行它时,它指出列表约束是未绑定的.这是为什么?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆