Lisp Case语句中的动态变量

时间:2010-12-18 18:42:12

标签: lisp common-lisp

我在常见的lisp中编写了这段代码(忽略了......因为在这里粘贴该部分毫无意义)。

(case turn 
   (*red-player* ...)
   (*black-player* ...)
   (otherwise ...))

red-player black-player 是使用defvar语句定义的变量,以便在C中“模拟”#define语句。

(defvar *red-player* 'r)
(defvar *black-player* 'b)

可以想象,当变量turn收到*red-player*的值('r)或*black-player*的值('b)时,case语句不会正常工作,因为它希望转弯包含*red-player*作为文字,而不是变量*red-player*的内容。

我知道我可以使用cond或if + equal语句轻松修复它,因为变量的内容在那里被评估,但我很好奇。也许有一种方法可以在Lisp中创建类似C的宏,或者有某种特殊的case语句允许使用变量而不是文字。

提前谢谢!

3 个答案:

答案 0 :(得分:5)

您可以使用阅读时评估

在表单中输入表达式的值
CL-USER 18 > (defvar *foo* 'a)
*FOO*

CL-USER 19 > (defvar *bar* 'b)
*BAR*

CL-USER 20 > '(case some-var (#.*foo* 1) (#.*bar* 2))
(CASE SOME-VAR (A 1) (B 2))

请注意,读取时评估不一定​​是改善代码维护和安全性的最佳选择。

另请注意,在Lisp中不需要有一个带有某个内部值的描述性名称的变量的想法:

dashedline = 4
drawLine(4,4,100,100,dashedline)

将在Lisp中

(draw-line 4 4 100 100 :dashed-line)

在Lisp中,可以传递描述性命名的符号。使用整数值或类似值的API只需要在API中使用通常用C语言编写的外部软件。

答案 1 :(得分:4)

简短的回答是“是的,你可以做到,有点像”。

更长答案的种子涉及使用defmacro创建自己的case版本,比如mycase,这将返回常规的case表单。您定义的宏将评估案例正文中每个列表的头部。

你会打电话:

(mycase turn
     (*red* ...)
     (*black* ...)
     (otherwise ...))

会返回

(case turn
   ((r) ...)
   ((b) ...)
   (otherwise ...))

给评估员。然后,将以您希望的方式评估返回的case表单。

然后,您可以自由地继续使用您的c-esque方式编程,让各地的lispers感到沮丧!双赢?

答案 2 :(得分:2)

您可以以任何您喜欢的方式滥用Lisp。与C不同,它很灵活。

它并不总是喜欢您使用它的用途。为什么要把Lisp推到一边?

尝试这种方法:

 (defvar *turn* nil)

 (cond
      ((eq *turn* 'red) 
        ...
        (setq *turn* 'black)))
      ((eq *turn* 'black) 
        ...
        (setq *turn* 'red)))
      (t
        .......))