函数应用——Applicative 编程
Table of Contents
Applicative 是函数式编程中的一个概念,通过函数应用来完成工作,例如,把函数对象传递给其他函数。
1. 匿名函数
通过 lambda 来定义,例如,定义一个匿名函数,将参数乘以 10:
(lambda (n) (* n 10))
变量 n 是闭包在匿名函数中的,因为这个性质,再加上函数可以作为参数和返回值,因此就能实现函数 Currying:
(defun print-log (level text) (format t "[~A] ~A~%" level text)) (defvar print-err (lambda (text) (print-log "ERR" text))) (defvar print-info (lambda (text) (print-log "INFO" text))) (defvar print-debug (lambda (text) (print-log "DEBUG" text))) (funcall print-debug "debug...")
funcall 可以把传递的符号作为函数来调用。
2. map/mapcar/mapc
这几个函数都会将函数应用到一个或多个列表上。
mapcar:
(mapcar #'1+ '(1 2 3)) ; => (2 3 4) (mapcar #'+ '(1 2 3) '(4 5 6) '(2 2 2)) ; => (7 9 11)
mapc 则是没返回值的版本:
(mapcar (lambda (u) (format t "welcome: ~A~%" u)) '(user1 user2 user3)) ;; 打印: ;; welcome: USER1 ;; welcome: USER2 ;; welcome: USER3
而 map 函数需要指定返回类型,如下,将字符列表中每个字母转成大写,最后返回字符串:
(map 'string #'char-upcase (list #\h #\e #\l #\l #\o)) ; => "HELLO"
3. reduce
(reduce #'+ '(1 2 3)) ; => 6
4. remove-if/remove-if-not
对列表做一个“过滤操作”,在一些函数式编程语言中也被命名为“filter”。
remove-if 第一个参数是谓词函数,最后会删除返回为 T 的元素。例,过滤掉列表中的奇数:
(remove-if #'oddp '(1 2 3 4 5)) ; => (2 4)
remove-if-not 则相反:
(remove-if-not #'oddp '(1 2 3 4 5)) ; => (1 3 5)
5. find-if
传递一个谓词函数,返回第一个调用谓词函数结果为 T 的元素:
(find-if #'oddp '(2 4 6 7 8 9)) ; => 7
6. every/some
every:传递一个谓词函数,如果对列表中所有元素调用为 T,则返回 T:
(every #'plusp '(2 4 6 7 8 9)) ; => T,因为所有元素都大于 0 (every #'plusp '(2 4 6 7 8 9 0)) ; => NIL
some:只要其中一个为 T,就返回 T:
(some #'plusp '(-2 -1 0 1)) ; => T