Ron*_*Ron 4 emacs elisp function
今天我尝试编写一个elisp函数,除了在函数返回nil时不断抛出的错误外,一切正常.这是功能:(请原谅格式化,我不确定如何缩进它.)
(defun byte-is-readable (byte)
"Determine whether BYTE is readable or not.
Returns t or nil."
(if (and (<= byte 126) (>= byte 32)) t nil))
;; Read the 100 bytes of a file
;; If 10 in a row are not 'readable', it is safe to assume the file is a binary
(defun is-file-binary (file)
"Determine whether FILE is a binary file.
Returns t or nil."
(let* ((i 1)
(c 0)
(size (nth 7 (file-attributes file)))
(lim (if (< size 100) size 100)))
(while (< i lim)
(let ((char (with-temp-buffer
(insert-file-contents file)
(buffer-substring i (+ i 1)))))
(if (not (byte-is-readable (aref char 0)))
(setq c (+ c 1))
(setq c 0))
(if (= c 10) (return t)))
(setq i (+ i 1))))
nil)
Run Code Online (Sandbox Code Playgroud)
这样调用它:(message "%s" (if (is-file-binary "/path/to/some/file") "true" "false")返回true时工作文件,但抛出"if:no catch for tag: - cl-block-nil--,t"返回nil时.我猜这是因为没有正确评估nil或其他东西.
我如何解决它?
小智 5
该错误来自您return在代码中使用的事实.这是一个宏,在其他一些cl宏的上下文中只有有意义的扩展,例如loop.
我会鼓励你使用loop而不是while因为它允许隐藏无趣的实现细节,如柜,throw- catch机制等,但是,如果你想为任何理由使用while的方法,从破while环是使用:
(catch 'label (while <condition> ... (throw 'label <result>)))
Run Code Online (Sandbox Code Playgroud)
使用的代码版本loop.
(defun byte-readable-p (byte)
"Determine whether BYTE is readable or not.
Returns t or nil."
(cl-case byte
((?\n ?\r ?\t) t)
(otherwise (and (<= byte 126) (>= byte 32)))))
(defun file-binary-p (file)
"Determine whether FILE is a binary file.
Returns t or nil."
(with-temp-buffer
(insert-file-contents file)
(cl-loop for c across
(buffer-substring-no-properties
1 (min 100 (buffer-size)))
thereis (not (byte-readable-p c)))))
(file-binary-p (expand-file-name "~/.emacs"))
nil
(file-binary-p (expand-file-name "~/.emacs.d/elpa/w3m-20131021.2047/w3m.elc"))
t
Run Code Online (Sandbox Code Playgroud)
或者,甚至更短的版本,使用高阶函数:
(defun file-binary-p (file)
"Determine whether FILE is a binary file.
Returns t or nil."
(with-temp-buffer
(insert-file-contents file)
(cl-find-if-not 'byte-readable-p
(buffer-substring-no-properties
1 (min 100 (buffer-size))))))
Run Code Online (Sandbox Code Playgroud)
请注意,传统上在Lisp代码函数中返回布尔值(通常称为"谓词")是使用以下方案命名的:<word>p或者<word>-<word>-p更确切地说is-<word>.