以下代码旨在从指定的等待时间开始倒计时,然后评估提供的表单:
(defun wait (seconds form)
(let ((end (+ (get-universal-time) seconds)))
(do ()
((>= (get-universal-time) end)
(eval form))
(sleep 1))))
如果我跑:
(wait 5 (format t "output"))
结果是“输出”将在倒计时之前发送到stdout。输出“输出”后,程序仍像往常一样倒计时。
我得到了预期的结果,其中“输出”在倒计时结束后发送到stdout,使用以下代码:
(defun wait (seconds form)
(let ((end (+ (get-universal-time) seconds)))
(do ()
((>= (get-universal-time) end)
(format t "output"))
(sleep 1))))
为什么在DO循环中调用EVAL会在声明DO循环时进行评估,但直接插入正在评估的表单会导致它等到结果时间?
答案 0 :(得分:10)
初学者的Lisp编程的第一定律:不,你不需要public function saveIngredients($ingredient_id)
{
foreach($ingredient_id as $row => $value) {
$query=$this->db->where('ingredient_id', $value->ingredient_id);
if($query->num_rows > 0) {
echo '<div class="alert alert-error"><a class="close" data-dismiss="alert">×</a><strong>';
echo "Ingredient already taken";
echo '</strong></div>';
} else {
$this->db->insert('ingredient', $value);
$insert_id[] = $this->db->insert_id();
}
}
return $insert_id;
}
。
您的函数未获取表单eval
,而是评估(foo)
的结果。在调用函数之前,将评估函数的所有参数。 Lisp不会使用参数的形式调用函数,而是调用参数的结果。
您的代码
(foo)
会发生什么?
(wait ; function wait
5 ; argument expression 1
(format t "output")) ; argument expression 2
是一个函数,得到它。wait
- &gt; 5
5
- &gt; (format t "output")
+输出作为副作用NIL
和wait
5
醇>
改进:传递功能
如果您不想在调用中运行参数,请创建一个函数NIL
,该函数将被计算为函数对象,将其传递给变量(lambda () (foo))
,并调用它delayed-function
。
这里发生了什么?
(funcall delayed-function)
(wait
5
(lambda ()
(format t "output")))
是一个函数,得到它。wait
- &gt; 5
5
- &gt;一个功能对象(lambda () (format t "output"))
和函数对象wait
醇>
现在你的函数5
需要做它想做的事情,并使用FUNCALL在正确的位置调用传递的函数对象。
答案 1 :(得分:2)
调用函数时,其参数在传递给函数之前会被计算一次。如果要传递未评估的表单,可以使用宏。 E.g:
(defmacro wait (seconds form)
(let ((end-name (gensym "end")))
`(do ((,end-name (+ (get-universal-time) ,seconds)))
((>= (get-universal-time) ,end-name))
,form
(sleep 1))))
查看其宏扩展:
CL-USER> (macroexpand-1 '(wait 10 (print 'test)))
(DO ((#:|end868| (+ (GET-UNIVERSAL-TIME) 10)))
((>= (GET-UNIVERSAL-TIME) #:|end868|))
(PRINT 'TEST)
(SLEEP 1))