用 autolisp 实现 racket 函数这个事情,之前写过一篇 blog, 记录的函数不是很多,远远不及SRFI 1的函数数量。这回再补充一些,不一定能写多少个,反正补一点算一点。

xcons

函数xcons 接受 2 个参数,将第 2 个参数 cons 到第 1 个参数,这个函数用作解决想要cons但是形参顺序不对的问题。

1
2
3
(defun xcons (x y)
  ;; 作者:徐工, 微博:@徐工徐工2020,头条:@徐工徐工
  (cons y x))

make-list

函数make-list 接受 2 个参数,第 1 个参数为整数,它返回 1 个 list,这个 list 的元素是第 2 个参数,list 的元素个数等于第 1 个参数。 比如,(make-list 4 'c) => (c c c c)

1
2
3
4
5
(defun make-list (n x / o)
  ;; 作者:徐工, 微博:@徐工徐工2020,头条:@徐工徐工
  (if (<= 1 n)
    (repeat n
      (setq o (cons x o)))))

list-tabulate

函数list-tabulate 接受 2 个参数,第 1 个参数 n 为整数,第 2 个参数 f 为函数符号,它返回 1 个 list, 这个 list 的元素是(f i) (0 <= i < n)的值。

比如,(list-tabulate 3 '1+) => (1 2 3)

1
2
3
4
5
6
7
8
9
(defun list-tabulate (n init-proc / i o)
  ;; 作者:徐工, 微博:@徐工徐工2020,头条:@徐工徐工
  (if (< 0 n)
    (progn
      (setq i 0)
      (repeat n
        (setq o (cons (apply init-proc (list i)) o)
              i (1+ i)))))
  (reverse o))

iota

函数iota 接受 3 个参数,第 1 个参数 n 为整数,第2、3参数为数值,它返回 1 个 list,这个 list以第2参数为首元素,后续元素 等于前一个元素加第3个参数。

比如,(iota 5 0 -0.1) => (0 -0.1 -0.2 -0.3 -0.4)

1
2
3
4
5
6
7
8
(defun iota (count start step / o) 
  ;; 作者:徐工, 微博:@徐工徐工2020,头条:@徐工徐工
  (if (<= 1 count) 
    (progn 
      (setq o (list start))
      (repeat (1- count) 
        (setq o (cons (+ step (car o)) o)))
      (reverse o))))

concatenate 函数

函数concatenate 就是 (apply 'append list-of-lists)

1
2
3
(defun concatenate (lst) 
  ;; 作者:徐工, 微博:@徐工徐工2020,头条:@徐工徐工
  (apply 'append lst))

append-reverse 函数

函数append-reverse 就是 先reverseappend

1
2
3
(defun append-reverse (rev-head tail)
  ;; 作者:徐工, 微博:@徐工徐工2020,头条:@徐工徐工 
  (append (reverse rev-head) tail))

一点体会

包括Racket/scheme/lisphaskellF#clojure在内的函数式编程语言,常常会有各种各样的短小精悍的函数, 这些函数功能不一、数量众多,这差不多能算是函数式编程的一种特色了。之所以会出现这样的情况,是因为大家习惯于不断地提炼、 把各种常用的高频操作转变成函数,这既是一种思维方式,也是一种积极运用语言能力书写代码的方式。

UNIX 也推崇这种化整为零的方法论。