You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

寻求可统计Lisp程序函数代码行数及递归包含函数数的工具

嘿,针对你要统计Lisp函数代码行数和递归包含函数数量的需求,我给你整理了实用的技术方案,分两部分来说:

一、统计Lisp函数的代码行数

这里有两种靠谱的思路,看你更偏向哪种场景:

  • 基于Lisp环境的自定义实现
    大多数Common Lisp实现(比如SBCL、CLISP)都提供了自省功能,可以直接获取函数的源代码。以SBCL为例,你可以写一个小函数来提取源码并统计有效行数(排除空行):

    ;; 需要先加载split-sequence库(多数环境默认已包含)
    (defun count-function-lines (target-func)
      (let* ((source-code (sb-introspect:function-source-code target-func))
             (code-string (format nil "~{~a~%~}" source-code))
             (lines (split-sequence:split-sequence #\Newline code-string)))
        (length (remove-if #'(lambda (line)
                               (string= (string-trim '(#\Space #\Tab #\Newline) line) ""))
                           lines))))
    

    如果用CLISP,把sb-introspect:function-source-code换成sys:function-lambda-expression即可,不同实现的自省API略有差异,查下对应文档就能调整。

  • 通用命令行工具
    如果你不想写Lisp代码,用cloc这个通用代码统计工具就很方便。直接在命令行运行:

    cloc your-lisp-file.lisp
    

    它会自动区分代码行、空行、注释行,还能按函数、文件等维度给出统计结果,支持多种Lisp方言。

二、统计顶层函数递归包含的函数数量

这里分静态分析(不运行代码)和动态分析(运行时追踪)两种方式,各有优劣:

  • 静态分析:遍历源码收集调用关系
    这种方法不需要运行程序,直接解析函数的源代码来收集所有被调用的函数(包括递归调用的)。你可以用代码遍历工具,或者自己写一个简单的遍历函数:

    (defvar *tracked-funcs* (make-hash-table :test #'eq))
    
    (defun walk-code (form)
      (cond
        ((consp form)
         ;; 检查是否是函数调用
         (when (and (symbolp (car form)) (fboundp (car form)))
           (setf (gethash (car form) *tracked-funcs*) t))
         ;; 递归遍历所有子形式
         (mapc #'walk-code form))
        (t nil)))
    
    (defun count-static-included-funcs (top-func)
      (clrhash *tracked-funcs*)
      ;; 获取顶层函数的源码并遍历
      (walk-code (sb-introspect:function-source-code top-func))
      ;; 返回去重后的函数数量
      (hash-table-count *tracked-funcs*))
    

    注意:静态分析会漏掉动态调用(比如(funcall some-var)这种带变量的调用),如果你的代码大量使用动态调用,这种方法就不太准确。另外,处理宏的话需要先展开宏,再分析展开后的代码(可以用macroexpand-1或者macroexpand)。

  • 动态分析:运行时追踪实际调用
    这种方法通过追踪函数的实际执行过程,记录所有被调用的函数,包括递归和动态调用的情况。以SBCL为例,你可以用内置的追踪功能实现:

    (defvar *called-funcs* (make-hash-table :test #'eq))
    
    (defun track-call (func &rest args)
      (declare (ignore args))
      (setf (gethash func *called-funcs*) t))
    
    (defun count-dynamic-included-funcs (top-func &rest func-args)
      (clrhash *called-funcs*)
      ;; 设置追踪钩子,记录所有调用
      (let ((trace-spec `(,top-func :entry (track-call ,top-func))))
        (unwind-protect
             ;; 运行顶层函数
             (apply top-func func-args)
          ;; 清理追踪
          (untrace top-func)))
      (hash-table-count *called-funcs*))
    

    这种方法更准确,但需要确保你的代码可以安全执行(比如没有副作用或者可以控制副作用)。

另外要提醒下:不同Lisp实现的自省和追踪API可能不同,比如CLISP的追踪用trace函数,参数格式略有差异,你可以根据自己使用的环境调整代码细节。

内容的提问来源于stack exchange,提问作者user2193970

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 08:15:25