15.2 函数 recursive-graph-body-print

函数 graph-body-print 也可以使用递归的方式来实现。递归解决方案分为两部分:一个外部包装器,它使用 let 表达式确定一些变量的值,这些变量只需找到一次,例如图形的最大高度;以及一个内部函数,该函数被递归调用以打印图形。

外部包装器比较简单:

(defun recursive-graph-body-print (numbers-list)
  "打印 NUMBERS-LIST 的条形图。"
  (let ((height (apply 'max numbers-list))
        (symbol-width (length graph-blank))
        from-position)
    (recursive-graph-body-print-internal
     numbers-list
     height
     symbol-width)))

递归函数稍微复杂一些。它分为四个部分:再次执行测试、打印代码、递归调用和下一步表达式。再次执行测试是一个 when 表达式,用于确定 numbers-list 是否包含任何剩余元素;如果包含,则该函数使用打印代码打印图的一列,并再次调用自身。函数再次调用自身的依据是下一步表达式产生的值,该值导致调用作用在 numbers-list 的较短版本上。

(defun recursive-graph-body-print-internal
  (numbers-list height symbol-width)
  "打印条形图,在 recursive-graph-body-print 函数中使用。"

  (when numbers-list
        (setq from-position (point))
        (insert-rectangle
         (column-of-graph height (car numbers-list)))
        (goto-char from-position)
        (forward-char symbol-width)
        (sit-for 0)     ; 逐列绘制图形。
        (recursive-graph-body-print-internal
         (cdr numbers-list) height symbol-width)))

安装完成后,可以测试此表达式;以下是一个示例:

(recursive-graph-body-print '(3 2 5 6 7 5 3 4 6 4 3 2 1))

这是 recursive-graph-body-print 生成的结果:

                *
               **   *
              ****  *
              **** ***
            * *********
            ************
            *************

这两个函数之一,graph-body-printrecursive-graph-body-print,都可以创建图形的主体。