c - 将 C 中的局部静态变量翻译成 Common Lisp

标签 c opencv static common-lisp

考虑来自 OpenCV Tutorial 8 - Chapter 9 的这段 C 代码

// Learn the background statistics for one more frame
void accumulateBackground( IplImage *I ){
    static int first = 1;
    cvCvtScale( I, Iscratch, 1, 0 );
    if( !first ){
        cvAcc( Iscratch, IavgF );
        cvAbsDiff( Iscratch, IprevF, Iscratch2 );
        cvAcc( Iscratch2, IdiffF );
        Icount += 1.0;
    }
    first = 0;
    cvCopy( Iscratch, IprevF );
}

看起来代码的设计方式是因为

if( !first )

程序永远不会执行:

cvAcc( Iscratch, IavgF );
cvAbsDiff( Iscratch, IprevF, Iscratch2 );
cvAcc( Iscratch2, IdiffF );
Icount += 1.0;

在 Lisp 中,我试图将其翻译为:

(defun accumulate-background (i)
  (setf 1st 1)
  (cvt-scale i i-scratch-1 1 0) ;; To float
  (if (not 1st) 
      (progn (acc i-scratch-1 i-avg-f)
             (abs-diff i-scratch-1 i-prev-f i-scratch-2)
             (acc i-scratch-2 i-diff-f)
             (setf i-count (+ i-count 1.0))))
  (setf 1st 0)
  (copy i-scratch-1 i-prev-f))

对于等效函数,(not 1st) 用于 !first,我认为这是正确的。 在 C++ 中,我这样做:

static int first = 1;

if( first ){
  cout << "reached this part of code " << endl << " " << first << endl << endl;
} 

但由于代码设计的原因,似乎永远不会产生任何输出。为什么教程代码的设计者会这样?他正在从学习 OpenCV 中复制。

最佳答案

C 代码中的变量firststatic,这意味着它只有一个实例,并且在所有实例之间共享对函数的调用。 (有关 C 中的 static 的更多信息,请参阅 What does "static" mean? 的已接受答案。)这有点像拥有一个全局变量,只是其他函数无法访问它(因为它不是在他们的范围内)。您可以使用用 defvardefparameter 定义的全局变量在 Common Lisp 中对此进行模拟,但我认为更直接的翻译将通过包装整个defunlet 中。

首先,让我们看一下具有相似结构的东西。此代码在第一次 时执行某些操作,但不会在后续调用中执行:

(let ((firstp t))
  (defun frob (bar)
    (when firstp
      (print 'initialized)
      (setf firstp nil))
    (print (list 'frobbed bar)))
    nil)

现在,当我们第一次运行它时,firstp 为真,所以我们将在输出中看到initialized,但是后续运行,我们不会:

CL-USER> (frob 'bar3)
INITIALIZED            ; printed output
(FROBBED BAR3)         ; printed output
;=> NIL

CL-USER> (frob 'bar5)
(FROBBED BAR5)         ; printed output
;=> NIL

您获得的 C 代码实际上在每次调用时都执行某些操作, 第一次调用除外。您也可以将其表述为“除非是第一次,否则请做某事”。那里的“除非”意味着暗示unless,你可以用它来稍微清理一下你的代码。除了 let-wrapping-defun 和适当的缩进,我们还有:

(let ((first t))
  (defun accumulate-background (i)
    (cvt-scale i i-scratch-1 1 0) ;; To float
    (unless first
      (acc i-scratch-1 i-avg-f)
      (abs-diff i-scratch-1 i-prev-f i-scratch-2)
      (acc i-scratch-2 i-diff-f)
      (setf i-count (+ i-count 1.0)))
    (setf first nil)
    (copy i-scratch-1 i-prev-f)))

关于c - 将 C 中的局部静态变量翻译成 Common Lisp,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19062562/

相关文章:

c - 二维数组内存映射 C

c - 将大数放入数组中

c++ - 使用opencv将RGB图像转换为一维数组

c++ - 是否可以在 C 程序中使用 C++ 库函数?

c - C 中的快速排序递归函数 - 不适用于大量元素

opencv - 用我自己的库打包opencv库

使用 openCV 和 openCL 的 Android Studio 应用程序

c# - 使用单例避免静态变量

variables - 常量和静态变量有什么区别,我应该选择哪个?

Java:使用字符串进行静态访问?