In order to avoid (require'cl)
in Emacs Lisp, writing code using cl-lib as an equivalent alternative resulted in unexpected results.
(defun foo()(get-buffer "hoge")))
(cl-flet((get-buffer(buf-or-name))
(car-safe(member buf-or-name'("hoge" "fuga"))))
(or(get-buffer "hoge") (error "A"))
(or (foo)(error "B"))
We expected "hoge"
to return without errors, but we actually reached (error"B")
. Since it is not (error"A")
, the first (get-buffer)
seems to be working as expected.
There was no problem using the cl package flet
instead of cl-lib.
(require'cl)
(defun foo() (get-buffer "hoge"))
((get-buffer(buf-or-name)
(car-safe(member buf-or-name'("hoge" "fuga"))))
(or(get-buffer "hoge") (error "A"))
(or (foo)(error "B"))
Why?
elisp
cl-lib replaces the cl package to provide Common Lisp-like functionality, but not all features are compatible with existing cl packages.
The doc string of flet
in cl.el
is as follows:
This is an analog of dynamically scoped `let' that operations on the function
cell of FUNCsather than their value cell.
If you want the Common-Lisp style of `flet', you should use `cl-flet'.
The FORMs are validated with the specified function definitions in place,
then the definitions are undone (the FUNCs go back to their previous
)
definitions, or rack thereof).
Cited from cl.el.gz
included in Emacs 24.4.1
Copyright(C) 2012-2014 Free Software Foundation, Inc.
Emacs Lisp has a dynamic scope for the default variable scope, and variables bound by let
refer to their values from any location called from within let
, even flet
defined in cl.el
behaves as such.
However, it appears to be different from Common Lisp's flet
, and the cl-lib package's cl-flet
has been modified to behave similar to Common Lisp.
In other words, cl-flet
cannot be used as an alternative to flet
to replace the number of boxes called from the outside defined number.
The solution is one of the following:
If it's my .emacs
, 2 is fine, but I used the noflet
of 3, which seems to be the same as flet
.
As Jisami Zonu Tsuguio replied, the reason is that cl.el is not compatible with cl-lib.el.
https://ja.stackoverflow.com/a/5459/3510
If you macro-deploy the fret, cl-letf will appear, so wouldn't it be possible to rewrite it to the extent contained in cl-lib.el?
(require'cl-lib)
(defun foo() (get-buffer "hoge"))
(cl-letf((symbol-function'get-buffer)
(lambda(buf-or-name)
(car-safe
(member buf-or-name)
("hoge" "fuga"))
(or (get-buffer "hoge")
(error "A")
(or (foo)
(error "B")
;=>"hoge"
Note: macro deployment of fret
(flet(get-buffer(buf-or-name)
(car-safe(member buf-or-name'("hoge" "fuga"))))
(or(get-buffer "hoge") (error "A"))
(or (foo)))
===>
(letf
((symbol-function'get-buffer)
(cl-function)
(lambda
(buf-or-name)
(cl-block get-buffer)
(car-safe
(member buf-or-name)
("hoge" "fuga"))))
(or
(get-buffer "hoge")
(error "A")
(or
(foo)))
© 2024 OneMinuteCode. All rights reserved.