小编xie*_*pan的帖子

SBCL do-symbols(和循环)返回重复项

我发现SBCL'do-symbols'(和循环)返回重复项.

测试环境:Windows上的SBCL 1.1.4 x86

首先,我们定义一些辅助函数:

;; compress from Ansi-Common-Lisp
(defun compress (x)
  (labels ((rec (e x n)
             (if (null x)
                 (if (= 1 n)
                     (list e)
                     (list (list e n)))
                 (if (eq e (car x))
                     (rec e (cdr x) (1+ n))
                     (cons (if (= 1 n)
                               e
                               (list e n))
                           (rec (car x)
                                (cdr x)
                                1))))))
    (rec (car x) (cdr x) 1)))

(compress '(a a b c d d d))
;;=> ((A 2) B C (D 3))

;; This one …
Run Code Online (Sandbox Code Playgroud)

common-lisp package

6
推荐指数
2
解决办法
186
查看次数

common-lisp中有关可选参数的错误

SBCL 64位,1.1.7

如果我想创建一个包并使用包中的一些小符号:CL,我将创建一个像这样的包:

(defpackage :foo
  (:import-from :cl 
                :defun :defmacro :in-package
                :null :car :cdr :cons :if
                :eq))
Run Code Online (Sandbox Code Playgroud)

但是,在这个包中,如果我定义一个带有可选参数的函数并在不提供可选参数的情况下调用它,我总会得到一个错误:

(defun test (&optional a))

(test)

invalid number of arguments: 0
   [Condition of type SB-INT:SIMPLE-PROGRAM-ERROR]

Restarts:
 0: [RETRY] Retry SLIME interactive evaluation request.
 1: [*ABORT] Return to SLIME's top level.
 2: [REMOVE-FD-HANDLER] Remove #<SB-IMPL::HANDLER INPUT on descriptor 10: #<CLOSURE (COMMON-LISP:LABELS SWANK-BACKEND::RUN :IN SWANK-BACKEND:ADD-FD-HANDLER) {100490B95B}>>
 3: [ABORT] Exit debugger, returning to top level.
Run Code Online (Sandbox Code Playgroud)

定义宏得到相同的错误,但有更多信息:

(defmacro test (&rest body))

(test)

error while parsing arguments to DEFMACRO …
Run Code Online (Sandbox Code Playgroud)

sbcl common-lisp optional-arguments ansi-common-lisp

5
推荐指数
2
解决办法
753
查看次数

为什么它有这么多缺点?

当我在 SBCL (2.3.5) 中运行以下代码时,我对消耗的字节数感到惊讶。

(defun number-of-digits (num)
  (do ((n 1 (1+ n))
       (num (floor num 10) (floor num 10)))
      ((zerop num) n)))

(defun p25 ()
  (do ((a 0 (+ a b))
       (b 1 a)
       (n 0 (1+ n)))
      ((>= (number-of-digits a) 1000) n)))
Run Code Online (Sandbox Code Playgroud)
(time (p25))
Evaluation took:
  0.890 seconds of real time
  0.888141 seconds of total run time (0.878463 user, 0.009678 system)
  [ Run times consist of 0.004 seconds GC time, and 0.885 seconds non-GC time. ]
  99.78% CPU
  1,864,981,440 …
Run Code Online (Sandbox Code Playgroud)

lisp sbcl common-lisp

5
推荐指数
2
解决办法
124
查看次数

是否可以将字节向量传递给 C 函数而不在 SBCL 中复制

我正在尝试使用 SBCL 的 FFI 工具调用 C 函数。C 函数需要字节缓冲区(无符号字符)并处理字节数据。不幸的是,在大多数情况下,缓冲区非常大。我想知道我是否已经有一个 Lisp 字节向量(simple-array元素类型为 '(unsigned-byte 8)),是否可以将其传递给 C 函数,而不是分配外来缓冲区并在那里复制字节。我认为这是一个经常出现的场景,也许 SBCL 团队已经涵盖了这一点。

我查看了 SBCL 手册,它只指出sb-alien:c-string类型可以直接传递给 C 函数而不进行复制,并且它要求字符为“base-char”(在 0 ~ 127 范围内,支持 unicode)。我们也可以在不复制的情况下传递字节向量,这不是很好吗?

sbcl common-lisp ffi

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

迷茫的宏定义

我想在SICP第3.5.1节中实现延迟流

首先,我定义了这两个功能

(defmacro delay (form)
  `(lambda () ,form))

(defun force (form)
  (when form
    (funcall form)))
Run Code Online (Sandbox Code Playgroud)

当我们打电话:

(force (delay '(+ 1 2)))
;;=> (+ 1 2)

(force (delay (+ 1 2)))
;;=> 3
Run Code Online (Sandbox Code Playgroud)

这样才有用.然后我继续定义`stream-cons',但这次似乎有两种方式:

(defmacro stream-cons (a b)
  `(cons ,a ,(delay b)))

(defmacro stream-cons (a b)
  `(cons ,a (delay ,b)))
Run Code Online (Sandbox Code Playgroud)

我不认为他们是不同的,但我错了!第一版,这是一个错误的版本,当被称为:

(force (cdr (stream-cons 'a (progn (print "hello") 2))))
;;=> (PROGN (PRINT "hello") 2)

(macroexpand '(stream-cons 'a (progn (print "hello") 2)))
;;=> (CONS 'A #<CLOSURE (LAMBDA # :IN STREAM-CONS) {25ABB3A5}>)
Run Code Online (Sandbox Code Playgroud)

和第二版,这是正确的,当被称为: …

macros common-lisp sicp lazy-sequences

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

如何提高在Common Lisp中逐行读取大文件的速度

最近,我有一个任务要处理一个大文件,文件大小为460MB,包含5777672行。当我使用linux内置命令'wc'计算文件行号时,速度很快:

time wc -l large_ess_test.log
5777672 large_ess_test.log

real    0m0.144s
user    0m0.052s
sys     0m0.084s
Run Code Online (Sandbox Code Playgroud)

然后,我使用以下代码计算Common Lisp(SBCL 1.3.7 64位)中的行号

#!/usr/local/bin/sbcl --script
(defparameter filename (second *posix-argv*))
(format t "nline: ~D~%"
        (with-open-file (in filename)
          (loop for l = (read-line in nil nil)
             while l
             count l)))
Run Code Online (Sandbox Code Playgroud)

结果令我感到失望,因为与“ wc”命令相比,它确实很慢。我们只计算行号,即使没有任何其他操作:

time ./test.lisp large_ess_test.log
nline: 5777672

real    0m3.994s
user    0m3.808s
sys     0m0.152s
Run Code Online (Sandbox Code Playgroud)

我知道SBCL提供了C函数接口,通过它我们可以直接调用C过程。我相信如果直接调用C函数,性能将会提高,因此我编写了以下代码:

#!/usr/local/bin/sbcl --script
(define-alien-type pointer (* char))
(define-alien-type size_t  unsigned-long)
(define-alien-type ssize_t long)
(define-alien-type FILE*   pointer)

(define-alien-routine fopen FILE*
  (filename c-string)
  (modes    c-string))

(define-alien-routine fclose …
Run Code Online (Sandbox Code Playgroud)

io performance sbcl common-lisp

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

ASDF 抛出系统过时情况

我在脚本文件中使用ASDFload 。cl-ppcre问题是(progn (require :asdf) (require :cl-ppcre))在顶层完全没问题,但如果将相同的代码包装在 a 中handler-casesystem-out-of-date则会捕获一个条件handler-case,并且整个评估停止,并且不会加载所需的包。我只是确认 REPL 中也发生了同样的问题。无论我尝试加载哪个库,同样的问题都会发生在handler-case. 以下是完整的会话:

; SLIME 2.27
CL-USER> (require :asdf)
NIL
CL-USER> (find-package :cl-ppcre)
NIL
CL-USER> (handler-case (require :cl-ppcre) (t (c) (format t "~a: ~a~%" (type-of c) c)))
SYSTEM-OUT-OF-DATE: system cl-ppcre is out of date
NIL
CL-USER> (find-package :cl-ppcre)
NIL
CL-USER> (require :cl-ppcre)
NIL
CL-USER> (find-package :cl-ppcre)
#<PACKAGE "CL-PPCRE">
CL-USER> (handler-case (require :cl-ppcre) (t (c) (format t "~a: ~a~%" …
Run Code Online (Sandbox Code Playgroud)

sbcl common-lisp asdf

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

在 Common Lisp 中获取当前函数名称

我知道这超出了标准,但是在具体实现中是否有官方方法来获取当前函数名称,例如 SBCL?有时我想将当前函数名称放入日志消息中。我相信如果有一个一致的方法来获取当前的函数名称,它会使维护代码变得更容易,至少我不必每次更改函数名称时都更改日志消息。

目前我正在 defun 周围使用包装宏

(defmacro defun2 (name (&rest args) &body body)
  `(defun ,name (,@args)
     (let ((fun-name ',name))
       ,@body)))

(defun2 foo (x y)
  (format nil "fun ~a: x is ~a, y is ~a~%"
          fun-name x y))
Run Code Online (Sandbox Code Playgroud)

但我很想知道是否有更简单的方法。

function common-lisp

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