Replacing a string with symbols using font-lock? - elisp

I'm trying to make a font lock hook to replace strings of text for a mathmatical notation plugin.
So I'm thinking " / " (note the spaces) will turn into " ÷ ", but "/" won't. (It's a package mainly for R statistical language.)
I'm playing with the examples from the manual and I can't even get that to work lol. I was trying to get the word FIXIT to change font color.
(add-hook 'emacs-lisp-mode-hook
(lambda ()
(font-lock-add-keywords nil
'(("\\<\\(FIXIT\\):" 1
font-lock-warning-face t)))))
I don't even fully understand the syntax since I'm just getting used to lisp. Does it use a RegEx to identify strings? and if so, what RegEx engine.
I was hoping it would change the font color, but it didnt... but again, that was just me playing with it trying to understand it, not the end goal. The end result would be the first thing I mentioned to change math symbols.

As far as your example is concerned: Perhaps you're missing the ":" after FIXIT? Try pasting
;; FIXIT: needs work
into an elisp buffer with your hook enabled, it should work.
As far as regular expressions are concerned, their syntax is detailed in the user manual under Regexps and in the Elisp manual under Syntax of Regexps.
I'm not too sure whether font-lock can actually help in your case. One way to change displayed text would be to use Text Properties, specifically the Display Property. The following code changes all slashes to "÷" if surrounded by spaces.
(while (re-search-forward " \\(/\\) " nil t)
(put-text-property (match-beginning 1)
(match-end 1)
'display "÷"))
However, unlike font-lock, which applies fonts as text changes, this would be "permanent" until the text is deleted or the property changed. If fonts could do the same (e.g. via a display property of the font itself), you might find yourself lucky, otherwise you'll have to find a workaround that is not reimplementing font-lock.
Edit: It turns out, that you can use jit-lock-register to run your own fontification functions. Based on observations made by inspecting the source of glasses-mode I've written a minor mode that does what you want as a proof of concept. It uses overlays rather than text properties, because those are easier to remove.
(defun make-divisions-fancy (beg end)
(save-excursion
(save-match-data
(goto-char beg)
(while (re-search-forward " \\(/\\) " end t)
(let ((overlay (make-overlay (match-beginning 1)
(match-end 1)
nil t)))
(overlay-put overlay 'category 'fancy-divide)
(overlay-put overlay 'evaporate t)
(overlay-put overlay 'display "÷"))))))
(defun make-divisions-boring (beg end)
(dolist (o (overlays-in beg end))
(when (eq (overlay-get o 'category) 'fancy-divide)
(delete-overlay o))))
(defun remake-fancy-divisions (beg end)
(make-divisions-boring beg end)
(make-divisions-fancy beg end))
(define-minor-mode fancy-div-mode
"Minor mode to make divisions like \" / \" fancier."
:init-value nil
(save-excursion
(save-restriction
(widen)
(make-divisions-boring (point-min) (point-max))
(if fancy-div-mode
(jit-lock-register 'remake-fancy-divisions)
(jit-lock-unregister 'remake-fancy-divisions)))))

Related

Is it possible to get FORMAT to ignore undefined format directives?

I wonder if it is possible to tell FORMAT to ignore undefined format directives. I have looked at the pages for FORMAT in the CLHS but I don't see anything.
What I am trying to do is to get FORMAT to ignore ~m in a format string and just output ~m instead of trying to replace it with something. My plan is that at that point I will call another function which knows what to do with with ~m.
I guess a related question is then, is there a way to define a function to handle a format directive which is otherwise not defined?
In anticipation of some questions. (1) I guess a workaround would be to substitute a placeholder for ~m, and then substitute it back in afterwards and keep going. I guess I'll do that if all else fails. (2) I guess another general strategy would be to call the other function first, to handle ~m, then call FORMAT on the result. Unfortunately that other function recognizes some of the same directives, and barfs on others; it doesn't recognize only ~m and ignore everything else.
You can define your own format directive with ~/name/, where name is the name of the function which is called. In your case you would have:
(format t "~/m/" 1)
(defun m (stream n colon-mod at-mod)
(format stream "~a" n)) ; or do something else with n
You still need to change the control string, but you can add a preprocessing step where "~m" is replaced by "~/m/".
I don't think there is a way of doing that portably (implementations may let you do all sorts of magic). I'd write a quote-weird-tildes and dequote-weird-tildes pair of functions and then write code like:
(defun format/qw (control &rest args)
(declare (dynamic-extent args)
(type string control)) ;can't be a function
(dequote-weird-tildes
(apply #'format nil (quote-weird-tildes control) args)))
Now you have a function which looks like (format nil ...) and is no harder to use than that. For extra value the quoting and dequoting functions should not cons a string if they don't have to.
From http://www.lispworks.com/documentation/lw50/CLHS/Body/22_c.htm
The control-string argument to format is actually a format control.
That is, it can be either a format string or a function, for example a
function returned by the formatter macro.
So you can do:
(defmacro frmt (control-string)
(let ((str (cl-ppcre:regex-replace-all "~m" control-string "~~m")))
`(formatter ,str)))
Now:
(format t (frmt "~m~A") 1)
outputs:
~m1
NIL
This way you don't have to modify the control string directly.
You do have to modify the call to format to include frmt.

Null value in Mit-Scheme?

Can anyone tell me what is the null value representation in mit-scheme? In the SICP book, it should be "nil" but it doesn't work.
Thanks.
'() should work. Basically, nil in scheme is the empty list, so quoting an empty list gives you nil.
There is the history.
visit http://web.archive.org/web/20070808004043/http://wiki.wordaligned.org/sicp/published/FrequentlyAskedQuestions
Original(broken): http://wiki.wordaligned.org/sicp/published/FrequentlyAskedQuestions
Text from the above FAQ (in case of Internet Archive breakage):
Why isn’t “nil” working?
The quick answer is: nil is no longer part of Scheme, use '() instead. The long answer follows…
Early examples in Chapter 2 use nil as a list terminator, but when these examples are run using (e.g.) MIT Scheme, you get:
;Unbound variable: nil
Similarly, using () or null in place of nil may work on some implementations, but neither is portable. The Wizard Book addresses the issue in this footnote
It’s remarkable how much energy in the standardization of Lisp dialects has been dissipated in arguments that are literally over nothing: Should nil be an ordinary name? Should the value of nil be a symbol? Should it be a list? Should it be a pair? In Scheme, nil is an ordinary name, which we use in this section as a variable whose value is the end-of-list marker (just as true is an ordinary variable that has a true value). Other dialects of Lisp, including Common Lisp, treat nil as a special symbol. The authors of this book, who have endured too many language standardization brawls, would like to avoid the entire issue. Once we have introduced quotation in section 2.3, we will denote the empty list as ‘() and dispense with the variable nil entirely.
Since this was written, nil has been excised from the Scheme standard—but the bottom line holds: use ‘(), not nil. In an email to the accu-sicp list, Mike notes:
It’s a troublesome thing, this nil/null/'() business. Scheme48 and
scm don't define null, and guile defines it but as a procedure akin to
common lisp's null (to go with its nil which behaves like cl's nil,
which itself is distinct from '()—maybe this had something to do
with fsf's plans to re-do emacs in guile). I think the best bet is to
replace the authors’ use of nil with ‘().
[Copied with just a touch of typographical clean up, to better match Markdown and usual ASCII input into the languages/implementations in question.]
I use MIT/GNU Scheme microcode 15.3, () and '() all works. (as you said, nil and null doesn't work).
1 ]=> ()
;Value: ()
1 ]=> '()
;Value: ()
1 ]=> (cons 1 ())
;Value 2: (1)
1 ]=> (cons 1 '())
;Value 3: (1)
(list ) '() and () can represent null. for example,
(define (transpose mat) (accumulate-n cons () mat))
or substitute () with '() or (list ).

Should the behaviour of a function depend on the name of its variable?

Here is a short elisp code which shows that the behaviour of a function depends on the name of its variable. Is this a bug?
A function is declared using a variable x. When that function is called with a variable named anything other than x, it works as expected. But if it is called with a variable named x, it fails!
My system is GNU Emacs 22.2.1 (powerpc-apple-darwin8.11.0, Carbon Version 1.6.0) of 2008-04-05 on g5.tokyo.stp.isas.jaxa.jp
Paste this on an emacs buffer, put the cursor after the last parehthesis and press \C-x\C-e to see that the function make-zero does now work correctly when called the second time.
(progn
(defun make-zero (x)
"Simple function to make a variable zero."
(set x 0))
(setq x 10)
(insert "\n Variable x is now equal to " (number-to-string x))
(setq y 20)
(insert "\n Variable y is now equal to " (number-to-string y))
(insert "\n\n Let us apply make-zero to y")
(make-zero 'y)
(insert "\n Variable y is now equal to " (number-to-string y))
(insert "\n\n Let us apply make-zero to x")
(make-zero 'x)
(insert "\n Variable x is now equal to " (number-to-string x))
(insert "\n\n Why make-zero had no effect on x? Is it because the name of the
variable in the definition of make-zero, namely 'x', is the same as the name of
the variable when make-zero was called? If you change the name of the variable
in the definition of make-zero from x to z, this strange behaviour will
disappear. This seems to be a bug in elisp."))
It's not a bug so much as the nature of Elisp's (and Lisp in general) dynamic binding. ' doesn't pass a reference (that is, it's not like & in C/C++), it passes an unevaluated symbol; what it then evaluates to depends on the scope in which it's evaluated, which means it gets the x that's in scope inside the function.
In Lisp-think, the normal way around this would be to use a macro.
(defmacro make-zero (x) (list 'set x 0))
or
(require 'cl)
(defmacro make-zero (x) `(set ,x 0))
It's not a bug. It'd be worth your while reading the manual entry for Scoping Rules For Variable Bindings.
The function you wrote calls set, which takes a symbol (the value of the first argument) and changes its value to the value of the 2nd argument. The make-zero you wrote binds x locally to its input argument, so when you pass in the symbol x, set changes the first binding for x it finds, which happens to be the local binding.
Here's a different example, let's say you just had the following:
(defun print-something (something)
(set 'something "NEW VALUE")
(insert something))
(print-something "OLD") ; inserts "NEW VALUE"
Looking at that snippet of code, does it make sense that the set line changes the local value of something?
It doesn't matter whether or not there's a global setting for the symbol something.
Another example is the following:
(defvar x "some global value") ;# could have used setq here
(let ((x "local binding"))
(set 'x "new value"))
Which binding would you expect the set line to change? The one created by the let or the global one created by defvar?
The function you wrote is (pretty much) doing exactly the same thing as the let, you're creating a local binding for a variable which is seen before the global one.
If you want to pass around a reference to a variable then the only safe way to do that is via macros, which I recommend, but not until you've grasped the basics of lisp (b/c macros are definitely more complicated). That said, don't let me stop you from diving into macros if that's your passion.
A good introduction to programming Emacs lisp can be found here.
geekosaur's answer does a nice job of showing how you'd achieve what you want.

How do I disable warnings in lisp (sbcl)

How do I disable all warnings in sbcl? The extra output is rather annoying.
After much faffing about
and slogging through documentation written by people who are apparently allergic to simple concrete examples
(which seems to be most documentation for most things)
I think all you need to do to disable all warnings
is add this line in your .sbclrc file:
(declaim (sb-ext:muffle-conditions cl:warning))
To disable only style-warnings, it's:
(declaim (sb-ext:muffle-conditions cl:style-warning))
I tried to disable specifically the warning that comes up if you enter eg (setq x 1) at a fresh REPL
; in: SETQ X
; (SETQ X 1)
;
; caught WARNING:
; undefined variable: X
;
; compilation unit finished
; Undefined variable:
; X
; caught 1 WARNING condition
By using this:
(declaim (sb-ext:muffle-conditions sb-kernel:redefinition-warning))
but it didn't work,
(apparently redefinition-warning means something else)
and I can't find what it should be.
I guessed sb-kernel:undefined-warning
but that doesn't exist.
Using a macro
Also,
in regards #Bogatyr's answer
(using a macro to automatically run defvar)
and #spacebat's comment
(that the macro evaluated the value twice)
I have this to say:
As another newb coming across this,
I wanted to make demo showing that the macro evals twice,
and showing a version that evaluates only once.
(
I originally edited it in at the end of the question
but it was rejected because:
"This edit was intended to address the author of the post and makes no sense as an edit. It should have been written as a comment or an answer."
Well, you can't answer an answer,
but comments can't take blocks of code,
so I guess I should put it here instead?
)
original
(defmacro sq (var value)
`(progn
(defvar ,var ,value)
(setq ,var ,value)))
(sq v (princ "hi"))
side-effects: prints hihi
return value: "hi"
rewrite 2 - only evals once, always runs defvar
(defmacro sq2 (var value)
(let
((value-to-set value))
`(progn
(defvar ,var)
(setq ,var ,value-to-set))))
(sq2 v (princ "hi"))
side-effects: prints hi
return value: "hi"
rewrite 3 - same as above, but trickier to read
I used value-to-set for clarity,
but you could just use value again with no problems:
(defmacro sq3 (var value)
(let
((value value))
`(progn
(defvar ,var)
(setq ,var ,value))))
(sq3 v (princ "hi"))
rewrite 4 - only runs defvar if the variable is unbound
Running those macros will always define the variable before setting it,
so if v was already "bound" but not "defined"
(ie you had introduced it with setq)
then won't get any more error messages when you use the variable,
or reset it with setq.
Here's a version of the macro
that only runs defvar if the variable is not already bound:
(defmacro sq4 (var value)
(let
((value-to-set value))
(if (boundp var)
`(setq ,var ,value-to-set)
`(progn
(defvar ,var)
(setq ,var ,value-to-set)))))
(sq4 v (princ "hi"))
So if you use it to set a variable that is bound but not defined
it will keep giving you error messages.
(Which is maybe a good thing?
Like, for the same reason-I-don't-actually-know-why the error message exists in the first place.)
[
Also,
I tested the macro on these:
(sq4 value 1 )
(sq4 value 'value )
(sq4 value 'value-to-set )
(sq4 value 'var )
(sq4 value-to-set 1 )
(sq4 value-to-set 'value )
(sq4 value-to-set 'value-to-set )
(sq4 value-to-set 'var )
(sq4 var 1 )
(sq4 var 'value )
(sq4 var 'value-to-set )
(sq4 var 'var )
(You know, checking I hadn't screwed up and... done something weird.)
The ones where I tried to use var as a variable spewed errors.
At first I thought I had messed something up,
but it's actually just reserved for something special in SBCL(?) itself.
(defvar var) gets:
; debugger invoked on a SYMBOL-PACKAGE-LOCKED-ERROR in thread
; #<THREAD "main thread" RUNNING {AB5D0A1}>:
; Lock on package SB-DEBUG violated when globally declaring VAR SPECIAL while
; in package COMMON-LISP-USER.
; See also:
; The SBCL Manual, Node "Package Locks"
So... when in doubt, avoid using the symbol var, I guess.
]
this is what i use to muffle both compile-time and runtime (load-time) redefinition warnings:
(locally
(declare #+sbcl(sb-ext:muffle-conditions sb-kernel:redefinition-warning))
(handler-bind
(#+sbcl(sb-kernel:redefinition-warning #'muffle-warning))
;; stuff that emits redefinition-warning's
))
following this pattern you can install these handlers on superclasses like cl:style-warning to muffle all style warnings.
You can either use SB-EXT:MUFFLE-CONDITIONS as Pillsy said, the other alternative is to read through the warnings and use them to modify your code to remove the warnings. Especially if they're actually warnings (rather than, say, optimization notes).
I couldn't get SB-EXT:MUFFLE-CONDITIONS to work for the highly annoying undefined variable warning even after much googling. That warning drives me nuts when experimenting at the REPL, so I did what all the books suggest we should do: extend lisp to suit my needs/preferences!
I wrote my own setq that shut up the sbcl warnings, my first macro ever :). I'm sure there are better ways to do it but this works great for me, and it's going right into my ~/.sbclrc!
(defmacro sq (var value)
`(progn
(defvar ,var ,value)
(setq ,var ,value)))
You probably want to look at SB-EXT:MUFFLE-CONDITIONS.
If warnings are all you care about you can set:
(setf sb-ext:*muffled-warnings* 'style-warning)
This will only apply to style warnings and allow other warnings and conditions to print out. Any warning that shares the same parent will be automatically muffled.
For me (and probably others), most of the warnings were actually being piped to stdErr.
So this silenced the annoying output:
sbcl 2>/dev/null/
Alternatively, you can pipe to a file.
sbcl 2>myTempLog.txt
When starting sbcl, the problem is that at least in my configuration, alexandria spews out a tonne of method warnings and redifining warnings because of asdf, alexandria and readline, regardless of the mute solutions.
User theoski's solutions (sbcl 2>/dev/null ...) totally work to get rid of those, but at the expense of warnings that might actually be useful.
Still, I always have a repl open in a terminal as a scratch for quick hacks and experimenting, and it's a LOT nicer not seeing that avalanche when loading it up.

Lisp Parentheses

Why do Lispers format their code like shown in sample 1 instead of as shown in sample 2? To me (and I guess, to most others coming from different programming backgrounds than Lisp), the formatting shown in sample 2 would be easier to read. Is there any particular reason why Lispers prefer the sample 1 style?
Sample 1
(defun factorial (n)
(if (<= n 1)
1
(* n (factorial (- n 1)))))
Sample 2
(defun factorial (n)
(if (<= n 1)
1
(* n (factorial (- n 1)))
)
)
LISP IDE environments tend to balance parentheses automatically and manage indents based on nesting level. Sample 2 does not bring any advantages in those situations.
In the C/FORTRAN/Pascal heritage, you tend to emphasize sequencing over nesting (code parse trees are shallower and wider). End of scope is a more significant event in your code: hence emphasis has been and still to some extent is more important.
For experienced Lisp users, the nesting level is more important than finding closing parentheses. Putting closing parentheses on their own lines does not really help with nesting levels.
The basic idea is that the parentheses are directly AROUND their contents.
(a)
and not
(a
)
What follows is this:
(defun foo (bar)
(foo (bar (baz
...
)
...
)
...
)
)
vs.
(defun foo (bar)
(foo (bar (baz ...) ...) ...))
One of the basic ideas when editing Lisp text is, that you can select a list by (double-) clicking on the parentheses (or by using a key command when the cursor is inside the expression or on the parentheses). Then you can cut/copy the expression and paste it into another position in some other function. Next step is to select the other function and
re-indent the function. Done. There is no need to remove or introduce new lines for for closing parentheses. Just paste and re-indent. It just fits in. Otherwise you would either waste time formatting the code, or you would need to re-format the code with some editor tool (so that closing parentheses are on their own lines. Most of the time it that would create additional work and hinders moving code around.
There is one occasion where experienced Lispers would sometime write closing parentheses on their own line:
(defvar *persons*
(list (make-person "fred")
(make-person "jane")
(make-person "susan")
))
Here it indicates that new persons can be added. Place the cursor directly before the second closing parentheses on the last line, press c-o (open line), add the clause and indent the parentheses that they are aligned again. This saves the 'trouble' to find the right parentheses and then press return, when all parentheses are closed on one line.
Because there is no need whatsoever to line up closing parens. It doesn't add anything semantically. To know how many to close, most Lispers use a good editor, such as Emacs, that matches parens to closing parens and hence makes the task trivial.
In Python, there are no closing parens or end keywords at all, and Pythonistas live just fine.
After a while with Lisp you don't notice the parentheses any longer, so your example two comes across as having a bunch of unnecessary whitespace in the end of it. More specifically, most lispers use an editor that is aware of parentheses and takes care of closing the forms correctly, so you as the developer don't need to match opening and closing parentheses like you do in e.g. C.
As for whether the last form should be
(* n (factorial (- n 1)))
or
(* n
(factorial (- n 1)))
that mostly comes down to personal preference and how much stuff is going on in the code (In this case I'd prefer the former just because there is so little happening in the code).
Besides the fact that most Lisp IDE's use paren matching, the amount of space that you would use to write any reasonable program would be ridiculous! You would get carpal tunnel from all the scrolling. A 1,000 line program would be close to a million lines of code if you put all the closing parenthesis on their own line. It may look prettier and be easier to read in a small program, but that idea wouldn't scale well at all.
Why do C programmers write things like:
((a && b) || (c && d))
instead of
((a && b) || (c && d
)
)
Wouldn't #2 be easier to read? :)
Seriously, though, the bunched up closing style works well for other languages, too.
#include <stdlib.h>
#include <stdio.h>
int main(void)
{ int i, j, k;
for (i = 0; i < 1000; i++)
{ for (j = 0; j < 1000; j++)
{ for (k = 0; k < 1000; k++)
{ if (i * i + j * j == k * k)
{ printf("%d, %d, %d\n", i, j, k); } } } }
return 0; }
After a while, you don't "see" the braces, just the structure given by the indentation.
if/else looks like this:
if (cond)
{ stmt;
stmt; }
else
{ stmt; }
switch:
switch (expr)
{ case '3':
stmt;
break;
case '4':
{ stmt;
break; } }
structs:
struct foo
{ int x;
struct bar
{ int y; };
union u
{ int a, b;
char c; }; };
Just first and obvious reason: 4 LOC in first case vs. 7 LOC in second one.
Any text editor that is aware of LISP syntax will highlight you matched/mismatched parentheses, so it's not the problem.
I experienced the same dilemma in PHP using the CakePHP framework and its many nested array() structures, sometimes 5+ layers deep. After a short while I realized that being OCD about the closing parenthesis did nothing but waste my precious development time and distracted me from the end goal. The indentation was to be the most useful aspect of the formatting.
Saving all the space seems like the primary reason. If it's almost as readable (esp. once you're used to the syntax) why use the extra 3 lines.
Because Lisp programmers look at the indentation and "shape", not the brackets.
You might consider Lisp variants which do without the (). In Genyris it looks like this:
def factorial (n)
if (< n 2) 1
* n
factorial (- n 1)
Seems like this is not a real question, just a judgement on Lisp, but the answer is perfectly obvious (but not, apparently, to non-Lispers!): parentheses in Lisp are in no way equivalent to braces in C-like languages -- rather, they're precisely equivalent to parentheses in C-like languages. Lispers don't generally write
(foo bar baz
)
for exactly the same reason C programmers don't generally write
foo(bar, baz
);
The reason
(if foo
(bar)
(baz))
looks different from
if (foo) {
bar();
} else {
baz();
}
has more to do with the if than the parentheses!
I have an explanation as to C programmers have a problem with Lispers putting all the remaining closing parentheses at the end. The practice seems to me that the meaning of parentheses could be the reason. This explanation overlaps and expands on some other answers.
To a C programmer (or other language using {braces} like C does), Lisp looks like it uses #| comments |# instead of /* comments */. And looks like Lisp parentheses () are in place of C braces {}.
But really, the Lisp parentheses mean very close to the same thing as in C (and similar languages using parentheses). Consider
defun f () nil
This defines a function f that does absolutely nothing, nil. And I type that line exactly as is into the Lisp Listener, and it just responds "F". In other words, it accepts it, without a beginning and ending parentheses around the whole thing.
What I think happens when you type that into the Listener is the Listener passes what you typed to Eval. Passing it to Eval could be represented as:
Eval( Listener() )
And Listener accepts my input and returns what I typed. And you would consider "Listener()" replaced in the expression so that it becomes
Eval (defun f () nil)
REPL (read, eval, print, loop) could be represented conceptually as a recursion
/* REPL expressed in C */
Loop()
{
Print ( Eval ( Listen () ) );
Loop();
}
Understood in the example is that Listen(), Eval(), and Print() are defined elsewhere or are built into the language.
The Listener lets me type
setf a 5
and also lets me type
(setf a 5)
but complains when I type
((setf a 5))
If parentheses were equivalent to C language braces, then the listener would accept it. In my C\C++ compilers, I can type
void a_fun(void)
{{
}}
without complaint. I can even type
void a_fun(void)
{{{
}}}
with no complaint from the C/C++ compiler.
But if I dare to type
void a_fun((void))
{
}
my C/C++ compiler complains--just like the Lisp listener complains!
For a C programmer writing nested function calls, seems it is more natural to write
fun_d( fun_c( fun_b( fun_a())));
than to write
fun_d( fun_c( fun_b( fun_a()
)
)
);
In C, braces demarcate a block of code. And a block of code is part of a function definition. Lisp parentheses don't demarcate blocks. They are somewhat like C's parentheses. In C, the parentheses demarcate a list; maybe a list of parameters passed to a function.
In Lisp, seems the opening parentheses "(" means we are going to start a new list, to which the CAR side of a CONS construct will point. Then we list the items to be contained or optionally pointed to by the CAR side of the CONS, with the CDR side pointing to nil (for end of list) or the next CONS. The closing parenthesis ")" means to terminate the list with a nil, and go back to continue the previous level of listing. So, C language does not do CONS's. So, there is a little bit of a difference between C's parentheses and Lisp's. Even so, seems very close, maybe even practically the same thing.
Some have written that Lisp becomes more like C if you move the function outside the parentheses. For example,
(setf a 5)
becomes
setf(a 5)
But what it really is, is that Eval requires that the first item in a list be the function that Eval needs to call. It is more like passing a C function a pointer to a function. So, what it really is is
eval(setf a 5)
And that looks more like C. You can even type it in the listener just like that without complaint from the listener or eval. You are just saying that eval should call eval which should then call setf. The rest of the list are parameters to setf.
Anyway, that's just what I think I see.
It's just that Eval needs to know which processor to call.
And I think this explanation provides an understanding of why C programmers think initially that Lispers should align closing parentheses under the opening parentheses which they close. The C programmer mistakenly thinks that Lisp's parenthesis correspond to C's braces. They don't. Lisp's parentheses correspond to C's parentheses.

Resources