博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Common Lisp学习笔记(七)
阅读量:6682 次
发布时间:2019-06-25

本文共 6280 字,大约阅读时间需要 20 分钟。

7 Applicative Programming

7.2 funcall

(funcall #'cons 'a 'b) -> (a . b)

funcall可以通过函数名字来调用函数

lisp里面引用函数使用符号#'

再看一个例子,

> (setf fn #'cons)#
> (funcall fn 'c 'd)(c . d)
7.3 mapcar

mapcar可以将一个函数应用到一个list中的每一个元素中,然后将每次返回的结果全部放到一个list中返回

(defun square (n) (* n n))(square 3) -> 9(square '(1 2 3)) -> error(mapcar #'square '(1 2 3) -> (1 4 9)
7.4 manipulating tables with mapcar

(mapcar #'function-name list)

现在有一张英语和法语的转换表

(setf words  `((one un)    (two deux)    (three trois)    (four quatre)    (five cinq)))

获取所有list的第一个item:

> (mapcar #'first words)(one two three four five)

ex 7.1

(defun add1 (x) (+ x 1))> (mapcar #'add1 '(1 3 5 7 9)
7.5 lambda expressions

(lambda (n) (* n n))

在使用mapcar的时候如果不想另外定义一个函数,可以直接在mapcar函数里面定义匿名函数lambda

> (mapcar #'(lambda (n) (* n n)) '(1 2 3)(1 4 9)

ex 7.7

(defun flips (x)   (mapcar #'(lambda (n) (if (equal n 'up) 'down 'up)) x))
7.6 find-if

(find-if #'predicate list)

对list中的每个item调用predicate,返回第一个返回值是t的item,没有返回t的就返回nil

> (find-if #'oddp '(2 4 6 7 8))7
7.7 my-assoc

assoc函数有2个参数(key table),返回在table中第一个元素是key的那个list

现在可以用find-if来写一个assoc功能的函数

(defun my-assoc (key table)  (find-if #'(lambda (entry) (equal key (first entry))) table))

对于table中的每个list,我们定义的lambda函数要判断key是否等于这个list的第一个元素,如果想等就返回t,而find-if函数只要lambda函数返回t就将那个list返回,刚好可以实现assoc函数的功能

要注意的一点,例子中lambda函数可以访问定义在my-assoc函数中的局部变量key,说明lambda函数可以包含这个lambda函数的外层函数的local vars

ex 7.8

(defun foo (x k)   (find-if #'(lambda (n) (if (< n (- k 10)) nil (<= n (+ k 10)))) x))

ex 7.9

(defun find-nested (x)  (find-if #'(lambda (entry) (and (listp entry) (not (equal entry nil)))) x))
7.8 remove-if, remove-if-not

(remove-if #'function-name list)

对于list中的每个元素都调用函数进行判断,如果为t就将其删除,返回剩下的list

> (remove-if #'numberp '(2 for 1 sale)(for sale)

remove-if-not则相反,如果函数返回为nil就将该元素删除

> (remove-if-not #'(lambda (x) (> x 3)) '(2 3 4 5 6))(4 5 6)

ex 7.15

(defun rank (x) (first x))(defun suit (x) (second x))(setf my-hand `((3 hearts) (5 clubs) (2 diamonds) (4 diamonds) (ace spades)))(defun count-suit (suit hand)   (length (remove-if-not #'(lambda (entry) (equal suit (second entry))) hand)))(setf colors '((clubs black) (diamonds red) (hearts red) (spades black)))(defun color-of (x)   (second (assoc (second x) colors)))(defun first-red (hand)  (find-if #'(lambda (card) (equal 'red (color-of card))) hand))(defun black-cards (hand)  (remove-if-not #'(lambda (card) (equal 'black (color-of card))) hand))(defun what-ranks (suit hand)  (mapcar #'first (remove-if-not #'(lambda (card) (equal suit (second card))) hand)))(setf all-ranks '(2 3 4 5 6 7 8 9 10 jack queen king ace))(defun higher-rank-p (card1 card2)  (member (first card1) (rest (member (first card2) all-ranks))))(defun high-card (hand)  ;;建立一个rank的list(ace king queen jack 10 ... 2),使用find-if对这个list的rank逐个查找是否出现在hand中  ;;(mapcar #'first hand)可以得到hand中所有的rank的list  (assoc (find-if #'(lambda (rank) (member rank (mapcar #'first hand))) (reverse all-ranks)) hand))
7.9 reduce

(reduce #'function list)

reduce函数对list不断进行操作直到只剩一个结果,如对一个list使用加法相当与对list中的所有因素求和

比如list是(a b c d),则先计算a b的结果,再用这个结果与c运算,得到的结果再与d运算,最后剩下一个结果

其中function必须是有两个参数的,eg,

(reduce #'+ '(1 2 3)) -> 6(reduce #'* '(2 3 4)) -> 24

reduce可以将嵌套的list变为一个list,eg,

> (reduce #'append '((one un) (two deux) (three trois)))(one un two deux three trois)

ex 7.17

(defun total-length (x)  (reduce #'+ (mapcar #'length x)))
7.10 every

(every #'predicate list)

如果list中的所有元素都使得predicate返回t则函数返回t,意思就是对于每一个list中的因素都成立,否则返回nil,eg,

> (every #'numberp '(1 2 3))t

如果第二个参数是nil,则every返回t

every后面也可以给多个list,eg,

> (every #'> '(10 20 30 40) '(1 4 11 23))t

>函数需要两个参数,every每次从后面的两个list中各取出一个作为参数,如例子中10>1,20>4,30>11,40>24都成立,所以返回t

debug tool: trace
  • (trace func1 func2 ...)
  • (trace) : 查看正在trace的函数
  • (untrace func1 func2 ...)
  • (untrace) : untrace所有函数
(defun half (n) (* n 0.5))(defun average (x y)  (+ (half x) (half y)))> (trace half average)(half average)> (average 3 7)1. Trace: (AVERAGE '3 '7)2. Trace: (HALF '3)2. Trace: HALF ==> 1.52. Trace: (HALF '7)2. Trace: HALF ==> 3.51. Trace: AVERAGE ==> 5.05.0

ex 7.29

(setf database   '((b1 shape brick)    (b1 color green)    (b1 size  small)    (b1 supported-by b2)    (b1 supported-by b3)    (b2 shape brick)    (b2 color red)    (b2 size small)    (b2 supports b1)    (b2 left-of b3)    (b3 shape brick)    (b3 color red)    (b3 size small)    (b3 supports b1)    (b3 right-of b2)    (b4 shape pyramid)    (b4 color blue)    (b4 size large)    (b4 supported-by b5)    (b5 shape cube)    (b5 color green)    (b5 size large)    (b5 supports b4)    (b6 shape brick)    (b6 color purple)    (b6 size large)))    (defun match-element (x y)  (or (equal x y) (equal y '?)))(defun match-triple (assertion pattern)  (every #'match-element assertion pattern))(defun fetch (pattern)  (remove-if-not #'(lambda (entry) (match-triple entry pattern)) database))> (fetch '(b4 shape ?)) > (fetch '(? shape brick))> (fetch '(b2 ? b3))> (fetch '(? color ?))> (fetch '(b4 ? ?))(defun ask-color (block)  (list block 'color '?))(defun supporters (block)  (mapcar #'first  (fetch (list '? 'supports block))))(defun supp-cube (block)  (find-if #'(lambda (entry) (fetch (list entry 'shape 'cube))) (supporters block)))(defun desc1 (block)  (remove-if-not #'(lambda (entry) (equal block (first entry))) database))(defun desc2 (block)  (mapcar #'rest (desc1 block)))(defun description (block)  (reduce #'append (desc2 block)))(setf (cdr (last database)) '((b1 material wood) (b2 material plastic)))
7.11 operating on multiple lists

之前我们使用mapcar是将一个list的每个item作为参数调用一个函数,这个函数只接受一个参数。其实mapcar也可以对多参数的函数使用,eg,

> (mapcar #'(lambda (x y) (list x 'get y)) '(fred wilma) '(job1 job2))((fred gets job1) (wilma gets job2))> (mapcar #'+ '(1 2 3) '(10 20 30 40))(11 22 33)

这种方式类似于前面的every后面跟多个list,如果两个list的长度不一样,则遍历完较短那个就会停止

ex 7.30

(mapcar #'append words (mapcar #'list '(uno dos tres quatro cinco)))
7.12 function函数

'代表函数quote,#'则代表函数function,#'cons等价与(function cons)

> 'conscons> #'cons#
> #'(lambda (x) (...))#

#'返回的是一个函数对象,可以用funcall来进行调用

> (setf g #'(lambda (x) (* x 10)))#
> (funcall g 12)120
7.13 kwargs for applicative operators

:from-end等关键字参数也可以应用在find-if,remove-if,reduce这些函数

> (reduce #'cons '(a b c d e))((((a . b) . c) . d) . e)> (reduce #'cons '(a b c d e) :from-end t)(a b c d . e)

转载于:https://www.cnblogs.com/jolin123/p/4484033.html

你可能感兴趣的文章
设计模式(5)--单例模式
查看>>
pitch yaw roll是什么
查看>>
深浅copy
查看>>
Hibernate之一级缓存
查看>>
Python基础之定义有默认参数的函数
查看>>
iOS5中的UUID
查看>>
(转载)XML Tutorial for iOS: How To Read and Write XML Documents with GDataXML
查看>>
poj 3259 Wormholes
查看>>
py学习之道
查看>>
o(1)复杂度之双边滤波算法的原理、流程、实现及效果。
查看>>
python中requests模块使用
查看>>
git bash 常用命令 新手学习
查看>>
最短路径
查看>>
POJ题目(转)
查看>>
day28 classmethod 装饰器
查看>>
QName
查看>>
Java使用线程并发库模拟弹夹装弹以及发射子弹的过程
查看>>
程序员找不女朋友的原因
查看>>
C#编程之“串口通讯多次接收”
查看>>
【python 文件操作】python 文件操作
查看>>