小编dav*_*ugh的帖子

Common Lisp对函数的引用

在Common Lisp中引用函数似乎有许多不同的方法:

  1. 通过符号,其中符号出现(未引用)作为形式的汽车(1+ 2) => 3,或在功能参数位置(mapcar '1+ '(1 2 3)) => (2 3 4);

  2. 通过功能对象,其中,所述(解释或编译)函数对象可以出现在函数自变量的位置中(mapcar #'1+ '(1 2 3)) => (2 3 4)或(mapcar (symbol-function '1+) '(1 2 3)) => (2 3 4),而不是作为一种形式如在车上(#'1+ 2) => error或((symbol-function '1+) 2) => error;

  3. 通过lambda表达式,其中lambda表达式显示为lambda形式的汽车((lambda (x) (1+ x)) 2) => 3,或者在函数参数位置中显示(mapcar (lambda (x) (1+ x)) '(1 2 3)) => (2 3 4)[但是,Hyperspec不会将lambda表达式识别为"函数指示符"].

在这三种"方式"中,对我而言,第一种似乎有些不合适,因为它似乎使Common Lisp运算符仅仅评估其参数一次的基本准则复杂化.如果在上面的示例'1+中进行评估,它将生成符号1+ …

lambda function common-lisp

2
推荐指数
1
解决办法
384
查看次数

使用`once-only`宏

在实用Common Lisp的第8章末,Peter Seibel展示了once-only宏观.其目的是通过用户定义的宏中的变量评估来缓解一些微妙的问题.注意我在这一点上并没有试图理解这个宏如何工作,就像在其他一些帖子中一样,但是如何正确使用它:

(defmacro once-only ((&rest names) &body body)
  (let ((gensyms (loop for n in names collect (gensym))))
    `(let (,@(loop for g in gensyms collect `(,g (gensym))))
      `(let (,,@(loop for g in gensyms for n in names collect ``(,,g ,,n)))
        ,(let (,@(loop for n in names for g in gensyms collect `(,n ,g)))
           ,@body)))))
Run Code Online (Sandbox Code Playgroud)

以下是一个示例(不正确)设计宏,试图展示几个变量评估问题.它声称通过某个delta迭代一系列整数,返回范围:

(defmacro do-range ((var start stop delta) &body body)
  "Sample macro with faulty variable evaluations."
  `(do ((,var ,start (+ ,var ,delta))
        (limit …
Run Code Online (Sandbox Code Playgroud)

macros common-lisp practical-common-lisp

2
推荐指数
1
解决办法
175
查看次数

如何正确指定可调向量的元素类型

以下是旨在用作(lifo)堆栈或(fifo)队列的结构

(defstruct jvector
  (vector (make-array 0 :adjustable t :fill-pointer 0) :type (array * (*)))
  (start 0 :type (integer 0 *)))
Run Code Online (Sandbox Code Playgroud)

内容的范围从jvector-start到jvector-vector填充指针。我希望能够用类似的东西指定内容的元素类型

(defun create-jvector (&key (element-type t))
  (make-jvector :vector (make-array 0 :element-type element-type :adjustable t :fill-pointer 0)
                :start 0))
Run Code Online (Sandbox Code Playgroud)

并用

(defun push-jvector (elt jvec)
  (vector-push-extend elt (jvector-vector jvec)))
Run Code Online (Sandbox Code Playgroud)

但是,create-jvector中的元素类型将被忽略。例如,

* (defparameter v (create-jvector :element-type 'integer))
V
* v
#S(JVECTOR :VECTOR #() :START 0)
* (push-jvector 1 v)
0          ;OK result
* v
#S(JVECTOR :VECTOR #(1) :START 0)
* (push-jvector 'a v) …
Run Code Online (Sandbox Code Playgroud)

types common-lisp adjustable-array

2
推荐指数
1
解决办法
82
查看次数

符号平等

他说,在Paul Graham的书" ANSI Common Lisp"中,他讨论了符号与字符串操作

符号可以一步比较eql......"

(P138).以下是符号比较的两种情况:

(setq x 3)
3
(setq a 'x)
X
(setq b 'x)
X
(eq a b)
T
Run Code Online (Sandbox Code Playgroud)

因此,由于a和b指向相同的符号对象,名为X,因此它们是eq.然而,这与之形成鲜明对比

(setq a (copy-symbol 'x))
#:X
(setq b (copy-symbol 'x))
#:X
(symbol-name a)
"X"
(symbol-name b)
"X"
(eq a b)
NIL
(eql a b)
NIL
(equal a b)
NIL
(equalp a b)
NIL
Run Code Online (Sandbox Code Playgroud)

现在,a和b指向不同的符号对象,即使它们具有相同的符号名称和相同的打印名称.我的问题是:

  1. 为什么格雷厄姆说eql而不是eq,而且
  2. 在第二种情况下,为什么a和b至少不是equalp?

symbols common-lisp

1
推荐指数
1
解决办法
750
查看次数

无损设定?

Common Lisp似乎竭尽全力提供非破坏性功能(如subst和remove)和破坏性功能以及修改宏(如delete和rotatef)以供一般使用.据推测,这是为了有效地支持功能和非功能的编程风格.但是在无处不在的设计中似乎也存在对非功能性风格的特殊偏见setf.setf包含通用引用的宏显然足够灵活,可以修改任何可指定的位置(除了可能的不可变整数和字符).尽管其无功能/破坏性行为,但这种力量可能是其广泛使用的原因.

问题是为什么没有相应的"功能样式"非破坏性操作符,后面的图案setf(称之为put,因为set已经采用),类似于其他非破坏性/破坏性的lisp操作符对.这样的运算符可能会使用相同的参数,一个位置和一个值,但会返回嵌入了该位置的对象的副本,而不是该位置的新值.它也可能涉及某种通用复印机,标准setf只是在返回之前修改副本.然后可以使用非破坏性运算符代替setf大多数分配,并setf为大型对象保留.鉴于通用复印机的(推测)要求以及从嵌入其中的任意位置恢复物体的需要,这样的操作者是否可行(甚至可能)?

functional-programming common-lisp setf

1
推荐指数
1
解决办法
185
查看次数

在多线程代码(通用Lisp)中使用库函数

当可以从多个线程访问/更新变量时,通常需要保护它免受同时更改的影响。一种有效的方法是使用原子函数来保证互斥访问。例如(sb-ext:atomic-incf *count*)。另一种方法是像这样围绕更新操作包装一个锁(bt:with-lock-held (*lock*) (incf *count*)),但这有点昂贵。

有没有一种有效的方法可以在多线程代码中包含库函数(例如来自亚历山大图书馆)?例如,如果 (alexandria:deletef x *list*)要从多个线程中执行操作?还是需要锁?(ps:我假设a deletef需要保护,但不能完全确定。)

multithreading locking common-lisp shared-libraries

1
推荐指数
1
解决办法
80
查看次数

调整Common Lisp“ pushnew”以返回成功/失败

Common Lisp宏pushnew返回作为参数给出的(可能已更新)位置列表。看来,如果您想知道给定的项目是否实际被推送,则需要比较放置前和放置后列表以查看其是否已更改。但这对于我的使用来说效率太低,因为它将涉及重复比较两个复杂结构对象的列表以得出等效结果。

另一种可行的替代方法是使用:test参数来pushnew记录是否已找到该项目,因为已扫描列表元素。如果找到该项目,则可以将T作为第二个整数值返回,否则返回NIL。下面的宏尝试执行此操作:

(defmacro pushnew+p (item place &key test (key #'identity) &aux old?)
  "Same as pushnew, but also returns whether item was pushed."
  `(values (pushnew ,item ,place
                    :test (lambda (item element)
                            (if ,test
                              (setf old? (funcall ,test item element))
                              (setf old? (eql item element))))
                    :key ,key)
           (not old?)))
Run Code Online (Sandbox Code Playgroud)

似乎工作正常,因为

(defparameter x '(1 2 3))

(pushnew+p 0 x) -> (0 1 2 3), T

(pushnew+p 2 x) -> (0 1 2 3), NIL

(defparameter y '((1) (2) …
Run Code Online (Sandbox Code Playgroud)

macros common-lisp anonymous-function

1
推荐指数
1
解决办法
65
查看次数

编译 Lambda 表达式时 SBCL 中的细微编译器警告

我需要一些帮助来理解编译 lambda 表达式时出现的 SBCL 编译器警告消息。lambda 表达式临时存储为用户定义名称的符号值,编译后的函数随后存储在名称的符号函数下。

* (compile nil (symbol-value 'activate-connector-if!))
; in: LAMBDA (STATE ?CONNECTOR)
;     (APPLY #'SOME
;            (LAMBDA (WOULDWORK-PKG::?T1 WOULDWORK-PKG::?T2)
;              (AND
;               (GETHASH (+ 126 # #)
;                        (WOULDWORK-PKG::PROBLEM-STATE.IDB WOULDWORK-PKG::STATE))
;               (GETHASH (+ 126 # #)
;                        (WOULDWORK-PKG::PROBLEM-STATE.IDB WOULDWORK-PKG::STATE))
;               (LET (#)
;                 (WHEN VALUES #))
;               (LET (#)
;                 (WHEN VALUES #))
;               (NOT (EQL WOULDWORK-PKG::$HUE1 WOULDWORK-PKG::$HUE2))))
;            NIL NIL)
; --> MULTIPLE-VALUE-CALL SB-C::%FUNCALL SOME LET BLOCK SB-INT:DX-FLET FLET
; --> #:WRAPPER102 BLOCK LET
; …
Run Code Online (Sandbox Code Playgroud)

sbcl common-lisp compiler-warnings

1
推荐指数
1
解决办法
41
查看次数

在 Common Lisp 中使用包作为哈希表

最初将大量符号存储在一个包中(与项目包分开),并有效地将其用作项目可访问的哈希表(其中键表示简单的集合成员资格数据)是否可行?

* (defpackage :project (:use :cl))
#<PACKAGE "PROJECT">

* (defpackage :temp (:use :cl))
#<PACKAGE "TEMP">

* (in-package :project)
#<PACKAGE "PROJECT">

* (intern "ABC" :temp)
TEMP::ABC
NIL

* (find-symbol "ABC" :temp)
TEMP::ABC
:INTERNAL

;The following is not needed for this project, but is available

* (setf (symbol-value (find-symbol "ABC" :temp)) 123)
123

* (symbol-value (find-symbol "ABC" :temp))
123
Run Code Online (Sandbox Code Playgroud)

这似乎可行,但是有充分的理由避免并仅使用哈希表来代替吗?我的第一个想法是避免使用大量杂项键符号使项目包变得混乱。这些符号将在运行时从字符串生成(以检查哈希表中的集合成员资格)。这似乎涉及许多符号的运行时驻留,这些符号可能存储在表中,也可能不存储在表中。但我也想知道是否find-symbol可以比gethash. 或者,我可以只使用equal字符串的哈希表,但查找的绝对数量似乎指向eq而不是equal。寻找任何明智的建议,谢谢。

编辑:将equal哈希表与包符号查找进行比较的简单测试。

一、哈希表测试

* (defun random-string (n)
  "Generate a random …
Run Code Online (Sandbox Code Playgroud)

hashtable sbcl common-lisp package

1
推荐指数
1
解决办法
94
查看次数

Common Lisp 中结构的 :print-function 和 *print-readously* 之间的干扰?

我正在尝试将一个常见的 Lisp 结构以可读的方式打印到一个文件中,以便稍后可以将其读回。SBCL 似乎有一些相当复杂的内置工具,用于以可读方式打印复杂对象,这可以避免编写专门的打印对象方法。

我的结构是否有可能:print-function干扰*print-readably*?

(defstruct (problem-state (:conc-name problem-state.) (:print-function print-problem-state) (:copier nil))
  "A planning state including the current propositional database."
  (name nil :type symbol)  ;last action executed
  (instantiations nil :type list)  ;from last action effect
  (happenings nil :type list)  ;a list of (object (next-index next-time next-direction)) pairs
  (time 0.0 :type real)
  (value 0.0 :type real)
  (heuristic 0.0 :type real)
  (idb (make-hash-table) :type hash-table)  ;integer hash table of propositions
  (hidb (make-hash-table) :type hash-table))  ;integer table for …
Run Code Online (Sandbox Code Playgroud)

hashtable sbcl common-lisp writefile data-structures

1
推荐指数
1
解决办法
123
查看次数