Lisp笔记

2023-05-16

变量

动态变量

defvar defparameter

(dafvar *paraname* default-value
"Documentation"

defparameter始终赋值
defvar只初始化,且可以不赋值

动态变量和词法变量的不同

使用let形式操作动态变量会产生和词法变量不一样的效果
词法变量在声明函数时确定了作用域。即说的时候是几就是几,被调用时还是声明时那个作用域的值。
动态变量在调用函数时寻找调用语境的作用域。即用的时候看环境,包含动态变量的函数调用的作用域的值决定函数内这个变量的值。

(let ((y 2))
 (flet ((foo () y))
  (let ((y 3))
   (print (foo))) ;foo函数内的y取声明foo时的值
  (print (foo))))
------------------
2
2
(defvar *y* 1)
 (let ((*y* 2))
  (flet ((foo () *y*));*y*与声明时环境无关,取调用时所处环境的值
   (let ((*y* 3))
    (print (foo)))
   (print (foo))))
------------------
3
2

本质是foo函数中动态变量/特殊变量是像当前作用域寻找*y*这个值,而词法变量是向声明函数时y的作用域寻找该值。
窃以为如果foo是个宏,词法变量和动态变量会获得一样的效果。回头学了宏来试一试。

脑内解释

词法变量:因为值跟上下文的文本关系更强,与调用的环境无关。
动态变量:同样的函数在不同作用域下可能变现出不同值,叫动态变量合情合理。不适合称为全局变量。

常量

defconstant
+variablename+常量命名,不能被用于形参和重绑定

赋值

setf place value
setf place1 value1 place2 value2
返回最后赋予的值
(setf x (set y 10)) = 把复制给y的结果赋给x
Simple variable: (setf x 10)
Array: (setf (aref a 0) 10)
Hash table:(setf (gethash 'key hash) 10)
Slot named ‘field’: (setf (field o) 10)

修改宏

(incf x) = (setf x (+ x 1))
(incf x 10) = (setf x (+ x 10)
修改宏一般可以保证从左到右执行,保证参数和位置形式的子形式只被执行一次。

shiftf rotatef

(shiftf a b c)值向左传递,返回最左
(rotatef a b c)值向左传递,最右变量获得最左的值,返回nil

展开期(macro expansion time)
运行期(runtime)

(defmacro name (parameter*)
  "Optional documentation string."
  body-form*)

do

(do (variable-definition*)
(end-test-form result-form*)
statement*)

variable-definition

(var init-form step-form)

数字、字符、字符串、符号引用

#\a字符a
#\Space空格
'bar ->BAR单引号加字符串,如’bar,表示这个字符串的符号(symbol)对象。

集合

向量

#(a b c)#号打头的列表

集合操作

find
count
subsitute
position
remove
关键字
:test 类似于上述函数的-if版本,如count-if。
(count #\a #(a b c d e)) >1
(count #\a #(1 2 3 4 5) :test $'evenp) > 2
(count-if #'evenp #(1 2 3 4 5)) > 2
:key 对集合元素做一定提取,比如元素也是合集,可以用它提取选择提取哪个。
(count #\a #((a 10) (b 20) (c 30)) :key #'first)其中处理(a 10)时,就会提取第一个元素a和#\a进行对比。
:start
:end Num|Nil若指定Nil,则到末尾
:from-end T从后往前
:count在remove和substitute中,表示生效几次

合并

concatenate

(concatenate 'vector #(1 2 3) '(4 5 6)) -> #(1 2 3 4 5 6)
(concatenate 'list #(1 2 3) '(4 5 6)) -> (1 2 3 4 5 6)
(concatenate 'string "abc" '(#\d #\e #\f)) -> "abcdef"

merge (含排序)

(merge 'vector #(1 3 5) #(2 4 6) #'<) -> #(1 2 3 4 5 6)
(merge 'list #(1 3 5) #(2 4 6) #'<) -> (1 2 3 4 5 6)

排序

sortsort-stable
破坏性:改变参数

(setf my-sequence (sort my-sequence #'string<));如果不破坏得这样写
;rather than just this:
(sort my-sequence #'string<)

:key 关键字,提取的关键字只用于排序算法,而不是排序内容

子序列

(defparameter *x* (copy-seq "foobarbaz"))
(setf (subseq *x* 3 6) "xxx") ; subsequence and new value are same length
*x* -> "fooxxxbaz"
(setf (subseq *x* 3 6) "abcd") ; new value too long, extra character ignored.
*x* -> "fooabcbaz"
(setf (subseq *x* 3 6) "xx") ; new value too short, only two characters changed
*x* -> "fooxxcbaz"

mismatch

(mismatch "foobarbaz" "foom") -> 3
;It returns NIL if the strings match. MISMATCH also takes many of the standard keywordarguments: 
; a :key argument for specifying a function to use to extract the values to be compared;
; a :test argument to specify the comparison function; 
; :start1, :end1, :start2,and :end2 arguments to specify subsequences within the two sequences. 
; :from-end argument of T specifies the sequences should be searched in reverse order, causing MISMATCH to return the index, in the first sequence, where whatever common suffix the two sequences share begins.
(mismatch "foobar" "bar" :from-end t) -> 3;这个3仍然左起第3个

序列谓词

(every #'evenp #(1 2 3 4 5)) -> NIL
(some #'evenp #(1 2 3 4 5)) -> T
(notany #'evenp #(1 2 3 4 5)) -> NIL
(notevery #'evenp #(1 2 3 4 5)) -> T
;These calls compare elements of two sequences pairwise:
(every #'> #(1 2 3 4) #(5 4 3 2)) -> NIL
(some #'> #(1 2 3 4) #(5 4 3 2)) -> T
(notany #'> #(1 2 3 4) #(5 4 3 2)) -> NIL
(notevery #'> #(1 2 3 4) #(5 4 3 2)) -> T

映射

map
跟mathamatica的map一样的用法,给定一个谓词把n个序列的元素进行运算,返回一个新序列
*需要指定类型 'list or 'vecotr

(map 'vector #'* #(1 2 3 4 5) #(10 9 8 7 6)) -> #(10 18 24 28 30)

map-into
把返回结果放进第一个参数里(一个序列)
如果长度不统一以最短的为准

(map-into a #'+ a b c)

reduce
:initial-value 逻辑上提供一个第一位

(reduce #'+ #(1 2 3 4 5 6 7 8 9 10)) -> 55

哈希表

make-hash-table创建哈希表
hash的等价判断可以通过:test关键字传递,但仅接受EQUAL EQEQUALP

(defparameter *h* (make-hash-table))
(gethash 'foo *h*) -> NIL
(setf (gethash 'foo *h*) 'quux)
(gethash 'foo *h*) -> QUUX

GETHASH隐式地返回两个值,“值”和“是否存在”。与形参形式中(c Nil c-p)/(形参名 默认值 是否赋值)很像,用于判断是传值为Nil还是因为没有值才Nil
*多重返回值的工作方式决定,如果没有显示处理,额外返回值会被丢弃。即视为一个返回值。

(defun show-value (key hash-table)
  (multiple-value-bind (value present) (gethash key hash-table)
    (if present
      (format nil "Value ~a actually present." value)
      (format nil "Value ~a because key not found." value))))
(setf (gethash 'bar *h*) nil) ; provide an explicit value of NIL
(show-value 'foo *h*) -> "Value QUUX actually present."
(show-value 'bar *h*) -> "Value NIL actually present."
(show-value 'baz *h*) -> "Value NIL because key not found."

迭代

maphash两个参数

(maphash #'(lambda (k v) (format t "~a => ~a~%" k v)) *h*)

remhash 按key删除一个表格内容

(maphash #'(lambda (k v) (when (< v 10) (remhash k *h*))) *h*)

点对单元

(CAR . CDR)

(cons 1 2) -> (1 . 2)
(car (cons 1 2)) -> 1
(cdr (cons 1 2)) -> 2
;Both CAR and CDR are also SETFable places—given an existing cons cell, it’s possible toassign a new value to either of its values.3
(defparameter *cons* (cons 1 2))
*cons* -> (1 . 2)
(setf (car *cons*) 10) -> 10
*cons* -> (10 . 2)
(setf (cdr *cons*) 20) -> 20
*cons* -> (10 . 20)

列表就是点对单元单链表

(cons 1 nil) -> (1)
(cons 1 (cons 2 nil)) -> (1 2)
(cons 1 (cons 2 (cons 3 nil))) -> (1 2 3)

列表

多数列表函数使用函数式编写,这么做是有好处的,因为他们可以在返回结果中直接使用一部分实参。
比如append这样的函数用于链接2个列表,基于点对单元特征,可以把任意新列表的CDR连接到后者。

破坏性

基于上文提到的修改点对单元的操作,可能产生破坏参数的特征。只有当确认参数不在使用时,调用破坏性函数才是安全的。

(defparameter *list-1* (list 1 2))
(defparameter *list-2* (list 3 4))
(defparameter *list-3* (append *list-1* *list-2*))
;After evaluating these forms, you have three lists, but *list-3* and *list-2* share structure just like the lists in the previous diagram.
*list-1* -> (1 2)
*list-2* -> (3 4)
*list-3* -> (1 2 3 4)
;Now consider what happens when you modify *list-2*.
(setf (first *list-2*) 0) -> 0
*list-2* -> (0 4) ; as expected
*list-3* -> (1 2 0 4) ; maybe not what you wanted

破坏性 & 回收性

回收性函数
NREVERSENon-consing,不分配新的点对单元。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Lisp笔记 的相关文章

  • 突出显示 Lisp 表单的 Emacs 模式

    什么是 Emacs 模式或包 它突出显示 Lisp 表单 更改背景颜色 以便您所在的表单具有一种颜色 外部表单具有另一种颜色 外部表单具有另一种颜色 依此类推 你可能想尝试mwe 彩盒 http www foldr org michaelw
  • Common Lisp 中的动态和词法变量

    我正在读 Peter Seibel 的 Practical Common Lisp 一书 在第 6 章 变量 部分中 词法变量和闭包 和 动态 又名特殊变量 http www gigamonkeys com book variables h
  • 如何访问 cl-json 从 JSON 解码的对象?

    我正在尝试在 Common Lisp 中导入 JSON 我想出了如何从 JSON 字符串解码对象 但我不知道如何访问返回的对象的属性 要解码字符串 并将结果存储在 tempjson 中 我这样做 defun test json with i
  • Lisp 中的函数名可以有别名吗?

    就像包裹一样 我使用Emacs 也许 它可以提供某种解决方案 例如 defun the very very long but good name 稍后在代码中没有用处 但名字就像Fn 15或者第一个字母缩写也没有用 是否可以使用类似于包的别
  • Mathematica:未评估、延迟、保留、HoldForm、HoldAllComplete、等等

    我对所有旨在以某种方式阻止评估的内置 Mathematica 函数感到困惑 Unevaluated Defer Hold 以及超过六种形式Hold Mathematica 文档只是单独解释每个函数 而没有解释为什么选择其中一个函数 谁能对所
  • LISP - 小数点后的数字

    有谁知道如何在 Lisp 中指定浮点数小数点后的位数 假设我在 REPL 上打印此命令 CL USER 3 gt format t 15f float 1 7 I get 0 142857150000000 但是该数字四舍五入到小数点后第
  • LISP:关键字参数,提供-p

    目前我正在学习 Peter Seibel 的 Practical Common Lisp 在 实用 一个简单的数据库 一章中 http www gigamonkeys com book practical a simple database
  • 与 emacs/slime 的其他 Lisp/Scheme 实现等效的 'lein swank'

    我一直在使用 emacs slime 来编码 lisp 但是使用 Clojure 我发现了 lein swank 我必须说它非常有用 因为我可以连接到运行 clojure 的服务器 其他 Lisp 实现怎么样 哪些 Lisp 实现提供了与
  • 在lisp中,如何使用floor函数返回的第二个值?

    当我这样做时 4楼3 我得到了 1 1 3 但我该如何使用这 1 3 呢 例如 您可以使用将其绑定到变量multiple value bind multiple value bind quot rem floor 4 3 format t
  • 在 LISP 中使用“ash”执行二分查找?

    所以 我现在正在阅读 Land of Lisp 事实证明 Lisp 与我见过的其他编程语言有很大不同 无论如何 本书提供了一些我们要输入到 CLISP REPL 中的代码 defparameter small 1 defparameter
  • Scheme/Racket有枚举操作吗?

    Scheme Racket 是否有相当于 Haskell 中的 a b 表示法的枚举表示法 在 Haskell 中 1 5 计算结果为列表 1 2 3 4 5 for list i in range 1 6 i sequence gt li
  • Common Lisp 中的 LET 与 LET*

    我理解 LET 和 LET 并行绑定与顺序绑定 之间的区别 并且作为理论上的问题 它非常有意义 但有没有什么情况你曾经真正需要过 LET 在我最近查看的所有 Lisp 代码中 您可以将每个 LET 替换为 LET 而无需进行任何更改 编辑
  • 防止 LISP 中的终端输出

    我想运行一个函数 但不让它在终端中输出结果 例如 set A B 正常返回B在控制台中如下所示 gt gt gt set A B B gt gt gt A B 我不希望它返回任何东西 我仍然希望该函数能够完成它应该做的事情 只是默默地 gt
  • Common Lisp 类型声明未按预期工作

    当我在 Common Lisp 中定义一个函数时 如下所示 defun foo n declare type fixnum n n 42 我期待一个像这样的电话 foo a 立即失败 但在调用时失败 是个declareform 不保证静态类
  • elisp:有没有办法获取当前 .el 模块的名称(如 C 中的 __FILE__ )?

    在我的 elisp 模块的顶部 我想做一些简单的事情 message concat Loading expand file name current elisp module 您可以使用变量load file name https www
  • let* 和 set 之间的区别?在 Common Lisp 中

    我正在从事一个基因编程爱好项目 我有一个函数 宏设置 当以 setq setf 形式评估时 将生成一个如下所示的列表 setq trees make trees 2 gt x abs x 然后它将绑定到 lambda 函数
  • 为什么在基于 Lisp 的语言中习惯上将许多右括号放在一行上?

    通常代码如下所示 one thing another thing arg1 f arg5 r another thing arg1 f arg5 r 为什么不喜欢这样 one thing another thing arg1 f arg5
  • 使用包阴影符号

    例如 我有这个包定义 它遮蔽了 COMMON LISP LISTEN defpackage shadows use common lisp shadow listen export listen 然后我想使用另一个包中的这个包 比如说 de
  • 解决斐波那契数列的 Lisp 方法

    我想尝试学习 Lisp 但很快就放弃了 我想我会再试一次 我正在看 求 400 万以下所有偶数斐波那契数的总和 我写了下面的代码 它可以工作 但是很丑陋 其中最主要的是它太慢了 因为它一直在进行简单的递归 当我用 Python 编写这个程序
  • gensym 在 Lisp 中做什么?

    我听到一些同学谈论他们如何使用该功能gensym为此 我问他们它做了什么 甚至在网上查了一下 但我真的无法理解这个函数的作用是什么两者都不为什么或何时最好使用它 特别是 我对它在 Lisp 中的作用更感兴趣 谢谢你们 独特且未被拘禁的符号

随机推荐