在学习了CL并在不同的小项目中作为爱好练习了一段时间之后,我的个人CL图上仍然有一些空白区域。最近,我有许多函数都使用相同的owner
构造,并且我想到编写一个宏来使代码更简洁:
// Loop through the items
foreach( $array as $item ):
echo $item;
endforeach;
以便以后可以定义类似的功能(仅作为最小示例):
// Change final item
echo $item . 'last item';
现在,我想知道是否可以使用let
之类的宏/函数来缩短(defmacro with-context (&body body)
`(let ((context (make-array 4 :element-type 'fixnum
:initial-contents '(0 1 2 3))))
,@body))
表达式。
(defun test-a ()
(with-context
(setf (aref context 3)
(+ (aref context 0) (aref context 1)))
context))
但是变量(aref context n)
当然在编译时是未知的。我只是不知道我是否在这里有一些基本的误解,或者我怎么能告诉lisp我真正想要的是什么。所以,我的问题基本上是,是否有可能,这是否是个好主意。
答案 0 :(得分:4)
本地函数怎么了?
(defmacro with-context (&body body)
`(let ((context (make-array 4 :initial-contents '(0 1 2 3))))
(flet ((context (n)
(aref context n)))
,@body)))
也进行设置:
(defmacro with-context (&body body)
`(let ((context (make-array 4 :initial-contents '(0 1 2 3))))
(flet ((context (n)
(aref context n))
((setf context) (new n)
(setf (aref context n) new)))
,@body)))
答案 1 :(得分:3)
您可以在宏扩展中放入 Private Sub Form_formclosing(ByVal sender As Object, ByVal e As FormClosingEventArgs) Handles MyBase.FormClosing
If inEditMode Then
Dim dialog As DialogResult = MessageBox.Show("You can't exit the program when in edit mode. Please save your changes before exiting the program.")
If DialogResult = DialogResult.OK Then
e.Cancel = True
End If
Else
Dim dialog As DialogResult = MessageBox.Show("Do you really want to close the program? Any unsaved changes will be lost.", "Exit Application?", MessageBoxButtons.YesNo, MessageBoxIcon.Warning)
If dialog = DialogResult.Yes Then
Application.ExitThread()
ElseIf dialog = DialogResult.No Then
e.Cancel = True
End If
End If
End Sub '^warns user before closing the application^
:
macrolet
一些个人笔记:
我不喜欢照应宏,因此通常让用户为上下文定义名称。不过,对于(defmacro with-context (&body body)
(with-gensyms (i)
`(let ((context (make-array 4 …)))
(macrolet ((context (,i)
`(aref context ,,i)))
,@body))))
宏,这会感到奇怪。然后,我可能得出的结论是,我想要的只是一个context
函数,并继续使用make-standard-context
。我认为这与一般指南“常规”保持一致。