Once you've come to terms with power of setf, it is time to meet its
older sister, cl-letf. As the name implies, letf is to setf like
let is to setq, but, once again, that is only the tip of the
iceberg.
To get started, let's have a variable and require the feature.
When temporarily assigning a value to a variable, letf is (mostly)
identical to let.
They differs slightly in behaviour when you don't provide a value.
let binds the variable to nil and restores it upon exit (as I'm sure
you know), while letf preserves the current value and restores it
upon exit.
Of course, that's not where letf shines. It's when you use place
expressions that it simply blows let out of the water. Let's take a
simple example using our list.
If you're having trouble reading past the three consecutive
parentheses, this snippet simply takes our list and temporarily
changes its first and fourth elements to 1000 and 200,
respectively.
“Alright, but how often is that actually useful?”
It all depends on your creativity. This stackoverflow question
highlights a common issue that came up with the release of Emacs 24.3.
flet (short for function-let) was a macro which locally (and
dynamically) replaced the function definition associated to given
symbols. This is extremely useful for error testing, but if you try to
use this macro now you'll get following the message.
Warning: `flet' is an obsolete macro (as of 24.3); use either `cl-flet' or `cl-letf'.
Unfortunately, cl-flet is not identical to the original
flet—it's lexical, not dynamic.
For instance, the url-retrieve-synchronously usually prints a
message on the echo area. Now say you want to prevent that, you can
temporarily rebind the message function to do nothing.
Now do M-x silent-retrieve, and see that it works.
Unfortunately, if you try to be a good coder and replace the obsolete
flet with the recommended cl-flet, it won't work!
letf as a replacement for flet
The solution I usually see floating around is to employ Nic Ferrier's
fantastic noflet package. But I've never seen anyone mention the
built-in option, even though Emacs itself tells you to use it: “use
either `cl-flet' or `cl-letf'”.
You see, (symbol-function SYMBOL) is a valid place expression. Which
means you can bind it dynamically using cl-letf. Evaluate the
following defun and call M-x new-silent-retrieve.
It works! No messaging! All that we've done was tell letf to
temporarily replace the message function with the format function
(which does the same thing without echoing). We could also use
ignore instead of format (the latter just happens to have the same
return value as message).
Understanding letf and how it replaces flet
31 Aug 2014, by Artur Malabarba.Common-Lisp in Emacs post series
Once you've come to terms with power of
setf
, it is time to meet its older sister,cl-letf
. As the name implies,letf
is tosetf
likelet
is tosetq
, but, once again, that is only the tip of the iceberg.To get started, let's have a variable and require the feature.
When temporarily assigning a value to a variable,
letf
is (mostly) identical tolet
.They differs slightly in behaviour when you don't provide a value.
let
binds the variable to nil and restores it upon exit (as I'm sure you know), whileletf
preserves the current value and restores it upon exit.Of course, that's not where
letf
shines. It's when you use place expressions that it simply blowslet
out of the water. Let's take a simple example using our list.If you're having trouble reading past the three consecutive parentheses, this snippet simply takes our list and temporarily changes its first and fourth elements to
1000
and200
, respectively.“Alright, but how often is that actually useful?”
It all depends on your creativity. This stackoverflow question highlights a common issue that came up with the release of Emacs 24.3.
flet
(short for function-let) was a macro which locally (and dynamically) replaced the function definition associated to given symbols. This is extremely useful for error testing, but if you try to use this macro now you'll get following the message.Unfortunately,
cl-flet
is not identical to the originalflet
—it's lexical, not dynamic.For instance, the
url-retrieve-synchronously
usually prints a message on the echo area. Now say you want to prevent that, you can temporarily rebind themessage
function to do nothing.Now do M-x silent-retrieve, and see that it works. Unfortunately, if you try to be a good coder and replace the obsolete
flet
with the recommendedcl-flet
, it won't work!letf as a replacement for flet
The solution I usually see floating around is to employ Nic Ferrier's fantastic noflet package. But I've never seen anyone mention the built-in option, even though Emacs itself tells you to use it: “use either `cl-flet' or `cl-letf'”.
You see,
(symbol-function SYMBOL)
is a valid place expression. Which means you can bind it dynamically usingcl-letf
. Evaluate the following defun and call M-x new-silent-retrieve.It works! No messaging! All that we've done was tell
letf
to temporarily replace themessage
function with theformat
function (which does the same thing without echoing). We could also useignore
instead offormat
(the latter just happens to have the same return value asmessage
).Update
ignore
.this-fn
feature is something you can't do withcl-letf
.Tags: lisp, emacs,
Emacs Lisp Style Guide »
« The ins and outs of setf
Related Posts
Eval-result-overlays in Emacs-lisp in lisp
Define context-aware keys in Emacs in lisp
Using prettify-symbols in Clojure and Elisp without breaking indentation in lisp
Content © 2019, All rights reserved. Icons under CC3.0.