2010-12-18 148 views
4

我用普通的lisp编写了这段代码(忽略了...,因为在这里粘贴这个部分没有意义)。Lisp的动态变量Case语句

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

红色玩家黑球员使用defvar声明中定义的变量,为了C.

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

以“模拟” #define语句,你可以想象一下,当变量turn收到*red-player*的值('r)或*black-player*的值('b)时,case语句无法正常工作,因为它预期该转折包含*red-player*作为文字,而不是变量*red-player*

我知道我可以很容易地解决这个问题,使用cond或if + equal语句,因为变量的内容在那里被评估,但我很好奇。也许有一种方法可以在Lisp中创建类似C的宏,或者有某种特殊情况语句允许使用变量而不是文字。

预先感谢您!

+3

试图在lisp中模拟C预处理器宏...多么讽刺。 – delnan 2010-12-18 19:04:55

+0

它是什么类型的变量是没有区别的... – 2010-12-18 21:23:01

回答

2

你可以用任何你喜欢的方式滥用Lisp。这是灵活的,不像C.

它并不总是你把它的用途。为什么要推动Lisp?

试试这个办法:

(defvar *turn* nil) 

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

在注意到我的第一种方法无法正常工作之后,这是我的第一个解决方案。 – Chocolatmisu 2010-12-19 14:17:57

4

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

的时间越答案的种子涉及使用defmacro创建自己的case版本,说mycase,将返回一个普通case形式。您定义的宏将评估案例主体中每个列表的头部。

你会打电话:

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

这将返回

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

的评估。然后返回的case表单将以您想要的方式进行评估。

然后,你可以继续自由地继续使用c-esque风格编程,让每个地方的监护人都感到沮丧!双赢?

+0

非常感谢您的回答!我以前从来没有想过使用defmacro,结果是一个好主意。 – Chocolatmisu 2010-12-19 14:11:51

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只需要在通常用C编写的外部软件的API中。

+0

谢谢你的想法和你的知识!我会仔细考虑采取哪种方式,最终制定案例陈述。 – Chocolatmisu 2010-12-19 14:16:55