difference between fret and cl-flet

Asked 2 years ago, Updated 2 years ago, 142 views

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

2022-09-29 22:41

2 Answers

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.


2022-09-29 22:41

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)))


2022-09-29 22:41

If you have any answers or tips


© 2024 OneMinuteCode. All rights reserved.