all messages for Emacs-related lists mirrored at yhetil.org
 help / color / mirror / code / Atom feed
* Re: Why is defun not executed during load-file?
@ 2021-05-30 22:48 Drew Adams
  2021-05-30 22:57 ` Emanuel Berg via Users list for the GNU Emacs text editor
  0 siblings, 1 reply; 28+ messages in thread
From: Drew Adams @ 2021-05-30 22:48 UTC (permalink / raw)
  To: Help-Gnu-Emacs (help-gnu-emacs@gnu.org); +Cc: Emanuel Berg

> Macros are much more difficult to debug...

`macroexpand` and `macroexpand-1` are your friends.

Separate that first step, which is just reduction
(aka rewriting / reduction semantics), from the
subsequent step of Lisp-evaluating the sexp that
results from it.

So debug the macro-expansion step, to ensure you
get the sexp you want.  And debug evaluation of
that sexp - separately.



^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: Why is defun not executed during load-file?
  2021-05-30 22:48 Why is defun not executed during load-file? Drew Adams
@ 2021-05-30 22:57 ` Emanuel Berg via Users list for the GNU Emacs text editor
  2021-05-31  2:05   ` [External] : " Drew Adams
  0 siblings, 1 reply; 28+ messages in thread
From: Emanuel Berg via Users list for the GNU Emacs text editor @ 2021-05-30 22:57 UTC (permalink / raw)
  To: help-gnu-emacs

Drew Adams wrote:

>> Macros are much more difficult to debug...
>
> `macroexpand` and `macroexpand-1` are your friends.

Also, writing macros compared to writing functions typically
involves more bugs...

-- 
underground experts united
https://dataswamp.org/~incal




^ permalink raw reply	[flat|nested] 28+ messages in thread

* RE: [External] : Re: Why is defun not executed during load-file?
  2021-05-30 22:57 ` Emanuel Berg via Users list for the GNU Emacs text editor
@ 2021-05-31  2:05   ` Drew Adams
  2021-05-31  2:56     ` Emanuel Berg via Users list for the GNU Emacs text editor
  0 siblings, 1 reply; 28+ messages in thread
From: Drew Adams @ 2021-05-31  2:05 UTC (permalink / raw)
  To: Emanuel Berg; +Cc: Help-Gnu-Emacs (help-gnu-emacs@gnu.org)

> >> Macros are much more difficult to debug...
> >
> > `macroexpand` and `macroexpand-1` are your friends.
> 
> Also, writing macros compared to writing functions typically
> involves more bugs...

Why do you think so?

Most users write far fewer macros than functions.
A relative lack of familiarity/practice might
facilitate introduction of bugs.  IF what you
claim is true.  But what evidence is there?

Writing code that creates code is its own thing,
granted - it's a bit particular.  But if you did
that as often as you write typical defuns I'm
guessing you'd introduce about the same number
of bugs.

So yes, if "typically" one doesn't write macros
then writing macros will perhaps "typically"
involve more bugs.

But a little perspective hints that there's
nothing inherently buggy about writing macros.
Is it harder to ride a bike than to skateboard?
Depends on how used to each you are.



^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: [External] : Re: Why is defun not executed during load-file?
  2021-05-31  2:05   ` [External] : " Drew Adams
@ 2021-05-31  2:56     ` Emanuel Berg via Users list for the GNU Emacs text editor
  2021-05-31  5:05       ` Drew Adams
  0 siblings, 1 reply; 28+ messages in thread
From: Emanuel Berg via Users list for the GNU Emacs text editor @ 2021-05-31  2:56 UTC (permalink / raw)
  To: help-gnu-emacs

Drew Adams wrote:

>> Also, writing macros compared to writing functions
>> typically involves more bugs...
>
> Why do you think so? [...]

Maybe because it involves an extra layer, writing something
that will write something that will do something instead of
writing something that will do something...

> But what evidence is there?

Just keep on adding layers. Write something to write something
to write something ... etc. It gets more difficult for each
level added, is what we think.

-- 
underground experts united
https://dataswamp.org/~incal




^ permalink raw reply	[flat|nested] 28+ messages in thread

* RE: [External] : Re: Why is defun not executed during load-file?
  2021-05-31  2:56     ` Emanuel Berg via Users list for the GNU Emacs text editor
@ 2021-05-31  5:05       ` Drew Adams
  2021-05-31 19:20         ` Emanuel Berg via Users list for the GNU Emacs text editor
  0 siblings, 1 reply; 28+ messages in thread
From: Drew Adams @ 2021-05-31  5:05 UTC (permalink / raw)
  To: Emanuel Berg; +Cc: Help-Gnu-Emacs (help-gnu-emacs@gnu.org)

> >> Also, writing macros compared to writing functions
> >> typically involves more bugs...
> >
> > Why do you think so? [...]
> 
> Maybe because it involves an extra layer, writing something
> that will write something that will do something instead of
> writing something that will do something...
> 
> Just keep on adding layers. Write something to write something
> to write something ... etc. It gets more difficult for each
> level added, is what we think.

Fair enough; reasonable argument.

But I still think the perceived difficulty comes
from relative lack of practice.  There are only 2
levels/layers involved.  And they're completely
separate: (1) macro-expansion of a sexp to a sexp,
and (2) evaluation of the sexp resulting from #1.

You write lots of Lisp functions.  And you no
doubt think nothing of adding "layers" by having
a function that calls a function that calls a
function...  Even inhibiting evaluation with
`quote' here and there doesn't seem weird, once
a novice practices a bit and gets used to it.
But all of that is (can be) really quite complex.

It's just that you do that all the time - you're
used to it.  You don't write Lisp macros all the
time.
___

The macro-expansion step is the only part that's
a bit unusual - it's different from most of the
Lisp code you write.

Think of that step as just replacing one sexp by
another.  The input sexp has the form of a Lisp
function call: a non-empty list whose car is a
symbol.

The output is normally a sexp of the same form,
but it need not be - it can be any Lisp value
(any list, vector, string, symbol, number,
buffer, frame, syntax table, keymap,...).  As
far as step #1 is concerned, its result need
not even be something that can be evaluated
- or even read - without error.

And you have Lisp completely at your disposal,
for creating the output sexp, given the input
sexp.
___

Once you have the macro-expansion step defined,
the job's typically done.  What's left is to
verify that the output sexp _evaluates_ to the
result you want - and that, for every possible
input.

That is, because the result of macro-expansion
(#1) is typically evaluated, you do have to
worry about that evaluation step (#2), yes.

But if you only ever used `macroexpand' of sexp
to sexp to sexp to sexp,... then you wouldn't
need to bother with that worry.  You'd just be
transforming one list with a symbol car to
another, to another, to another,...

Macro-expansion isn't evaluation; it's reduction.
Lisp evaluation rules don't apply to producing
the output sexp from the input sexp.  What rules
do apply?  Whatever rules you like.  The only
rule underlying it all is that the input needs
to be a list with a symbol car.

For those used to purely functional programming,
that's all macro-expansion is: just reduction -
term rewriting.  You can look at it as a rewrite
rule from input patterns to output patterns. But
the rule can be implemented any way you like,
using any Lisp code.



^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: [External] : Re: Why is defun not executed during load-file?
  2021-05-31  5:05       ` Drew Adams
@ 2021-05-31 19:20         ` Emanuel Berg via Users list for the GNU Emacs text editor
  2021-05-31 19:47           ` Stefan Monnier via Users list for the GNU Emacs text editor
                             ` (4 more replies)
  0 siblings, 5 replies; 28+ messages in thread
From: Emanuel Berg via Users list for the GNU Emacs text editor @ 2021-05-31 19:20 UTC (permalink / raw)
  To: help-gnu-emacs

Drew Adams wrote:

>>>> Also, writing macros compared to writing functions
>>>> typically involves more bugs...
>>>
>>> Why do you think so? [...]
>> 
>> Maybe because it involves an extra layer, writing something
>> that will write something that will do something instead of
>> writing something that will do something...
>> 
>> Just keep on adding layers. Write something to write
>> something to write something ... etc. It gets more
>> difficult for each level added, is what we think.
>
> Fair enough; reasonable argument.
>
> But I still think the perceived difficulty comes from
> relative lack of practice. There are only 2 levels/layers
> involved. And they're completely separate: (1)
> macro-expansion of a sexp to a sexp, and (2) evaluation of
> the sexp resulting from #1.
>
> You write lots of Lisp functions. And you no doubt think
> nothing of adding "layers" by having a function that calls
> a function that calls a function... Even inhibiting
> evaluation with `quote' here and there doesn't seem weird,
> once a novice practices a bit and gets used to it. But all
> of that is (can be) really quite complex.
>
> It's just that you do that all the time - you're used to it.
> You don't write Lisp macros all the time.
>
> The macro-expansion step is the only part that's a bit
> unusual - it's different from most of the Lisp code
> you write.
>
> Think of that step as just replacing one sexp by another.
> The input sexp has the form of a Lisp function call:
> a non-empty list whose car is a symbol.
>
> The output is normally a sexp of the same form, but it need
> not be - it can be any Lisp value (any list, vector, string,
> symbol, number, buffer, frame, syntax table, keymap,...).
> As far as step #1 is concerned, its result need not even be
> something that can be evaluated - or even read -
> without error.
>
> And you have Lisp completely at your disposal, for creating
> the output sexp, given the input sexp.
>
> Once you have the macro-expansion step defined, the job's
> typically done. What's left is to verify that the output
> sexp _evaluates_ to the result you want - and that, for
> every possible input.
>
> That is, because the result of macro-expansion (#1) is
> typically evaluated, you do have to worry about that
> evaluation step (#2), yes.
>
> But if you only ever used `macroexpand' of sexp to sexp to
> sexp to sexp,... then you wouldn't need to bother with that
> worry. You'd just be transforming one list with a symbol car
> to another, to another, to another,...
>
> Macro-expansion isn't evaluation; it's reduction.
> Lisp evaluation rules don't apply to producing the output
> sexp from the input sexp. What rules do apply?
> Whatever rules you like. The only rule underlying it all is
> that the input needs to be a list with a symbol car.
>
> For those used to purely functional programming, that's all
> macro-expansion is: just reduction - term rewriting. You can
> look at it as a rewrite rule from input patterns to output
> patterns. But the rule can be implemented any way you like,
> using any Lisp code.

Hm ... interesting. Yeah, maybe we should start do that more?

But I'm unsure even what is the entry point...

What kind of things or problems could or should you solve
with macros?

-- 
underground experts united
https://dataswamp.org/~incal




^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: [External] : Re: Why is defun not executed during load-file?
  2021-05-31 19:20         ` Emanuel Berg via Users list for the GNU Emacs text editor
@ 2021-05-31 19:47           ` Stefan Monnier via Users list for the GNU Emacs text editor
  2021-05-31 20:09             ` Marcin Borkowski
  2021-06-07  2:19             ` Emanuel Berg via Users list for the GNU Emacs text editor
  2021-05-31 21:40           ` Example use of macro to minimize and generalize the code Jean Louis
                             ` (3 subsequent siblings)
  4 siblings, 2 replies; 28+ messages in thread
From: Stefan Monnier via Users list for the GNU Emacs text editor @ 2021-05-31 19:47 UTC (permalink / raw)
  To: help-gnu-emacs

> Hm ... interesting. Yeah, maybe we should start do that more?

Not really: it's better to avoid macros when you can.
But it's better to use macros than to use `eval`.

> What kind of things or problems could or should you solve
> with macros?

Whenever you find yourself forced to use `eval` ?


        Stefan




^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: [External] : Re: Why is defun not executed during load-file?
  2021-05-31 19:47           ` Stefan Monnier via Users list for the GNU Emacs text editor
@ 2021-05-31 20:09             ` Marcin Borkowski
  2021-06-07  2:19             ` Emanuel Berg via Users list for the GNU Emacs text editor
  1 sibling, 0 replies; 28+ messages in thread
From: Marcin Borkowski @ 2021-05-31 20:09 UTC (permalink / raw)
  To: Stefan Monnier; +Cc: help-gnu-emacs


On 2021-05-31, at 21:47, Stefan Monnier via Users list for the GNU Emacs text editor <help-gnu-emacs@gnu.org> wrote:

>> Hm ... interesting. Yeah, maybe we should start do that more?
>
> Not really: it's better to avoid macros when you can.
> But it's better to use macros than to use `eval`.
>
>> What kind of things or problems could or should you solve
>> with macros?
>
> Whenever you find yourself forced to use `eval` ?

Or when you lack some syntactical construct you could find useful, like
anaphoric-if.  Or if what you need is closer to a "special form" than to
a function.  A typical case is when you need a construct which will be
able to evaluate something or not, depending on the circumstances.  Or
when you need a construct which will evaluate some form(s) /after/ doing
something (remember that when a function gets its arguments, they are
all evaluated before even the first form of a function is evaluated!).
Here (shameless plug!) is an example of something you couldn't achieve
with functions alone (unless you wanted to wrap some code in `(lambda ()
...)', which would be rather ugly):
http://mbork.pl/2016-04-24_The_conditional-save-excursion_macro

Hth,

-- 
Marcin Borkowski
http://mbork.pl



^ permalink raw reply	[flat|nested] 28+ messages in thread

* Example use of macro to minimize and generalize the code
  2021-05-31 19:20         ` Emanuel Berg via Users list for the GNU Emacs text editor
  2021-05-31 19:47           ` Stefan Monnier via Users list for the GNU Emacs text editor
@ 2021-05-31 21:40           ` Jean Louis
  2021-05-31 23:37             ` Michael Heerdegen
  2021-05-31 21:45           ` Example use of macro to minimize and generalize the code (2) Jean Louis
                             ` (2 subsequent siblings)
  4 siblings, 1 reply; 28+ messages in thread
From: Jean Louis @ 2021-05-31 21:40 UTC (permalink / raw)
  To: help-gnu-emacs

* Emanuel Berg via Users list for the GNU Emacs text editor <help-gnu-emacs@gnu.org> [2021-05-31 22:21]:
> What kind of things or problems could or should you solve
> with macros?

Example use of macro:

I have noticed that I am often repeating some structures, really
boring, something like:

(defun my-fun ()
  (interactive)
  (let ((id (tabulated-list-get-id)))
    (if (and id (string= rcd-current-table "hyobjects"))
	(do-more)
      (warn something))))

instead:

(defmacro when-tabulated-id (table id &rest body)
  (declare (indent 2) (debug t))
  (ignore id)
  `(if id
       (progn
	 ,@body)
     (if (or (eq ,table 'any)
	     (string-equal ,table rcd-current-table))
	 (let ((id (tabulated-list-get-id)))
	   (if id
	       (progn ,@body)
	     (message "Did not get ID")))
       (message "This function is for table `%s' only" ,table))))

solves the problem and I get less code:

(defun my-fun (&optional id)
  (interactive)
  (when-tabulated-id "hyobjects" id
    (do-something)))

Imagine having 300+ functions where each function should maybe
report something in case of error, like you can see in the
macro. In this case I am minimizing code by using macro.


-- 
Jean

Take action in Free Software Foundation campaigns:
https://www.fsf.org/campaigns

Sign an open letter in support of Richard M. Stallman
https://stallmansupport.org/



^ permalink raw reply	[flat|nested] 28+ messages in thread

* Example use of macro to minimize and generalize the code (2)
  2021-05-31 19:20         ` Emanuel Berg via Users list for the GNU Emacs text editor
  2021-05-31 19:47           ` Stefan Monnier via Users list for the GNU Emacs text editor
  2021-05-31 21:40           ` Example use of macro to minimize and generalize the code Jean Louis
@ 2021-05-31 21:45           ` Jean Louis
  2021-05-31 21:48           ` [External] : Re: Why is defun not executed during load-file? Michael Heerdegen
  2021-05-31 23:41           ` Drew Adams
  4 siblings, 0 replies; 28+ messages in thread
From: Jean Louis @ 2021-05-31 21:45 UTC (permalink / raw)
  To: help-gnu-emacs

* Emanuel Berg via Users list for the GNU Emacs text editor <help-gnu-emacs@gnu.org> [2021-05-31 22:21]:

> What kind of things or problems could or should you solve with
> macros?

Another good use of a macro is with the database application where:

- database user can define the type of the object, for example,
  database user "joe" could create new type named "bc evaluation"

- the type of the object is accessible to user only, not to other
  users; 

- user edits the type and declares that the value should be evaluated
  with the external program named "bc". Such declaration could be
  simple "bc" instead of complex programming

- macro generates a function specific for that user who needs to see
  the output from "bc evaluation"

Thus it becomes a program that develops itself further based on
users's input. 

-- 
Jean

Take action in Free Software Foundation campaigns:
https://www.fsf.org/campaigns

Sign an open letter in support of Richard M. Stallman
https://stallmansupport.org/



^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: [External] : Re: Why is defun not executed during load-file?
  2021-05-31 19:20         ` Emanuel Berg via Users list for the GNU Emacs text editor
                             ` (2 preceding siblings ...)
  2021-05-31 21:45           ` Example use of macro to minimize and generalize the code (2) Jean Louis
@ 2021-05-31 21:48           ` Michael Heerdegen
  2021-05-31 23:41           ` Drew Adams
  4 siblings, 0 replies; 28+ messages in thread
From: Michael Heerdegen @ 2021-05-31 21:48 UTC (permalink / raw)
  To: help-gnu-emacs

Emanuel Berg via Users list for the GNU Emacs text editor
<help-gnu-emacs@gnu.org> writes:

> What kind of things or problems could or should you solve
> with macros?

My opinion is: Macros extend the language ("Lisp is a programmable
programming language").  Using macros can be beneficial if the problem
is of a kind so that adding new constructs to the language allows for
abstractions or at least coding style that makes writing and reading
code (and thinking) actually easier.  If that's not the case, don't use
them when possible.

Michael.




^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: Example use of macro to minimize and generalize the code
  2021-05-31 21:40           ` Example use of macro to minimize and generalize the code Jean Louis
@ 2021-05-31 23:37             ` Michael Heerdegen
  2021-05-31 23:59               ` Jean Louis
  0 siblings, 1 reply; 28+ messages in thread
From: Michael Heerdegen @ 2021-05-31 23:37 UTC (permalink / raw)
  To: help-gnu-emacs

Jean Louis <bugs@gnu.support> writes:

> (defmacro when-tabulated-id (table id &rest body)
>   (declare (indent 2) (debug t))
>   (ignore id)
>   `(if id
>        (progn
> 	 ,@body)
>      (if (or (eq ,table 'any)
> 	     (string-equal ,table rcd-current-table))
> 	 (let ((id (tabulated-list-get-id)))
> 	   (if id
> 	       (progn ,@body)
> 	     (message "Did not get ID")))
>        (message "This function is for table `%s' only" ,table))))

There is something wrong with that definition however: the variable `id'
is completely ignored, specifying something at that argument position is
redundant.

Tt may "work" by accident if the symbol `id' happens to be dynamically
bound to the same thing that you specify as argument, but only when that
exact variable name is used and only in dynamically binding Lisp.
Normally the byte compiler warns about this kind of problem - of course
only if you don't silence it ;-)

Michael.




^ permalink raw reply	[flat|nested] 28+ messages in thread

* RE: [External] : Re: Why is defun not executed during load-file?
  2021-05-31 19:20         ` Emanuel Berg via Users list for the GNU Emacs text editor
                             ` (3 preceding siblings ...)
  2021-05-31 21:48           ` [External] : Re: Why is defun not executed during load-file? Michael Heerdegen
@ 2021-05-31 23:41           ` Drew Adams
  4 siblings, 0 replies; 28+ messages in thread
From: Drew Adams @ 2021-05-31 23:41 UTC (permalink / raw)
  To: Emanuel Berg; +Cc: Help-Gnu-Emacs (help-gnu-emacs@gnu.org)

> Hm ... interesting. Yeah, maybe we should start do that more?

Dunno what you mean by "do that more".  If you mean use
`defmacro' more or something, then let me be clear that
I'm NOT suggesting that.  I'm not suggesting that people
should define more Lisp macros.

In general, don't define a macro if a function will do
what you want.

I just wanted to point out that I think the supposed
difficulty or bugginess of defining macros is due partly
(largely?) to the fact that we (all of us) write macros
much less often than we write functions.

> But I'm unsure even what is the entry point...

I'm guessing that here you're asking about how to use
a macro to just translate one Lisp sexp to another
(where the first is a list with symbol car).

If so, the answer is to use function `macroexpand'.
(or `macroexpand-1' or `macroexpand-all').  That just
does the first step: it expands an input sexp to its
expansion.  `eval', on the other hand, does both steps:
it expands the input sexp and then it evaluates the
resulting sexp.

(defun bar (x y z)
  (format "%s, %s! Is the answer really %s?" y x z)) 

(defmacro foo (a b) `(bar ,b ,a 42))

(macroexpand '(foo "Hello" 'alpha))
; ==> (bar 'alpha "Hello" 42)

(eval '(foo "Hello" 'alpha)))
; ==> "Hello, alpha! Is the answer really 42?"

> What kind of things or problems could or should you solve
> with macros?

Sexp translation.  One common use is to define control
structures (conditionals etc.), since a macro need not
evaluate all (or any) of its arguments.  Emacs Lisp
(like most Lisps) is not lazy - functions evaluate all
of their args before the function body is invoked.  So
you can't define a conditional such as `my-if' as a
Lisp function.  But you can define it as a macro.

Another common use is to define access functions, e.g.,
provide recognizable, domain-specific names.  E.g.:

(defmacro antenna-frobulator (satellite)
  `(caddr (caar (cddr (cdaar satellite)))))

Defining a domain-specific language is a major use
case for Lisp macros.  Of course, with Emacs Lisp the
resulting language still has Lisp-like syntax to a
large extent.  But with Common Lisp you also have
reader macros, which means you can end up with pretty
much any syntax you want for your DSL.

Most uses of macros are something like these.

Paul Graham describes what Lisp macros are all about,
what they're used for, and how to use them, in several
of his essays, and in his book "On Lisp".  Here's one
such short essay - search for "macro":

http://www.paulgraham.com/avg.html
___

What's a use case of just macro-expanding, i.e., just
translating Lisp sexps, without evaluating the result?

This is not common.  Let me be clear about that.

But as one example, the first non-trivial Lisp program
I wrote did just that.  It essentially used `macrolet'
to define a zillion macros that translated all of the
predefined forms (functions, special forms, macros) of
Franz Lisp to Common Lisp (this was before Franz Inc.
went Common).  (Another part of the code translation
translated predefined global variables.)

The program was used to make a first, automatic, pass
at translating lots of Franz-Lisp code to Common Lisp
for a Lisp/Prolog machine we built.  (This was back
when there were few CL implementations.  A preliminary
implementation of Kyoto CL was all we had.  We were
writing a CL implementation for the Lisp machine.)

Franz then was only dynamically scoped, and CL is
lexically scoped, so exact translation is ultimately
impossible.

But a given sexp translation (e.g. `(apply #+ foobar)'
could sometimes be relatively straightforward.
(Actually, even `+' was not straightforward, as the
type systems were different etc.)

In a simple case, a sexp translation might only mean
changing the order of some arguments.  The two Lisps
had a lot in common, even though they were also very
different.  There were plenty of "faux amis" and such.

More generally, the output would be a sexp with lambda
forms that had doc strings describing correspondences
for functions/macros etc. (the closest correspondences
to be found), args, limitations, etc.

The result of translating a short program could thus
be a large program of approximate code.  The point was
to serve as an aid to humans who had to produce a CL
version of the code.  We translated tons of code this
way.  The translation tool was only that - a tool that
helped people translate code.

You could also use the tool interactively to evaluate
the translation result.  That is, it gave us a way to
to interpret Franz code on the fly using CL, in a
first-pass way.  That helped with testing & debugging.
  




^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: Example use of macro to minimize and generalize the code
  2021-05-31 23:37             ` Michael Heerdegen
@ 2021-05-31 23:59               ` Jean Louis
  2021-06-01  0:34                 ` Michael Heerdegen
  0 siblings, 1 reply; 28+ messages in thread
From: Jean Louis @ 2021-05-31 23:59 UTC (permalink / raw)
  To: Michael Heerdegen; +Cc: help-gnu-emacs

* Michael Heerdegen <michael_heerdegen@web.de> [2021-06-01 02:38]:
> Jean Louis <bugs@gnu.support> writes:
> 
> > (defmacro when-tabulated-id (table id &rest body)
> >   (declare (indent 2) (debug t))
> >   (ignore id)
> >   `(if id
> >        (progn
> > 	 ,@body)
> >      (if (or (eq ,table 'any)
> > 	     (string-equal ,table rcd-current-table))
> > 	 (let ((id (tabulated-list-get-id)))
> > 	   (if id
> > 	       (progn ,@body)
> > 	     (message "Did not get ID")))
> >        (message "This function is for table `%s' only" ,table))))
> 
> There is something wrong with that definition however: the variable `id'
> is completely ignored, specifying something at that argument position is
> redundant.

I appreciate all comments.

> Tt may "work" by accident if the symbol `id' happens to be dynamically
> bound to the same thing that you specify as argument, but only when that
> exact variable name is used and only in dynamically binding Lisp.

You guessed it well, I am using it this way:

(defun hyperscope-tabulated-action (&optional id)
  (interactive)
  (when-tabulated-id "hyobjects" id
    (hyperscope-ring id)
    (hyperscope-action id)))

As there are many different tables which all have its ID, so the macro
has to make sure it is invoked in the right table. There could be
other ways to check that. 

Programs have their lexical binding true, maybe that one you did not
expect.

Such functions can be invoked programmatically or interactively,
interactively there is check if there is right database table in the
tabulated-list-mode, as otherwise it gives a warning that it is not
invoked in that other different table.

> Normally the byte compiler warns about this kind of problem - of course
> only if you don't silence it ;-)

That is why `ignore' is there. Ignore is there to suppress the byte
compiler warning just as you guessed it.

Otherwise:

In when-tabulated-id:
rcd-cf.el:165:45: Warning: Unused lexical argument `id'


-- 
Jean

Take action in Free Software Foundation campaigns:
https://www.fsf.org/campaigns

Sign an open letter in support of Richard M. Stallman
https://stallmansupport.org/



^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: Example use of macro to minimize and generalize the code
  2021-05-31 23:59               ` Jean Louis
@ 2021-06-01  0:34                 ` Michael Heerdegen
  2021-06-01  0:39                   ` Jean Louis
  0 siblings, 1 reply; 28+ messages in thread
From: Michael Heerdegen @ 2021-06-01  0:34 UTC (permalink / raw)
  To: help-gnu-emacs

Jean Louis <bugs@gnu.support> writes:

> [...]
> That is why `ignore' is there. Ignore is there to suppress the byte
> compiler warning just as you guessed it.
>
> Otherwise:
>
> In when-tabulated-id:
> rcd-cf.el:165:45: Warning: Unused lexical argument `id'

Sure - but why do you add an argument to that macro that it (or its
expansion) doesn't use at all?  That's very confusing, it would be
better to remove the argument.  Or - could the macro be rewritten to not
ignore that argument?

Regards,

Michael.




^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: Example use of macro to minimize and generalize the code
  2021-06-01  0:34                 ` Michael Heerdegen
@ 2021-06-01  0:39                   ` Jean Louis
  2021-06-01  0:59                     ` Michael Heerdegen
  0 siblings, 1 reply; 28+ messages in thread
From: Jean Louis @ 2021-06-01  0:39 UTC (permalink / raw)
  To: Michael Heerdegen; +Cc: help-gnu-emacs

* Michael Heerdegen <michael_heerdegen@web.de> [2021-06-01 03:35]:
> Jean Louis <bugs@gnu.support> writes:
> 
> > [...]
> > That is why `ignore' is there. Ignore is there to suppress the byte
> > compiler warning just as you guessed it.
> >
> > Otherwise:
> >
> > In when-tabulated-id:
> > rcd-cf.el:165:45: Warning: Unused lexical argument `id'
> 
> Sure - but why do you add an argument to that macro that it (or its
> expansion) doesn't use at all?  That's very confusing, it would be
> better to remove the argument.  Or - could the macro be rewritten to not
> ignore that argument?

I would like to improve but I have to understand what you mean. This
is the macro, arguments are table, id and body. I need all of them.

- table is there as I don't want my functions invoked in other tables,
  it could cause havoc;

- ID is necessary;

- functions can be then invoked programmatically and interactively
  with less arguments:

So help me understand...

(defmacro when-tabulated-id (table id &rest body)
  (declare (indent 2) (debug t))
  (ignore id)
  `(if id
       (progn
	 ,@body)
     (if (or (eq ,table 'any)
	     (string-equal ,table rcd-current-table))
	 (let ((id (tabulated-list-get-id)))
	   (if id
	       (progn ,@body)
	     (message "Did not get ID")))
       (message "This function is for table `%s' only" ,table))))

-- 
Jean

Take action in Free Software Foundation campaigns:
https://www.fsf.org/campaigns

Sign an open letter in support of Richard M. Stallman
https://stallmansupport.org/



^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: Example use of macro to minimize and generalize the code
  2021-06-01  0:39                   ` Jean Louis
@ 2021-06-01  0:59                     ` Michael Heerdegen
  2021-06-01  1:25                       ` Jean Louis
  0 siblings, 1 reply; 28+ messages in thread
From: Michael Heerdegen @ 2021-06-01  0:59 UTC (permalink / raw)
  To: help-gnu-emacs

Jean Louis <bugs@gnu.support> writes:

> - ID is necessary;

Your macro calls always ignore what you specify at that argument's
position.  Instead, the macros refer to a (free) variable `id'.  AFAICT,
with your current implementation nothing would change if you would
remove the macro argument (and the `ignore' call) and simply don't use
it.

Typically, the backquote expression in the macro body would have ",id"
instead of "id" to include the value specified by the ID argument.  The
compiler warning is not just noise.

Michael.




^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: Example use of macro to minimize and generalize the code
  2021-06-01  0:59                     ` Michael Heerdegen
@ 2021-06-01  1:25                       ` Jean Louis
  2021-06-01 14:02                         ` Michael Heerdegen
  0 siblings, 1 reply; 28+ messages in thread
From: Jean Louis @ 2021-06-01  1:25 UTC (permalink / raw)
  To: Michael Heerdegen; +Cc: help-gnu-emacs

* Michael Heerdegen <michael_heerdegen@web.de> [2021-06-01 04:00]:
> Jean Louis <bugs@gnu.support> writes:
> 
> > - ID is necessary;
> 
> Your macro calls always ignore what you specify at that argument's
> position.  Instead, the macros refer to a (free) variable `id'.  AFAICT,
> with your current implementation nothing would change if you would
> remove the macro argument (and the `ignore' call) and simply don't use
> it.
> 
> Typically, the backquote expression in the macro body would have ",id"
> instead of "id" to include the value specified by the ID argument.  The
> compiler warning is not just noise.

I do believe you see it what you say, but I didn't see what you
say... (✿╹◡╹) -- so yes, now it works, thanks.

I have removed `id' and `ignore' and there are no compiler warnings
and there is for now no impact how I see that. That comes due to
various testing, I have actually started it that way, there was no ID,
then I messed something up and addedd ID and now you see more, and I
removed it from bunch of functions. For now it works.

(defmacro when-tabulated-id (table &rest body)
  (declare (indent 2) (debug t))
  ;;(ignore id)
  `(if id
       (progn
	 ,@body)
     (if (or (eq ,table 'any)
	     (string-equal ,table rcd-current-table))
	 (let ((id (tabulated-list-get-id)))
	   (if id
	       (progn ,@body)
	     (message "Did not get ID")))
       (message "This function is for table `%s' only" ,table))))

-- 
Jean

Take action in Free Software Foundation campaigns:
https://www.fsf.org/campaigns

Sign an open letter in support of Richard M. Stallman
https://stallmansupport.org/



^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: Example use of macro to minimize and generalize the code
  2021-06-01  1:25                       ` Jean Louis
@ 2021-06-01 14:02                         ` Michael Heerdegen
  2021-06-01 16:33                           ` Jean Louis
  0 siblings, 1 reply; 28+ messages in thread
From: Michael Heerdegen @ 2021-06-01 14:02 UTC (permalink / raw)
  To: help-gnu-emacs

Jean Louis <bugs@gnu.support> writes:

> (defmacro when-tabulated-id (table &rest body)
>   (declare (indent 2) (debug t))
>   ;;(ignore id)
>   `(if id
>        (progn
> 	 ,@body)
>      (if (or (eq ,table 'any)
> 	     (string-equal ,table rcd-current-table))
> 	 (let ((id (tabulated-list-get-id)))
> 	   (if id
> 	       (progn ,@body)
> 	     (message "Did not get ID")))
>        (message "This function is for table `%s' only" ,table))))

Yes, better.

The downside now is that using the macro hides the fact that the code
depends on the id, and the resulting code is (still) hard to understand.
Why don't you consider to make the id a real argument?

Regards,

Michael.



^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: Example use of macro to minimize and generalize the code
  2021-06-01 14:02                         ` Michael Heerdegen
@ 2021-06-01 16:33                           ` Jean Louis
  2021-06-01 16:54                             ` Yuri Khan
  0 siblings, 1 reply; 28+ messages in thread
From: Jean Louis @ 2021-06-01 16:33 UTC (permalink / raw)
  To: Michael Heerdegen; +Cc: help-gnu-emacs

* Michael Heerdegen <michael_heerdegen@web.de> [2021-06-01 17:03]:
> Jean Louis <bugs@gnu.support> writes:
> 
> > (defmacro when-tabulated-id (table &rest body)
> >   (declare (indent 2) (debug t))
> >   ;;(ignore id)
> >   `(if id
> >        (progn
> > 	 ,@body)
> >      (if (or (eq ,table 'any)
> > 	     (string-equal ,table rcd-current-table))
> > 	 (let ((id (tabulated-list-get-id)))
> > 	   (if id
> > 	       (progn ,@body)
> > 	     (message "Did not get ID")))
> >        (message "This function is for table `%s' only" ,table))))
> 
> Yes, better.
> 
> The downside now is that using the macro hides the fact that the code
> depends on the id, and the resulting code is (still) hard to understand.
> Why don't you consider to make the id a real argument?

I wish I could fully understand but I don't, and I consider your
advises important.

How would I make the ID a real argument?

Each of those functions has &optional id as if function is not
capturing ID from tabulated-list-mode then it may receive it
programmatically.

Example:

(defun hyperscope-new-appointment (&optional id)
  "Add new `Appointment' hyperdocument."
  (interactive)
  (when-tabulated-id "hyobjects"
    (let ((parent (hlink-parent id)))
      (hyperscope-add-new-appointment-hyperdocument parent))))

-- 
Jean

Take action in Free Software Foundation campaigns:
https://www.fsf.org/campaigns

Sign an open letter in support of Richard M. Stallman
https://stallmansupport.org/



^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: Example use of macro to minimize and generalize the code
  2021-06-01 16:33                           ` Jean Louis
@ 2021-06-01 16:54                             ` Yuri Khan
  2021-06-01 17:24                               ` Jean Louis
  0 siblings, 1 reply; 28+ messages in thread
From: Yuri Khan @ 2021-06-01 16:54 UTC (permalink / raw)
  To: Michael Heerdegen, help-gnu-emacs

On Tue, 1 Jun 2021 at 23:38, Jean Louis <bugs@gnu.support> wrote:

> > > (defmacro when-tabulated-id (table &rest body)
> > >   (declare (indent 2) (debug t))
> > >   ;;(ignore id)
> > >   `(if id

> > Why don't you consider to make the id a real argument?
>
> I wish I could fully understand but I don't, and I consider your
> advises important.
>
> How would I make the ID a real argument?

I believe Michael is hinting at this:

    (defmacro when-tabulated-id (id table &rest body)
      `(if ,id
           …

which means “at macro expansion time, substitute the value of the
argument to the macro”, rather than your original

    (defmacro when-tabulated-id (id table &rest body)
      `(if id
           …

which means “at evaluation time, substitute the value of the symbol 'id”.



^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: Example use of macro to minimize and generalize the code
  2021-06-01 16:54                             ` Yuri Khan
@ 2021-06-01 17:24                               ` Jean Louis
  2021-06-01 17:57                                 ` Yuri Khan
  0 siblings, 1 reply; 28+ messages in thread
From: Jean Louis @ 2021-06-01 17:24 UTC (permalink / raw)
  To: Yuri Khan; +Cc: Michael Heerdegen, help-gnu-emacs

* Yuri Khan <yuri.v.khan@gmail.com> [2021-06-01 20:12]:
> On Tue, 1 Jun 2021 at 23:38, Jean Louis <bugs@gnu.support> wrote:
> 
> > > > (defmacro when-tabulated-id (table &rest body)
> > > >   (declare (indent 2) (debug t))
> > > >   ;;(ignore id)
> > > >   `(if id
> 
> > > Why don't you consider to make the id a real argument?
> >
> > I wish I could fully understand but I don't, and I consider your
> > advises important.
> >
> > How would I make the ID a real argument?
> 
> I believe Michael is hinting at this:
> 
>     (defmacro when-tabulated-id (id table &rest body)
>       `(if ,id
>            …
> 
> which means “at macro expansion time, substitute the value of the
> argument to the macro”, rather than your original
> 
>     (defmacro when-tabulated-id (id table &rest body)
>       `(if id
>            …
> 
> which means “at evaluation time, substitute the value of the symbol
> 'id”.

I have removed `id' argument and now I have:

(macroexpand '(when-tabulated-id "people" (ignore))) 
⇒ (if id (progn (ignore)) 
    (if (or (eq "people" 'any) (string-equal "people" rcd-current-table)) 
	(let ((id (tabulated-list-get-id)))
	  (if id (progn (ignore)) (message "Did not get ID"))) 
      (message "This function is for table `%s' only" "people")))

If I would use ,d it would expand into number or nil, it seem it would end up same.

Now I don't have compiler warnings, and functions work fine.

Let me know if I am making errors in this.

-- 
Jean

Take action in Free Software Foundation campaigns:
https://www.fsf.org/campaigns

Sign an open letter in support of Richard M. Stallman
https://stallmansupport.org/



^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: Example use of macro to minimize and generalize the code
  2021-06-01 17:24                               ` Jean Louis
@ 2021-06-01 17:57                                 ` Yuri Khan
  2021-06-01 18:12                                   ` Jean Louis
  0 siblings, 1 reply; 28+ messages in thread
From: Yuri Khan @ 2021-06-01 17:57 UTC (permalink / raw)
  To: Yuri Khan, Michael Heerdegen, help-gnu-emacs

On Wed, 2 Jun 2021 at 00:27, Jean Louis <bugs@gnu.support> wrote:

> I have removed `id' argument and now I have:
>
> (macroexpand '(when-tabulated-id "people" (ignore)))
> ⇒ (if id (progn (ignore))
>     (if (or (eq "people" 'any) (string-equal "people" rcd-current-table))
>         (let ((id (tabulated-list-get-id)))
>           (if id (progn (ignore)) (message "Did not get ID")))
>       (message "This function is for table `%s' only" "people")))
>
> If I would use ,d it would expand into number or nil, it seem it would end up same.
>
> Now I don't have compiler warnings, and functions work fine.
>
> Let me know if I am making errors in this.

Yes you are. Your macro expands to a form that refers to a symbol
named “id” from outer scope. Next, there are several possibilities:

* The symbol is not defined, in which case the result of expansion
will signal (void-variable id):

    (when-tabulated-id "people" (ignore))
    ⇒ Debugger entered--Lisp error: (void-variable id)

* The user of your macro has to define a variable named “id” globally
or buffer-locally. This is bad because the name “id” is not
namespaced. In your own package, any variable names you define should
start with a prefix unique to your package.

    (setq id t)
    (when-tabulated-id "people" (ignore))
    ⇒ nil

* The user has to use your macro in a context where “id” is bound as a
local variable or a function argument. If that’s your intent, you
should document it in the docstring of the macro, but it’s fragile
because nobody expects forms to behave this way.

    (let ((id t))
      (when-tabulated-id "people" (ignore)))
    ⇒ nil

    (defun foo (id)
      (when-tabulated-id "people" (ignore)))
    (foo t)
    ⇒ nil

* Lastly, you might have intended this macro to be used only by you.
In that case, it should be namespaced to your package with a double
hyphen after the prefix. Anyway, three month later, you forget that
the macro depends on “id” and you stare at your (let ((id t)) …) or
(defun foo (id) …) which doesn’t obviously use “id” and remove the
binding. Suddenly everything breaks.



^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: Example use of macro to minimize and generalize the code
  2021-06-01 17:57                                 ` Yuri Khan
@ 2021-06-01 18:12                                   ` Jean Louis
  0 siblings, 0 replies; 28+ messages in thread
From: Jean Louis @ 2021-06-01 18:12 UTC (permalink / raw)
  To: Yuri Khan; +Cc: Michael Heerdegen, help-gnu-emacs

* Yuri Khan <yuri.v.khan@gmail.com> [2021-06-01 20:58]:
> On Wed, 2 Jun 2021 at 00:27, Jean Louis <bugs@gnu.support> wrote:
> 
> > I have removed `id' argument and now I have:
> >
> > (macroexpand '(when-tabulated-id "people" (ignore)))
> > ⇒ (if id (progn (ignore))
> >     (if (or (eq "people" 'any) (string-equal "people" rcd-current-table))
> >         (let ((id (tabulated-list-get-id)))
> >           (if id (progn (ignore)) (message "Did not get ID")))
> >       (message "This function is for table `%s' only" "people")))
> >
> > If I would use ,d it would expand into number or nil, it seem it would end up same.
> >
> > Now I don't have compiler warnings, and functions work fine.
> >
> > Let me know if I am making errors in this.
> 
> Yes you are. Your macro expands to a form that refers to a symbol
> named “id” from outer scope. Next, there are several possibilities:
> 
> * The symbol is not defined, in which case the result of expansion
> will signal (void-variable id):
> 
>     (when-tabulated-id "people" (ignore))
>     ⇒ Debugger entered--Lisp error: (void-variable id)

Macro is exclusively used in functions as this:

(defun my-fun (&optional id)
  ""
  (interactive)
  (when-tabulated-id "hyobjects"
     ))

> * The user of your macro has to define a variable named “id” globally
> or buffer-locally. This is bad because the name “id” is not
> namespaced. In your own package, any variable names you define should
> start with a prefix unique to your package.

Do you mean all, or just global variables to have prefix?

>     (setq id t)
>     (when-tabulated-id "people" (ignore))
>     ⇒ nil

I understand, just macro is used exclusively in functions as above. Is
that alright?

> * The user has to use your macro in a context where “id” is bound as a
> local variable or a function argument. If that’s your intent, you
> should document it in the docstring of the macro, but it’s fragile
> because nobody expects forms to behave this way.
> 
>     (let ((id t))
>       (when-tabulated-id "people" (ignore)))
>     ⇒ nil
> 
>     (defun foo (id)
>       (when-tabulated-id "people" (ignore)))
>     (foo t)
>     ⇒ nil

(◍•ᴗ•◍) that can be, but that is exactly how I expected it to
behave. As the ID is either obtained programmatically which makes the
macro work or from (tabulated-list-get-id)

> * Lastly, you might have intended this macro to be used only by you.

Yes, and I see difficulties in future if somebody else wish to use it.

> In that case, it should be namespaced to your package with a double
> hyphen after the prefix. Anyway, three month later, you forget that
> the macro depends on “id” and you stare at your (let ((id t)) …) or
> (defun foo (id) …) which doesn’t obviously use “id” and remove the
> binding. Suddenly everything breaks.

Breaking I can also understand.

Macro or not macro my goal is to minimize programming, as 400+
functions are asking for (tabulated-list-get-id) and the ID can be in
different tables. 

Maybe it can be solved without any macro.

-- 
Jean

Take action in Free Software Foundation campaigns:
https://www.fsf.org/campaigns

Sign an open letter in support of Richard M. Stallman
https://stallmansupport.org/



^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: [External] : Re: Why is defun not executed during load-file?
  2021-05-31 19:47           ` Stefan Monnier via Users list for the GNU Emacs text editor
  2021-05-31 20:09             ` Marcin Borkowski
@ 2021-06-07  2:19             ` Emanuel Berg via Users list for the GNU Emacs text editor
  2021-06-07  6:27               ` Jean Louis
  2021-06-07 14:18               ` FW: " Drew Adams
  1 sibling, 2 replies; 28+ messages in thread
From: Emanuel Berg via Users list for the GNU Emacs text editor @ 2021-06-07  2:19 UTC (permalink / raw)
  To: help-gnu-emacs

Stefan Monnier via Users list for the GNU Emacs text editor wrote:

>> Hm ... interesting. Yeah, maybe we should start do that more?
>
> Not really: it's better to avoid macros when you can.
> But it's better to use macros than to use `eval`.

Ah, that's what I thought all along but it sounded cool when
Mr Adams said it wasn't evaluated anymore but reduced (?) ...

>> What kind of things or problems could or should you solve
>> with macros?
>
> Whenever you find yourself forced to use `eval` ?

OK so the hierarchy is:

1. `defun' (best)
2. `defmacro' (at least better than `eval')
3. eval (worse)

That what you meant?

Can one summarize in human language without references to Lisp
perhaps when macros are used? I used them so seldom I don't
know why people use them, even. I guess I did so good now I'm
ignorant instead.

-- 
underground experts united
https://dataswamp.org/~incal




^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: [External] : Re: Why is defun not executed during load-file?
  2021-06-07  2:19             ` Emanuel Berg via Users list for the GNU Emacs text editor
@ 2021-06-07  6:27               ` Jean Louis
  2021-06-07 14:18               ` FW: " Drew Adams
  1 sibling, 0 replies; 28+ messages in thread
From: Jean Louis @ 2021-06-07  6:27 UTC (permalink / raw)
  To: help-gnu-emacs

* Emanuel Berg via Users list for the GNU Emacs text editor <help-gnu-emacs@gnu.org> [2021-06-07 05:20]:
> OK so the hierarchy is:
> 
> 1. `defun' (best)
> 2. `defmacro' (at least better than `eval')
> 3. eval (worse)

No need for panic. There is nothing so special that can take place
with `eval' that cannot take place with `defun' or any bad
programming. We already said Org is eval-ing so much. Every Babel
source block in Org mode is eval-ed.

8 matches for "(eval " in buffer: org.el
   8421:    (eval `(let ,binds
   9329:			       (or (eval checklist)
  12473:	      (setq scope (eval scope)))
  14231:    (eval form)
  14645:	 (result (if calendar-debug-sexp (eval sexp)
  14647:		       (eval sexp)
  16525:      (eval org-speed-command))
  18337:			(not (equal (symbol-value v) (eval (car (get v 'standard-value)))))))

Org from Org babel:

(defun org-babel-execute:emacs-lisp (body params)
  "Execute a block of emacs-lisp code with Babel."
  (let* ((lexical (cdr (assq :lexical params)))
	 (result-params (cdr (assq :result-params params)))
	 (body (format (if (member "output" result-params)
			   "(with-output-to-string %s\n)"
			 "(progn %s\n)")
		       (org-babel-expand-body:emacs-lisp body params)))
	 (result (eval (read (if (or (member "code" result-params)


I have been `eval'-ing for years by using Perl, by using Common Lisp
and now Emacs Lisp especially when it comes to replacement of text,
variables, or keeping some program code in the database.

Each time you press C-x C-e you are `eval'-ing

Some data has to be eval-ed and some data arrives from other places
but program file, or is generated in some way and there is nothing
wrong with using `eval' wherever it is required.


-- 
Jean

Take action in Free Software Foundation campaigns:
https://www.fsf.org/campaigns

In support of Richard M. Stallman
https://stallmansupport.org/



^ permalink raw reply	[flat|nested] 28+ messages in thread

* FW: [External] : Re: Why is defun not executed during load-file?
  2021-06-07  2:19             ` Emanuel Berg via Users list for the GNU Emacs text editor
  2021-06-07  6:27               ` Jean Louis
@ 2021-06-07 14:18               ` Drew Adams
  2021-06-07 14:41                 ` Emanuel Berg via Users list for the GNU Emacs text editor
  1 sibling, 1 reply; 28+ messages in thread
From: Drew Adams @ 2021-06-07 14:18 UTC (permalink / raw)
  To: Help-Gnu-Emacs (help-gnu-emacs@gnu.org); +Cc: Emanuel Berg

> >> Hm ... interesting. Yeah, maybe we should start do that more?
> >
> > Not really: it's better to avoid macros when you can.
> > But it's better to use macros than to use `eval`.
> 
> Ah, that's what I thought all along but it sounded cool when
> Mr Adams said it wasn't evaluated anymore but reduced (?) ...

Mr. Adams also said:

  If you mean use `defmacro' more or something, then let
  me be clear that I'm NOT suggesting that.  I'm not
  suggesting that people should define more Lisp macros.

  In general, don't define a macro if a function will do
              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  what you want.

  I just wanted to point out that I think the supposed
  difficulty or bugginess of defining macros is due partly
  (largely?) to the fact that we (all of us) write macros
  much less often than we write functions.

> Can one summarize in human language without references to Lisp
> perhaps when macros are used? I used them so seldom I don't
> know why people use them, even. I guess I did so good now I'm
> ignorant instead.

Syntax transformation: sexp1 to sexp2, followed typically
(and automatically) by evaluation of sexp2.

Without the evaluation step (i.e., with only "expansion"),
a macro just substitutes one sexp (that's an expression -
syntax) for another.

When do you want to do syntax transformation?  Typically
to define a domain-specific language (which nevertheless
has Lisp-like syntax).  And "DSL" here can mean just
define some accessor functions (macros) that speak more
directly to the purpose/intent/meaning of the thing
accessed.

Another typical use is to define a control structure,
that is, something that need not evaluate all of its
args before invoking the body.  E.g., a conditional or
other predicate.  You can't define something like `if'
with `defun' in Elisp.  You can defined it as a macro.

I said all of this before, with examples:

https://lists.gnu.org/archive/html/help-gnu-emacs/2021-05/msg01157.html



^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: FW: [External] : Re: Why is defun not executed during load-file?
  2021-06-07 14:18               ` FW: " Drew Adams
@ 2021-06-07 14:41                 ` Emanuel Berg via Users list for the GNU Emacs text editor
  0 siblings, 0 replies; 28+ messages in thread
From: Emanuel Berg via Users list for the GNU Emacs text editor @ 2021-06-07 14:41 UTC (permalink / raw)
  To: help-gnu-emacs

Drew Adams wrote:

> Mr. Adams also said:
>
>   If you mean use `defmacro' more or something, then let
>   me be clear that I'm NOT suggesting that.  I'm not
>   suggesting that people should define more Lisp macros.
>
>   In general, don't define a macro if a function will do
>               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
>   what you want.
>
>   I just wanted to point out that I think the supposed
>   difficulty or bugginess of defining macros is due partly
>   (largely?) to the fact that we (all of us) write macros
>   much less often than we write functions.

Yeah, but how do you get more experience without doing it?

So then it is all the way back to reality where it is more
difficult and do involve more bugs and more
difficult debugging?

Or should I rephrase it so, macros are more difficult, it
involves more bugs that are harder to fix, except for the
people whose poor judgement and intuition has placed them in
the undesirable situation where they in fact have AS MUCH
experience with defuns as with macros?

Still - doesn't sound right? But difficult to say what Lego
piece is missing. Copenhagen maybe?

-- 
underground experts united
https://dataswamp.org/~incal




^ permalink raw reply	[flat|nested] 28+ messages in thread

end of thread, other threads:[~2021-06-07 14:41 UTC | newest]

Thread overview: 28+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2021-05-30 22:48 Why is defun not executed during load-file? Drew Adams
2021-05-30 22:57 ` Emanuel Berg via Users list for the GNU Emacs text editor
2021-05-31  2:05   ` [External] : " Drew Adams
2021-05-31  2:56     ` Emanuel Berg via Users list for the GNU Emacs text editor
2021-05-31  5:05       ` Drew Adams
2021-05-31 19:20         ` Emanuel Berg via Users list for the GNU Emacs text editor
2021-05-31 19:47           ` Stefan Monnier via Users list for the GNU Emacs text editor
2021-05-31 20:09             ` Marcin Borkowski
2021-06-07  2:19             ` Emanuel Berg via Users list for the GNU Emacs text editor
2021-06-07  6:27               ` Jean Louis
2021-06-07 14:18               ` FW: " Drew Adams
2021-06-07 14:41                 ` Emanuel Berg via Users list for the GNU Emacs text editor
2021-05-31 21:40           ` Example use of macro to minimize and generalize the code Jean Louis
2021-05-31 23:37             ` Michael Heerdegen
2021-05-31 23:59               ` Jean Louis
2021-06-01  0:34                 ` Michael Heerdegen
2021-06-01  0:39                   ` Jean Louis
2021-06-01  0:59                     ` Michael Heerdegen
2021-06-01  1:25                       ` Jean Louis
2021-06-01 14:02                         ` Michael Heerdegen
2021-06-01 16:33                           ` Jean Louis
2021-06-01 16:54                             ` Yuri Khan
2021-06-01 17:24                               ` Jean Louis
2021-06-01 17:57                                 ` Yuri Khan
2021-06-01 18:12                                   ` Jean Louis
2021-05-31 21:45           ` Example use of macro to minimize and generalize the code (2) Jean Louis
2021-05-31 21:48           ` [External] : Re: Why is defun not executed during load-file? Michael Heerdegen
2021-05-31 23:41           ` Drew Adams

Code repositories for project(s) associated with this external index

	https://git.savannah.gnu.org/cgit/emacs.git
	https://git.savannah.gnu.org/cgit/emacs/org-mode.git

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.