* Why I cannot use this variable in macro call from function?
@ 2021-06-08 13:10 Jean Louis
2021-06-08 13:41 ` [External] : " Drew Adams
0 siblings, 1 reply; 28+ messages in thread
From: Jean Louis @ 2021-06-08 13:10 UTC (permalink / raw)
To: Help GNU Emacs
I have this macro, as purpose of it is to dynamically generate history
variables for more than 100 database tables. If new database table is
generated a new variable will be generated without changing the source
code.
(defmacro rcd-db-completing-table-history (table)
(let ((variable (intern (concat "rcd-db-completing-table-history-" table))))
`(if (boundp ,variable)
(quote ,variable)
(progn
(defvar ,variable nil ,(format "History for table `%s'" table))
(quote ,variable)))))
The above macro expands into following:
(macroexpand '(rcd-db-completing-table-history "var-name")) ⇒ (if (boundp rcd-db-completing-table-history-var-name) 'rcd-db-completing-table-history-var-name (progn (defvar rcd-db-completing-table-history-var-name nil "History for table `var-name'") 'rcd-db-completing-table-history-var-name))
As I need a symbol for completing read and mini buffer functions.
However, here are the problems:
If I press C-M-x in the middle of the following function, the function
will be defined without erorr. If I press C-x C-e on the end I will
get debugging error: sequencep, var
Here I cannot understand why I cannot use `var' variable to call macro
from a function?
(defun my-fun-123 ()
(let ((var "new"))
(rcd-db-completing-table-history var)))
(my-fun-123)
Debugger entered--Lisp error: (wrong-type-argument sequencep var)
concat("rcd-db-completing-table-history-" var)
(intern (concat "rcd-db-completing-table-history-" table))
(let ((variable (intern (concat "rcd-db-completing-table-history-" table)))) (list 'if (list 'boundp variable) (list 'quote variable) (list 'progn (list 'defvar variable nil (format "History for table `%s'" table)) (list 'quote variable))))
(closure (t) (table) (let ((variable (intern (concat "rcd-db-completing-table-history-" table)))) (list 'if (list 'boundp variable) (list 'quote variable) (list 'progn (list 'defvar variable nil (format "History for table `%s'" table)) (list 'quote variable)))))(var)
(rcd-db-completing-table-history var)
(let ((var "new")) (rcd-db-completing-table-history var))
my-fun-123()
(progn (my-fun-123))
eval((progn (my-fun-123)) t)
elisp--eval-last-sexp(nil)
eval-last-sexp(nil)
funcall-interactively(eval-last-sexp nil)
call-interactively(eval-last-sexp nil nil)
command-execute(eval-last-sexp)
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
* RE: [External] : Why I cannot use this variable in macro call from function?
2021-06-08 13:10 Why I cannot use this variable in macro call from function? Jean Louis
@ 2021-06-08 13:41 ` Drew Adams
2021-06-08 14:47 ` Jean Louis
2021-06-08 17:14 ` Jean Louis
0 siblings, 2 replies; 28+ messages in thread
From: Drew Adams @ 2021-06-08 13:41 UTC (permalink / raw)
To: Jean Louis, Help GNU Emacs
> (defmacro rcd-db-completing-table-history (table)
> (let ((variable
> (intern
> (concat "rcd-db-completing-table-history-"
> table))))
> (defun my-fun-123 ()
> (let ((var "new"))
> (rcd-db-completing-table-history var)))
>
> (my-fun-123)
>
> Debugger entered--Lisp error: (wrong-type-argument sequencep var)
> concat("rcd-db-completing-table-history-" var)
You are passing the symbol `var' as the arg
to your macro. Macros don't automatically
evaluate their args. What you are expecting
is presumably to pass the _value_ of symbol
`var', i.e., treat the symbol as a variable
and pass its value.
^ permalink raw reply [flat|nested] 28+ messages in thread
* Re: [External] : Why I cannot use this variable in macro call from function?
2021-06-08 13:41 ` [External] : " Drew Adams
@ 2021-06-08 14:47 ` Jean Louis
2021-06-08 17:14 ` Jean Louis
1 sibling, 0 replies; 28+ messages in thread
From: Jean Louis @ 2021-06-08 14:47 UTC (permalink / raw)
To: Drew Adams; +Cc: Help GNU Emacs
* Drew Adams <drew.adams@oracle.com> [2021-06-08 16:42]:
> > (defmacro rcd-db-completing-table-history (table)
> > (let ((variable
> > (intern
> > (concat "rcd-db-completing-table-history-"
> > table))))
>
> > (defun my-fun-123 ()
> > (let ((var "new"))
> > (rcd-db-completing-table-history var)))
> >
> > (my-fun-123)
> >
> > Debugger entered--Lisp error: (wrong-type-argument sequencep var)
> > concat("rcd-db-completing-table-history-" var)
>
> You are passing the symbol `var' as the arg
> to your macro. Macros don't automatically
> evaluate their args. What you are expecting
> is presumably to pass the _value_ of symbol
> `var', i.e., treat the symbol as a variable
> and pass its value.
I hoped I will solve it with the function `symbol-value', but this
does not work:
(let ((var "new-table"))
(rcd-db-completing-table-history (symbol-value var)))
How do you mean?
--
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
* Re: [External] : Why I cannot use this variable in macro call from function?
2021-06-08 13:41 ` [External] : " Drew Adams
2021-06-08 14:47 ` Jean Louis
@ 2021-06-08 17:14 ` Jean Louis
2021-06-08 18:31 ` tomas
1 sibling, 1 reply; 28+ messages in thread
From: Jean Louis @ 2021-06-08 17:14 UTC (permalink / raw)
To: Drew Adams; +Cc: Help GNU Emacs
Major problem is that this does not behave how I expect it to behave:
(defvar (intern "my-function-123") nil)
(type-of 'my-function-123) ⇒ symbol
NOT WORKING:
(defvar 'my-function-123 nil)
(defvar (intern "my-function-123") nil):
Debugger entered--Lisp error: (wrong-type-argument symbolp (intern "my-function-123"))
boundp((intern "my-function-123"))
elisp--eval-defun-1((defvar (intern "my-function-123") nil))
elisp--eval-last-sexp(nil)
eval-last-sexp(nil)
funcall-interactively(eval-last-sexp nil)
call-interactively(eval-last-sexp nil nil)
command-execute(eval-last-sexp)
Though it says that after `defvar' should come SYMBOL
defvar is a special form in ‘src/eval.c’.
(defvar SYMBOL &optional INITVALUE DOCSTRING)
Probably introduced at or before Emacs version 1.5.
Define SYMBOL as a variable, and return SYMBOL.
--
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
* Re: [External] : Why I cannot use this variable in macro call from function?
2021-06-08 17:14 ` Jean Louis
@ 2021-06-08 18:31 ` tomas
2021-06-08 18:37 ` Oops function? tomas
2021-06-08 19:27 ` [SOLVED with `eval']: Why I cannot use this variable in macro call from function? Jean Louis
0 siblings, 2 replies; 28+ messages in thread
From: tomas @ 2021-06-08 18:31 UTC (permalink / raw)
To: Drew Adams, Help GNU Emacs
[-- Attachment #1: Type: text/plain, Size: 2670 bytes --]
On Tue, Jun 08, 2021 at 08:14:08PM +0300, Jean Louis wrote:
> Major problem is that this does not behave how I expect it to behave:
>
> (defvar (intern "my-function-123") nil)
>
> (type-of 'my-function-123) ⇒ symbol
>
> NOT WORKING:
> (defvar 'my-function-123 nil)
Read the docs: defvar is a special form, not a function. Its arguments
**don't get evaluated**. That's something you don't want special forms
to do.
And 'my-function-123 *is*not*a*symbol*. It is a handy shorthand for
(quote my-function-123).
So what your (defvar...) above is seeing is:
(defvar (quote my-function123) nil)
and it complains.
Same for the (intern...) attempt: your defvar sees the whole two-element
S-expression (intern "my-function-123") and says:
> (defvar (intern "my-function-123") nil):
>
> Debugger entered--Lisp error: (wrong-type-argument symbolp (intern "my-function-123"))
> boundp((intern "my-function-123"))
> elisp--eval-defun-1((defvar (intern "my-function-123") nil))
> elisp--eval-last-sexp(nil)
> eval-last-sexp(nil)
> funcall-interactively(eval-last-sexp nil)
> call-interactively(eval-last-sexp nil nil)
> command-execute(eval-last-sexp)
"HEY! I have been built to accept a symbol as my first arg, and am
getting this funny list '(intern "my-function-123). Help!"
> Though it says that after `defvar' should come SYMBOL
>
> defvar is a special form in ‘src/eval.c’.
>
> (defvar SYMBOL &optional INITVALUE DOCSTRING)
>
> Probably introduced at or before Emacs version 1.5.
>
> Define SYMBOL as a variable, and return SYMBOL.
Exactly. A SYMBOL and not a form.
Read again the chapter on special forms from the fine elisp manual.
Please, really do.
10.2.7 Special Forms
--------------------
A “special form” is a primitive function specially marked so that its
arguments are not all evaluated. Most special forms define control
structures or perform variable bindings—things which functions cannot
do.
We are so accustomed to things being evaluated from the inside-out
that we read 'foo as "the symbol foo", and (+ 3 2) as 5. They are
not. They are expressions which (eventually) evaluate to the symbol
foo and to 5, if we let them. Macros and special forms don't let
them, to give you, the programmer, the chance to intervene before.
The price you pay is that it's sometimes difficult to wrap one's
head around it.
Someone said upthread macros are harder than functions. I think that's
spot-on.
That said, they are different tools, too. You could turn a screw with
a bandsaw, but it's generally not recommended.
Cheers
- t
[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 198 bytes --]
^ permalink raw reply [flat|nested] 28+ messages in thread
* Oops function?
2021-06-08 18:31 ` tomas
@ 2021-06-08 18:37 ` tomas
2021-06-08 19:27 ` [SOLVED with `eval']: Why I cannot use this variable in macro call from function? Jean Louis
1 sibling, 0 replies; 28+ messages in thread
From: tomas @ 2021-06-08 18:37 UTC (permalink / raw)
To: Help GNU Emacs
[-- Attachment #1: Type: text/plain, Size: 98 bytes --]
Oops. Mail went to Drew although I was answering to Jean Louis.
I should've checked, sorry.
- t
[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 198 bytes --]
^ permalink raw reply [flat|nested] 28+ messages in thread
* [SOLVED with `eval']: Why I cannot use this variable in macro call from function?
2021-06-08 18:31 ` tomas
2021-06-08 18:37 ` Oops function? tomas
@ 2021-06-08 19:27 ` Jean Louis
2021-06-08 20:03 ` tomas
1 sibling, 1 reply; 28+ messages in thread
From: Jean Louis @ 2021-06-08 19:27 UTC (permalink / raw)
To: tomas; +Cc: Help GNU Emacs
Thanks Tomas.
I know you have sharp mind. Is there a way to dynamically
generate global variable based on a string and use it as history?
It's interesting how this works:
(defmacro rcd-gen-defvar (name description)
`(defvar ,(intern name) nil ,description))
Now I can repeat and use the below and it will remember history:
(read-from-minibuffer "Tell me: " nil nil nil (rcd-gen-defvar "my-history" "This is history"))
I was expecting it NOT to work as I was expecting `defvar' to be
repeated and to nullify the value, but it does not.
In the next step all what I would need is to dynamically
give "my-history" to macro `rcd-gen-defvar', but as I don't know
how to do that, heaven thanks there is function `eval' which
solves the problem.
Now this function is to create the history variable if it does
not exist and basically returns its symbol for completion
function like the one below.
(defun rcd-db-completing-table-history (table)
(let ((rcd-symbol (intern (concat "rcd-db-completing-table-history-" table)))
(description (format "History for table `%s'" table)))
(if (boundp rcd-symbol)
rcd-symbol
(eval (list 'defvar rcd-symbol nil description)))))
(defun rcd-db-combo-selection (table)
(let* ((prompt (format "Select within table `%s': " table))
(prompt (append-colon-space prompt))
(sql (format "SELECT * FROM %s_combo ORDER BY id DESC" table)))
(rcd-completing-read-sql-hash prompt sql cf-db (rcd-db-completing-table-history table))))
I have lost hours trying all possible combinations. From Lisp I
do expect those combinations to be possible. At least `eval'
works. It saves me continous variable definitions for each new
foreign referenced table in PostgreSQL. I guess there must be few
hundreds of such variables overall.
Like table people_prefixes now receivs the variable
`rcd-db-completing-table-history-prefixes' automatically for
history. Table people_sufixes receives
`rcd-db-completing-table-history-suffixes' automatically as that
is useful to minimize repetitions and to avoid errors with the
mixed input history.
--
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
* Re: [SOLVED with `eval']: Why I cannot use this variable in macro call from function?
2021-06-08 19:27 ` [SOLVED with `eval']: Why I cannot use this variable in macro call from function? Jean Louis
@ 2021-06-08 20:03 ` tomas
2021-06-08 20:06 ` Sorry again tomas
2021-06-08 20:12 ` [SOLVED with `eval']: Why I cannot use this variable in macro call from function? Jean Louis
0 siblings, 2 replies; 28+ messages in thread
From: tomas @ 2021-06-08 20:03 UTC (permalink / raw)
To: Drew Adams, Help GNU Emacs
[-- Attachment #1: Type: text/plain, Size: 1176 bytes --]
On Tue, Jun 08, 2021 at 10:27:04PM +0300, Jean Louis wrote:
> Thanks Tomas.
Glad I could help :)
> I know you have sharp mind.
Don't let apperances mis-lead you...
> Is there a way to dynamically
> generate global variable based on a string and use it as history?
>
> It's interesting how this works:
>
> (defmacro rcd-gen-defvar (name description)
> `(defvar ,(intern name) nil ,description))
>
> Now I can repeat and use the below and it will remember history:
>
> (read-from-minibuffer "Tell me: " nil nil nil (rcd-gen-defvar "my-history" "This is history"))
>
> I was expecting it NOT to work as I was expecting `defvar' to be
> repeated and to nullify the value, but it does not.
[rest snipped]
Sorry, Jean Louis, I can't understand what you are after.
Even after reading you mail a couple of times.
Sometimes (but I'm not sure either), I have the impression
that you try to do too many things at once. Try to break them
down into little pieces to give your interlocutors at least
a small chance.
You want to define a variable whose name you can only know
at run time? Did I understand that correctly?
Cheers
- t
[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 198 bytes --]
^ permalink raw reply [flat|nested] 28+ messages in thread
* Sorry again
2021-06-08 20:03 ` tomas
@ 2021-06-08 20:06 ` tomas
2021-06-08 20:12 ` [SOLVED with `eval']: Why I cannot use this variable in macro call from function? Jean Louis
1 sibling, 0 replies; 28+ messages in thread
From: tomas @ 2021-06-08 20:06 UTC (permalink / raw)
To: Drew Adams, Help GNU Emacs
[-- Attachment #1: Type: text/plain, Size: 264 bytes --]
Gah. It happened again. Now at least I know why.
Something is setting the mail-followup-to help-gnu-emacs@gnu.org (which is
OK, for those who don't want a copy) AND to Drew Adams (which IMO is
not so OK).
I'll try to be more careful next time.
sorry again
- t
[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 198 bytes --]
^ permalink raw reply [flat|nested] 28+ messages in thread
* Re: [SOLVED with `eval']: Why I cannot use this variable in macro call from function?
2021-06-08 20:03 ` tomas
2021-06-08 20:06 ` Sorry again tomas
@ 2021-06-08 20:12 ` Jean Louis
2021-06-08 20:23 ` tomas
1 sibling, 1 reply; 28+ messages in thread
From: Jean Louis @ 2021-06-08 20:12 UTC (permalink / raw)
To: tomas; +Cc: Help GNU Emacs
* tomas@tuxteam.de <tomas@tuxteam.de> [2021-06-08 23:04]:
> You want to define a variable whose name you can only know
> at run time? Did I understand that correctly?
Exactly. The dynamic history variable in this case.
- The database table "notes" references the table "people"
- User edits the table "notes" and wish to re-assign the note to
another person; pressing up down brings back the history items for
that specific table, and the variable becomes automatically defined
as `people-history'
- now imagine hundreds of such variables and they grow each week
dynamically whenever some new table gets added;
Larger problem is the mixed history causes problems, so this way there
is no global history.
--
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
* Re: [SOLVED with `eval']: Why I cannot use this variable in macro call from function?
2021-06-08 20:12 ` [SOLVED with `eval']: Why I cannot use this variable in macro call from function? Jean Louis
@ 2021-06-08 20:23 ` tomas
2021-06-08 20:38 ` Jean Louis
2021-06-08 20:47 ` Jean Louis
0 siblings, 2 replies; 28+ messages in thread
From: tomas @ 2021-06-08 20:23 UTC (permalink / raw)
To: Jean Louis, Help GNU Emacs
[-- Attachment #1: Type: text/plain, Size: 1332 bytes --]
On Tue, Jun 08, 2021 at 11:12:26PM +0300, Jean Louis wrote:
[it seems to be your mailer which is setting up Drew in
the mail-followup-to: I exchanged the recipient]
> * tomas@tuxteam.de <tomas@tuxteam.de> [2021-06-08 23:04]:
> > You want to define a variable whose name you can only know
> > at run time? Did I understand that correctly?
>
> Exactly.
OK. Since you can't go back in time, you can set the variable
for a part of the program which isn't yet compiled. Otherwise
you'd have to "un-compile" your program first, right?
> The dynamic history variable in this case.
One step at a time.
> - The database table "notes" references the table "people"
>
> - User edits the table "notes" and wish to re-assign the note to
> another person; pressing up down brings back the history items for
> that specific table, and the variable becomes automatically defined
> as `people-history'
>
> - now imagine hundreds of such variables and they grow each week
> dynamically whenever some new table gets added;
>
> Larger problem is the mixed history causes problems, so this way there
> is no global history.
...but I have the hunch that a variable might not be the right
tool here. It smells of "dictionary" (hash or something). But
I might be wrong.
Cheers
- t
[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 198 bytes --]
^ permalink raw reply [flat|nested] 28+ messages in thread
* Re: [SOLVED with `eval']: Why I cannot use this variable in macro call from function?
2021-06-08 20:23 ` tomas
@ 2021-06-08 20:38 ` Jean Louis
2021-06-08 20:47 ` Jean Louis
1 sibling, 0 replies; 28+ messages in thread
From: Jean Louis @ 2021-06-08 20:38 UTC (permalink / raw)
To: tomas; +Cc: Help GNU Emacs
* tomas@tuxteam.de <tomas@tuxteam.de> [2021-06-08 23:23]:
> The dynamic history variable in this case.
>
> One step at a time.
> ...but I have the hunch that a variable might not be the right
> tool here. It smells of "dictionary" (hash or something). But
> I might be wrong.
It is history variable for completing-read function.
--
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
* Re: [SOLVED with `eval']: Why I cannot use this variable in macro call from function?
2021-06-08 20:23 ` tomas
2021-06-08 20:38 ` Jean Louis
@ 2021-06-08 20:47 ` Jean Louis
2021-06-09 6:09 ` tomas
1 sibling, 1 reply; 28+ messages in thread
From: Jean Louis @ 2021-06-08 20:47 UTC (permalink / raw)
To: tomas; +Cc: Help GNU Emacs
* tomas@tuxteam.de <tomas@tuxteam.de> [2021-06-08 23:23]:
> OK. Since you can't go back in time, you can set the variable
> for a part of the program which isn't yet compiled. Otherwise
> you'd have to "un-compile" your program first, right?
Should I worry now? Sounds like I should
(defun my-hello (string)
(interactive "sYour name: ")
(eval (list 'message-box (concat "Hello " string))))
If that works dynamically then my function should also work.
--
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
* Re: [SOLVED with `eval']: Why I cannot use this variable in macro call from function?
2021-06-08 20:47 ` Jean Louis
@ 2021-06-09 6:09 ` tomas
2021-06-09 6:42 ` Jean Louis
0 siblings, 1 reply; 28+ messages in thread
From: tomas @ 2021-06-09 6:09 UTC (permalink / raw)
To: Help GNU Emacs
[-- Attachment #1: Type: text/plain, Size: 2391 bytes --]
On Tue, Jun 08, 2021 at 11:47:09PM +0300, Jean Louis wrote:
> * tomas@tuxteam.de <tomas@tuxteam.de> [2021-06-08 23:23]:
> > OK. Since you can't go back in time, you can set the variable
> > for a part of the program which isn't yet compiled. Otherwise
> > you'd have to "un-compile" your program first, right?
>
> Should I worry now? Sounds like I should
>
> (defun my-hello (string)
> (interactive "sYour name: ")
> (eval (list 'message-box (concat "Hello " string))))
>
> If that works dynamically then my function should also work.
For some value of "work", yes. I propose doing the following
experiments:
Start always in a new "lisp interaction buffer". E.g. do
* Experiment 1
C-x b *my-new-experiment*, then M-x lisp-interaction-mode
First, type in
lexical-binding
...with point at the end of the line (or the next line) C-x e to
eval this, make sure the minubuffer shows "t". We have lexical
binding.
Now enter this
(let ((some-var 42)) ; just to set up some scope
(eval '(setq that-other-var 43))
(message "%S\n" that-other-var))
You'll see "43" in your minibuffer. We managed to set the dynamically
"defined" variable "that-other-var" to 43. Yay! Now enter
that-other-var
...and again C-x e. Minibuffer says... 43. The variable escaped the
scope. Bad variable, but hey, that's how setq goes, no?
* Experiment 2
Make new lisp interaction buffer, as above. Make sure you have
lexical binding (when experimenting, always change at most one
thing at a time, right?). Now:
(let ((some-var 42)
(that-other-var 44)) ; bind that-other-var locally
(eval '(setq that-other-var 43))
(message "%S\n" that-other-var))
Again, minibuffer says 43. Now...
that-other-var
...and C-x e. What does minibuffer say? Is that right or wrong?
Explain.
I guess you'll need a more differentiated model than just "works".
Works how? Do you want it to "work" like that? If yes, then fine.
And then there is the question of collaboration: if you want others
to understand your programs (and vice-versa), then there are even
more (!) criteria.
A very wise person [1] once said that he doesn't write programs
to get the computer to do what he wants, but to convince his
colleagues that the computer is doing the right thing.
Cheers
[1] ISTR that it was Donald Knuth.
- t
[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 198 bytes --]
^ permalink raw reply [flat|nested] 28+ messages in thread
* Re: [SOLVED with `eval']: Why I cannot use this variable in macro call from function?
2021-06-09 6:09 ` tomas
@ 2021-06-09 6:42 ` Jean Louis
2021-06-09 6:51 ` tomas
0 siblings, 1 reply; 28+ messages in thread
From: Jean Louis @ 2021-06-09 6:42 UTC (permalink / raw)
To: tomas; +Cc: Help GNU Emacs
* tomas@tuxteam.de <tomas@tuxteam.de> [2021-06-09 09:11]:
> You'll see "43" in your minibuffer. We managed to set the dynamically
> "defined" variable "that-other-var" to 43. Yay! Now enter
>
> that-other-var
>
> ...and again C-x e. Minibuffer says... 43. The variable escaped the
> scope. Bad variable, but hey, that's how setq goes, no?
Yes. I did it.
> * Experiment 2
>
> Make new lisp interaction buffer, as above. Make sure you have
> lexical binding (when experimenting, always change at most one
> thing at a time, right?). Now:
>
> (let ((some-var 42)
> (that-other-var 44)) ; bind that-other-var locally
> (eval '(setq that-other-var 43))
> (message "%S\n" that-other-var))
>
> Again, minibuffer says 43. Now...
>
> that-other-var
>
> ...and C-x e. What does minibuffer say? Is that right or wrong?
> Explain.
The one bound locally got 44, it was protected from a global
variable. That is so far expected. If I wish for example avoid case
sensitive entries, I do:
(let ((completion-ignore-case t)
(collection '("One" "Two")))
(completing-read "Choice: " collection nil t))
In that case the global variable `completion-ignore-case' is nil,
but I bind it temporarily globally to T, for better user
experience.
> I guess you'll need a more differentiated model than just "works".
> Works how? Do you want it to "work" like that? If yes, then fine.
Here is the function that just works, it asks for global
variable. If I would know better way, I would do it and if you
know some other way to dynamically assign global variable let me
know:
(defun rcd-db-completing-table-history (table)
"Return symbol of history variable for TABLE.
If TABLE is \"businesses\" the symbol will become
`rcd-db-completing-table-history-businesses' and it will be used
for functions `completing-read' and `read-from-minibuffer'
history.
If a dynamically generated variable does not exist, it will be
generated on the fly."
(let ((rcd-symbol (intern (concat "rcd-db-completing-table-history-" table)))
(description (format "History for table `%s'" table)))
(if (boundp rcd-symbol)
rcd-symbol
(eval (list 'defvar rcd-symbol nil description)))))
Just like any code, the above (eval (list 'defvar rcd-symbol nil
description)) is understandable only to people who know what
eval, list, defvar and variables mean. We are now in
collaboration and I am asking if there is better way to
dynamically assign a global variable if it does not exist and
return a symbol of it.
What I don't know is why the function work as I am somehow
expecting that new evaluation of (defvar ex-sting-variable nil)
would make it nil, but it does not and history is remembered.
> A very wise person [1] once said that he doesn't write programs
> to get the computer to do what he wants, but to convince his
> colleagues that the computer is doing the right thing.
Fine, but that way I don't get my dynamically assigned global
variables. (づ。◕‿‿◕。)づ
--
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
* Re: [SOLVED with `eval']: Why I cannot use this variable in macro call from function?
2021-06-09 6:42 ` Jean Louis
@ 2021-06-09 6:51 ` tomas
2021-06-09 7:03 ` Jean Louis
0 siblings, 1 reply; 28+ messages in thread
From: tomas @ 2021-06-09 6:51 UTC (permalink / raw)
To: Help GNU Emacs
[-- Attachment #1: Type: text/plain, Size: 1476 bytes --]
On Wed, Jun 09, 2021 at 09:42:00AM +0300, Jean Louis wrote:
> * tomas@tuxteam.de <tomas@tuxteam.de> [2021-06-09 09:11]:
> > You'll see "43" in your minibuffer. We managed to set the dynamically
> > "defined" variable "that-other-var" to 43. Yay! Now enter
> >
> > that-other-var
> >
> > ...and again C-x e. Minibuffer says... 43. The variable escaped the
> > scope. Bad variable, but hey, that's how setq goes, no?
>
> Yes. I did it.
>
> > * Experiment 2
> >
> > Make new lisp interaction buffer, as above. Make sure you have
> > lexical binding (when experimenting, always change at most one
> > thing at a time, right?). Now:
> >
> > (let ((some-var 42)
> > (that-other-var 44)) ; bind that-other-var locally
> > (eval '(setq that-other-var 43))
> > (message "%S\n" that-other-var))
> >
> > Again, minibuffer says 43. Now...
> >
> > that-other-var
> >
> > ...and C-x e. What does minibuffer say? Is that right or wrong?
> > Explain.
>
> The one bound locally got 44, it was protected from a global
> variable. That is so far expected. If I wish for example avoid case
> sensitive entries, I do:
Was "that-other-var" defined outside the `let'? If yes, what value
did it have? If not, why not?
[skipping the rest. I don't want even to think wrapping my head
around all that before basic things are not cleared. You'll have
to find yourself another sparring partner for this one, sorry]
Cheers
- t
[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 198 bytes --]
^ permalink raw reply [flat|nested] 28+ messages in thread
* Re: [SOLVED with `eval']: Why I cannot use this variable in macro call from function?
2021-06-09 6:51 ` tomas
@ 2021-06-09 7:03 ` Jean Louis
2021-06-09 7:39 ` tomas
0 siblings, 1 reply; 28+ messages in thread
From: Jean Louis @ 2021-06-09 7:03 UTC (permalink / raw)
To: tomas; +Cc: Help GNU Emacs
* tomas@tuxteam.de <tomas@tuxteam.de> [2021-06-09 09:52]:
> [skipping the rest. I don't want even to think wrapping my head
> around all that before basic things are not cleared. You'll have
> to find yourself another sparring partner for this one, sorry]
Feel free to be more direct. If I don't see what you see and that is
exactly what I wish to know, then tell me. If you remain mysterious
even while it is clear that I don't see what you are pointing out, how
do you expect me to see it without explanation?
I had problems constructing a macro, then I got information it is
special form, it will not work, etc. So it works now with `eval'.
The bottom question is if some other solution exists or not to
dynamically create completing-read and read-from-minibuffer history
variables.
--
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
* Re: [SOLVED with `eval']: Why I cannot use this variable in macro call from function?
2021-06-09 7:03 ` Jean Louis
@ 2021-06-09 7:39 ` tomas
2021-06-09 8:22 ` Jean Louis
0 siblings, 1 reply; 28+ messages in thread
From: tomas @ 2021-06-09 7:39 UTC (permalink / raw)
To: Help GNU Emacs
[-- Attachment #1: Type: text/plain, Size: 1622 bytes --]
On Wed, Jun 09, 2021 at 10:03:16AM +0300, Jean Louis wrote:
> * tomas@tuxteam.de <tomas@tuxteam.de> [2021-06-09 09:52]:
> > [skipping the rest. I don't want even to think wrapping my head
> > around all that before basic things are not cleared. You'll have
> > to find yourself another sparring partner for this one, sorry]
>
> Feel free to be more direct. If I don't see what you see and that is
> exactly what I wish to know, then tell me. If you remain mysterious
> even while it is clear that I don't see what you are pointing out, how
> do you expect me to see it without explanation?
>
> I had problems constructing a macro, then I got information it is
> special form, it will not work, etc. So it works now with `eval'.
>
> The bottom question is if some other solution exists or not to
> dynamically create completing-read and read-from-minibuffer history
> variables.
You snipped the (for me) interesting part: did you notice how
`eval' jumps over the local declaration? It doesn't even /see/
it, the defun whithin the eval munged with the outer scope
(which might be buffer-local or just global).
You could as well have messed with the obarray [1] directly.
If this is what you want, fine. If it's not, think again. I can't
even venture a guess towards what you have in mind, I'm that bad
at interpreting what you write.
And then there is the issue of how readable your code becomes,
which will be important or not, depending on whether you want
others to read it or not.
Cheers
[1] Finding which obarray to munge is left as an exercise for
the reader.
- t
[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 198 bytes --]
^ permalink raw reply [flat|nested] 28+ messages in thread
* Re: [SOLVED with `eval']: Why I cannot use this variable in macro call from function?
2021-06-09 7:39 ` tomas
@ 2021-06-09 8:22 ` Jean Louis
2021-06-09 8:54 ` tomas
0 siblings, 1 reply; 28+ messages in thread
From: Jean Louis @ 2021-06-09 8:22 UTC (permalink / raw)
To: tomas; +Cc: Help GNU Emacs
* tomas@tuxteam.de <tomas@tuxteam.de> [2021-06-09 10:40]:
> You snipped the (for me) interesting part: did you notice how
> `eval' jumps over the local declaration?
Do you mean variables within `let'?
(defun rcd-db-completing-table-history (table)
"Return symbol of history variable for TABLE.
If TABLE is \"businesses\" the symbol will become
`rcd-db-completing-table-history-businesses' and it will be used
for functions `completing-read' and `read-from-minibuffer'
history.
If a dynamically generated variable does not exist, it will be
generated on the fly."
(let ((rcd-symbol (intern (concat "rcd-db-completing-table-history-" table)))
(description (format "History for table `%s'" table)))
(if (boundp rcd-symbol)
rcd-symbol
(eval (list 'defvar rcd-symbol nil description)))))
In the above function I want to get a symbol of a global history
variable.
read-from-minibuffer is a built-in function in ‘C source code’.
(read-from-minibuffer PROMPT &optional INITIAL-CONTENTS KEYMAP READ
HIST DEFAULT-VALUE INHERIT-INPUT-METHOD)
(completing-read PROMPT COLLECTION &optional PREDICATE REQUIRE-MATCH
INITIAL-INPUT HIST DEF INHERIT-INPUT-METHOD)
History symbol HIST is used in the above functions. There are many
various columns and database tables and is for time being difficult to
find which one references to which one. New tables are created each in
a while, new variables would need to be created, that is not
handy. Users may create new variables too. It is easier to dynamically
(not related to dynamic bindings) assign global variables that keep
the history for `completing-read' and `read-from-minibuffer'. It is
useful not to mess with the global history.
> It doesn't even /see/ it, the defun whithin the eval munged with the
> outer scope (which might be buffer-local or just global).
There is `defvar' within the eval, it defines global variables. I
don't knof is such variable should be really buffer local, most
probably not as user may invoke functions from outside of the common
modes or buffers.
> If this is what you want, fine. If it's not, think again. I can't
> even venture a guess towards what you have in mind, I'm that bad
> at interpreting what you write.
Maybe you should start using history variables in
`read-from-minibuffer' or `completing-read' and you will understand
that one has to give some symbol. In the context of editing column
values in multiple database tables the difficulty is that one would
need to assign a history variable to each such column names. Columns
are also changeable, they could be even changed by user on the fly. If
I hard code the history variable then user would need to modify the
source. This way history variables are dynamically created without
modification of the source.
I have explained what I want:
- to dynamically (not related to global bindings) request for a symbol
representing a global variable;
- function or macro should either create the new global variable and
return the symbol or return the existing symbol if variable exists
already;
The bottom line is, what is the solution?
The only solution that works is in the above function, maybe something
else would work but I would not know how to implement it.
> And then there is the issue of how readable your code becomes,
> which will be important or not, depending on whether you want
> others to read it or not.
Readability can be improved, but if there is no functionality why
focus on readability?
You imply you know how to make it, so let me know how to make it
better.
--
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
* Re: [SOLVED with `eval']: Why I cannot use this variable in macro call from function?
2021-06-09 8:22 ` Jean Louis
@ 2021-06-09 8:54 ` tomas
2021-06-09 10:56 ` Jean Louis
0 siblings, 1 reply; 28+ messages in thread
From: tomas @ 2021-06-09 8:54 UTC (permalink / raw)
To: Help GNU Emacs
[-- Attachment #1: Type: text/plain, Size: 543 bytes --]
On Wed, Jun 09, 2021 at 11:22:38AM +0300, Jean Louis wrote:
> * tomas@tuxteam.de <tomas@tuxteam.de> [2021-06-09 10:40]:
> > You snipped the (for me) interesting part: did you notice how
> > `eval' jumps over the local declaration?
>
> Do you mean variables within `let'?
Yes, it doesn't see them :)
[...]
> You imply you know how to make it, so let me know how to make it
> better.
No, I have no idea. Still trying to wrap my head around "it". And
I won't start with history -- one rabbit hole too much :)
Cheers
- t
[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 198 bytes --]
^ permalink raw reply [flat|nested] 28+ messages in thread
* Re: [SOLVED with `eval']: Why I cannot use this variable in macro call from function?
2021-06-09 8:54 ` tomas
@ 2021-06-09 10:56 ` Jean Louis
2021-06-09 11:33 ` tomas
0 siblings, 1 reply; 28+ messages in thread
From: Jean Louis @ 2021-06-09 10:56 UTC (permalink / raw)
To: tomas; +Cc: Help GNU Emacs
* tomas@tuxteam.de <tomas@tuxteam.de> [2021-06-09 11:54]:
> On Wed, Jun 09, 2021 at 11:22:38AM +0300, Jean Louis wrote:
> > * tomas@tuxteam.de <tomas@tuxteam.de> [2021-06-09 10:40]:
> > > You snipped the (for me) interesting part: did you notice how
> > > `eval' jumps over the local declaration?
> >
> > Do you mean variables within `let'?
>
> Yes, it doesn't see them :)
Maybe in theory it does not see, but in reality it does see it as
`list' is evaluated before `eval', so the interned `rcd-symbol' and
variable `description' they get evaluated before `eval'.
(defun rcd-db-completing-table-history (table)
"Return symbol of history variable for TABLE.
If TABLE is \"businesses\" the symbol will become
`rcd-db-completing-table-history-businesses' and it will be used
for functions `completing-read' and `read-from-minibuffer'
history.
If a dynamically generated variable does not exist, it will be
generated on the fly."
(let ((rcd-symbol (intern (concat "rcd-db-completing-table-history-" table)))
(description (format "History for table `%s'" table)))
(if (boundp rcd-symbol)
rcd-symbol
(eval (list 'defvar rcd-symbol nil description)))))
--
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
* Re: [SOLVED with `eval']: Why I cannot use this variable in macro call from function?
2021-06-09 10:56 ` Jean Louis
@ 2021-06-09 11:33 ` tomas
2021-06-09 14:39 ` Jean Louis
0 siblings, 1 reply; 28+ messages in thread
From: tomas @ 2021-06-09 11:33 UTC (permalink / raw)
To: Help GNU Emacs
[-- Attachment #1: Type: text/plain, Size: 1157 bytes --]
On Wed, Jun 09, 2021 at 01:56:45PM +0300, Jean Louis wrote:
> * tomas@tuxteam.de <tomas@tuxteam.de> [2021-06-09 11:54]:
> > On Wed, Jun 09, 2021 at 11:22:38AM +0300, Jean Louis wrote:
> > > * tomas@tuxteam.de <tomas@tuxteam.de> [2021-06-09 10:40]:
> > > > You snipped the (for me) interesting part: did you notice how
> > > > `eval' jumps over the local declaration?
> > >
> > > Do you mean variables within `let'?
> >
> > Yes, it doesn't see them :)
>
> Maybe in theory it does not see, but in reality it does see it as
> `list' is evaluated before `eval', so the interned `rcd-symbol' and
> variable `description' they get evaluated before `eval'.
That sentence doesn't make any sense to me. It does or it doesn't.
I propose to you the next experiment:
* experiment 3
(let ()
(let ((x 42))
(eval '(progn (setq x 43) (message "in eval: x is %S" x)))
(message "inner let: x is %S" x))
(message "outer let: x is %S" x))
(you might have to switch to the *Messages* buffer to see all three
messages).
What are the results? Do they correspond to your expectations? If
not, why not?
Cheers
- t
[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 198 bytes --]
^ permalink raw reply [flat|nested] 28+ messages in thread
* Re: [SOLVED with `eval']: Why I cannot use this variable in macro call from function?
2021-06-09 11:33 ` tomas
@ 2021-06-09 14:39 ` Jean Louis
2021-06-09 16:41 ` tomas
2021-06-10 2:10 ` Robert Thorpe
0 siblings, 2 replies; 28+ messages in thread
From: Jean Louis @ 2021-06-09 14:39 UTC (permalink / raw)
To: tomas; +Cc: Help GNU Emacs
;; -*- lexical-binding: t; -*-
* tomas@tuxteam.de <tomas@tuxteam.de> [2021-06-09 14:35]:
> On Wed, Jun 09, 2021 at 01:56:45PM +0300, Jean Louis wrote:
> > * tomas@tuxteam.de <tomas@tuxteam.de> [2021-06-09 11:54]:
> > > On Wed, Jun 09, 2021 at 11:22:38AM +0300, Jean Louis wrote:
> > > > * tomas@tuxteam.de <tomas@tuxteam.de> [2021-06-09 10:40]:
> > > > > You snipped the (for me) interesting part: did you notice how
> > > > > `eval' jumps over the local declaration?
> > > >
> > > > Do you mean variables within `let'?
> > >
> > > Yes, it doesn't see them :)
> >
> > Maybe in theory it does not see, but in reality it does see it as
> > `list' is evaluated before `eval', so the interned `rcd-symbol' and
> > variable `description' they get evaluated before `eval'.
> That sentence doesn't make any sense to me. It does or it doesn't.
Well, I get confused too, you said that it does not see, but it is
obvious that it does see.
> I propose to you the next experiment:
>
> * experiment 3
>
> (let ()
> (let ((x 42))
> (eval '(progn (setq x 43) (message "in eval: x is %S" x)))
> (message "inner let: x is %S" x))
> (message "outer let: x is %S" x))
>
> (you might have to switch to the *Messages* buffer to see all three
> messages).
The outer scope does not see the inner scope.
Then the buffer *Backtrace* jumps up:
Debugger entered--Lisp error: (void-variable x)
(message "outer let: x is %S" x)
(let nil (let ((x 42)) (eval '(progn (setq x 43) (message "in eval: x is %S" x))) (message "inner let: x is %S" x)) (message "outer let: x is %S" x))
eval((let nil (let ((x 42)) (eval '(progn (setq x 43) (message "in eval: x is %S" x))) (message "inner let: x is %S" x)) (message "outer let: x is %S" x)) nil)
elisp--eval-last-sexp(nil)
eval-last-sexp(nil)
funcall-interactively(eval-last-sexp nil)
call-interactively(eval-last-sexp nil nil)
command-execute(eval-last-sexp)
> What are the results? Do they correspond to your expectations? If
> not, why not?
I did not have any expectations for that piece of code and that
one does not generate new global variables to return the symbol
for history, which is what I need, and what is solved with `eval'
nicely.
Look here:
(let ((x 42))
(eval (list 'progn (setq x 43) (message "in eval: x is %S" x)))) ⇒ "in eval: x is 43"
that obviously does work nicely as the list gets evaluated before eval
receives it. At least I assume it is so, according to learning about
the LISP in general.
In your example you have given pure data to `eval' in which case the
variables within data don't get expanded.
There is other way to expand them but using `list':
(let ((x 43))
(eval `(+ 2 ,x))) ⇒ 45
It seems that this works too:
(let ((x 43))
(eval '(+ 3 x))) ⇒ 46
While this will not work:
(let ()
(let ((x 43))
(eval '(+ 3 x)))
x)
but this will also not work and is not related to `eval':
(let ()
(let ((x 43))
x)
x)
As how I see that code above from you it is by its meaning
similar to that one above.
By the way, `eval' is powerful LISP function in general, it
obviously has its uses when nothing else works.
Example here below is when Emacs Lisp is read from a
database. User can define a type of a page and how to process the
page, for example with (rcd-markdown wrs-text) which symbolic
expression is fetched from the database. Of course, by allowing
user to define any Emacs Lisp into database there are security
issues and those are solved with permissions.
rcd-cf.el:6444: (eval (car (read-from-string (rcd-db-get-entry "pagetypes" "pagetypes_elisp" type cf-db))))))
For some small functions I use `eval':
rcd-devel-utilities.el:57: (let ((result (eval (elisp--preceding-sexp))))
(defun replace-last-sexp ()
"Eval last sexp and replaces it in the buffer with its result."
(interactive)
(let ((result (eval (elisp--preceding-sexp))))
(kill-sexp -1)
(insert (format "%s" result))))
I can find I have been using it in the package `rcd-hash-edit.el'
very handy to edit visually a hash and dispatch the hash by
email, or other communication to collaborator:
(defun rcd-hash-create (symbol)
"Create hash NAME.
Argument SYMBOL will be created in global space."
(eval `(defvar ,(intern (symbol-name symbol)) (make-hash-table :test 'equal))))
I heard much talk of `eval' being bad, but that is not true
inherently. function is powerful and one can feed data to
function and get it evaluated. When public is supplying input to
`eval' then there are some safety issues, but nothing so much
more than without eval. People accept input without `eval' and
they forget quoting or parsing and people enter into web servers
or intrude into systems.
Let's not forget, this is LISP, it is for `eval'-ing.
Yet, nothing from the above is not helping to make dynamically
generated global variables, do you know how to solve it in the
second run without `eval'?
--
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
* Re: [SOLVED with `eval']: Why I cannot use this variable in macro call from function?
2021-06-09 14:39 ` Jean Louis
@ 2021-06-09 16:41 ` tomas
2021-06-10 2:10 ` Robert Thorpe
1 sibling, 0 replies; 28+ messages in thread
From: tomas @ 2021-06-09 16:41 UTC (permalink / raw)
To: Help GNU Emacs
[-- Attachment #1: Type: text/plain, Size: 4371 bytes --]
On Wed, Jun 09, 2021 at 05:39:25PM +0300, Jean Louis wrote:
> ;; -*- lexical-binding: t; -*-
> * tomas@tuxteam.de <tomas@tuxteam.de> [2021-06-09 14:35]:
> > On Wed, Jun 09, 2021 at 01:56:45PM +0300, Jean Louis wrote:
> > > * tomas@tuxteam.de <tomas@tuxteam.de> [2021-06-09 11:54]:
> > > > On Wed, Jun 09, 2021 at 11:22:38AM +0300, Jean Louis wrote:
> > > > > * tomas@tuxteam.de <tomas@tuxteam.de> [2021-06-09 10:40]:
> > > > > > You snipped the (for me) interesting part: did you notice how
> > > > > > `eval' jumps over the local declaration?
> > > > >
> > > > > Do you mean variables within `let'?
> > > >
> > > > Yes, it doesn't see them :)
> > >
> > > Maybe in theory it does not see, but in reality it does see it as
> > > `list' is evaluated before `eval', so the interned `rcd-symbol' and
> > > variable `description' they get evaluated before `eval'.
>
> > That sentence doesn't make any sense to me. It does or it doesn't.
>
> Well, I get confused too, you said that it does not see, but it is
> obvious that it does see.
>
> > I propose to you the next experiment:
> >
> > * experiment 3
> >
> > (let ()
> > (let ((x 42))
> > (eval '(progn (setq x 43) (message "in eval: x is %S" x)))
> > (message "inner let: x is %S" x))
> > (message "outer let: x is %S" x))
> >
> > (you might have to switch to the *Messages* buffer to see all three
> > messages).
>
> The outer scope does not see the inner scope.
>
> Then the buffer *Backtrace* jumps up:
>
> Debugger entered--Lisp error: (void-variable x)
> (message "outer let: x is %S" x)
> (let nil (let ((x 42)) (eval '(progn (setq x 43) (message "in eval: x is %S" x))) (message "inner let: x is %S" x)) (message "outer let: x is %S" x))
> eval((let nil (let ((x 42)) (eval '(progn (setq x 43) (message "in eval: x is %S" x))) (message "inner let: x is %S" x)) (message "outer let: x is %S" x)) nil)
> elisp--eval-last-sexp(nil)
> eval-last-sexp(nil)
> funcall-interactively(eval-last-sexp nil)
> call-interactively(eval-last-sexp nil nil)
> command-execute(eval-last-sexp)
Oh, that is interesting. For me (this is copied off the *Messages* buffer;
I started Emacs anew to make sure no global definition of x lingers
around; to make extra sure, I just eval'ed x before: it throws the
expected void-variable x):
in eval: x is 43
inner let: x is 42
outer let: x is 43
"outer let: x is 43"
This is what I actually expect: the setq whithin the eval does set x's
global (or buffer-local, if there is one) value. It doesn't touch the
lexical value, because it doesn't know about it.
> > What are the results? Do they correspond to your expectations? If
> > not, why not?
>
> I did not have any expectations for that piece of code and that
> one does not generate new global variables to return the symbol
> for history, which is what I need, and what is solved with `eval'
> nicely.
>
> Look here:
>
> (let ((x 42))
> (eval (list 'progn (setq x 43) (message "in eval: x is %S" x)))) ⇒ "in eval: x is 43"
It seems you have fun generating intentionally obfuscated code. Eval
is a function, so its argument is evaluated. Let's see...
(list ; a function
'progn ; (quote progn) evaluates to the symbol progn
(setq x 43) ; evaluates to 43 SIDE EFFECT: set x to 43 at some global/buffer-local level
(message "...") ; evaluates to "..." SIDE EFFECT print "..." to *Messages*
What eval "sees" at the end is
(eval '(progn 43 "in eval: x is 43"))
which evaluates to "in eval: x is 43".
On the way to there, two side effects happened. The symbol x was bound to 43 in some
(global or buffer-local) symbol table (obarray), probably "before" (message ...)
happens (I've assumed so when substituting-in the x there), and something got
printed to *Messages*. Go look there: you'll probably find two copies of
"in eval: x is 43". The one is the side effect, the other the p from the REPL.
> that obviously does work nicely as the list gets evaluated before eval
> receives it. At least I assume it is so, according to learning about
> the LISP in general.
If it works nicely, we're all in agreement.
I'll have to stop here. Other things demand my attention, and I just can't
keep up with your bandwidth.
So happy hacking!
Cheers
- t
[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 198 bytes --]
^ permalink raw reply [flat|nested] 28+ messages in thread
* Re: [SOLVED with `eval']: Why I cannot use this variable in macro call from function?
2021-06-09 14:39 ` Jean Louis
2021-06-09 16:41 ` tomas
@ 2021-06-10 2:10 ` Robert Thorpe
2021-06-10 6:56 ` Jean Louis
1 sibling, 1 reply; 28+ messages in thread
From: Robert Thorpe @ 2021-06-10 2:10 UTC (permalink / raw)
To: Jean Louis, tomas, help-gnu-emacs
I just want to say a couple of things about this.
I think you should read the Emacs lisp manual more. Or maybe even
another book on Lisp. Understanding of scope is important. So are
macros and quoting if you're using them.
For the snippet of code that Tomas gives I get the same result:
> (let ()
> (let ((x 42))
> (eval '(progn (setq x 43) (message "in eval: x is %S" x)))
> (message "inner let: x is %S" x))
> (message "outer let: x is %S" x))
Gives:
> in eval: x is 43
> inner let: x is 42
> outer let: x is 43
> "outer let: x is 43"
I don't get any errors.
However, I think that your problem doesn't really require any of that
complexity. I think it can be done with an Alist.
Why not save all of your histories into one alist? Instead of an alist
you could use a hash. I don't see why you have to create a set of new
global variables to solve the problem.
You have a function that creates one of those variables. Why not
replace it with a function that enters the information in a global
alist? Then you only need one global variable. Then when you need to
call "completing-read" use an assoc to find the sub-list to use.
BR,
Robert Thorpe
^ permalink raw reply [flat|nested] 28+ messages in thread
* Re: [SOLVED with `eval']: Why I cannot use this variable in macro call from function?
2021-06-10 2:10 ` Robert Thorpe
@ 2021-06-10 6:56 ` Jean Louis
2021-06-11 6:33 ` Robert Thorpe
0 siblings, 1 reply; 28+ messages in thread
From: Jean Louis @ 2021-06-10 6:56 UTC (permalink / raw)
To: Robert Thorpe; +Cc: help-gnu-emacs
* Robert Thorpe <rt@robertthorpeconsulting.com> [2021-06-10 05:12]:
> I just want to say a couple of things about this.
>
> I think you should read the Emacs lisp manual more. Or maybe even
> another book on Lisp. Understanding of scope is important. So are
> macros and quoting if you're using them.
>
> For the snippet of code that Tomas gives I get the same result:
> > (let ()
> > (let ((x 42))
> > (eval '(progn (setq x 43) (message "in eval: x is %S" x)))
> > (message "inner let: x is %S" x))
> > (message "outer let: x is %S" x))
>
> Gives:
>
> > in eval: x is 43
> > inner let: x is 42
> > outer let: x is 43
> > "outer let: x is 43"
>
> I don't get any errors.
With `emacs -Q' I get no errors in *scratch*, now I can see that. I
can see that my *scratch* was changing lexical bindings. When I invoke
it in a new emacs-lisp-mode buffer there is error under dynamic
bindings, and no error under lexical bindings.
IMHO everybody should learn more and so I do. Obviously I did not
find the way. Whoever has read more than me, then I am asking to
give me references.
> However, I think that your problem doesn't really require any of
> that complexity. I think it can be done with an Alist.
>
> Why not save all of your histories into one alist? Instead of an alist
> you could use a hash. I don't see why you have to create a set of new
> global variables to solve the problem.
Definitely good idea and now I was thinking there is some description
pointing to it and have looked into `completing-read' and
`read-from-minibuffer' and found nothing, I have to provide a variable
or cons with variable to those functions. It is good idea definitely,
but show me the practical way how to use alist or hash in those
functions.
> You have a function that creates one of those variables. Why not
> replace it with a function that enters the information in a global
> alist? Then you only need one global variable. Then when you need to
> call "completing-read" use an assoc to find the sub-list to use.o
Your ideas go to the root or to depth of the problem. But how
practically to do that? I don't want to change those functions, I
want to pass something to them which will have dynamic names or
arguments. I could assign a single global buffer-local variable
that keeps the name of the edited column, and the function passed
could then find that variable and fetch from alist.
But how?
(read-from-minibuffer PROMPT &optional INITIAL-CONTENTS KEYMAP READ
HIST DEFAULT-VALUE INHERIT-INPUT-METHOD)
Fifth arg HIST, if non-nil, specifies a history list and optionally
the initial position in the list. It can be a symbol, which is the
history list variable to use, or a cons cell (HISTVAR . HISTPOS).
In that case, HISTVAR is the history list variable to use, and
HISTPOS is the initial position for use by the minibuffer history
commands. For consistency, you should also specify that element of
the history as the value of INITIAL-CONTENTS. Positions are counted
starting from 1 at the beginning of the list. If HIST is the symbol
‘t’, history is not recorded.
It works this way:
(let ((history '("One" "Two" "Three")))
(read-from-minibuffer "Tell me: " nil nil nil 'history))
Not this way:
(let ((history (lambda () '("One" "Two" "Three"))))
(read-from-minibuffer "Tell me: " nil nil nil 'history))
Or this way:
(let ((history '("One" "Two" "Three")))
(read-from-minibuffer "Tell me: " nil nil nil '(history . 1)))
and I guess it is similar situation here:
(completing-read PROMPT COLLECTION &optional PREDICATE REQUIRE-MATCH
INITIAL-INPUT HIST DEF INHERIT-INPUT-METHOD)
, if non-nil, specifies a history list and optionally the initial
position in the list. It can be a symbol, which is the history list
variable to use, or it can be a cons cell (HISTVAR . HISTPOS). In
that case, HISTVAR is the history list variable to use, and HISTPOS
is the initial position (the position in the list used by the
minibuffer history commands). For consistency, you should also
specify that element of the history as the value of INITIAL-INPUT.
(This is the only case in which you should use INITIAL-INPUT instead
of DEF.) Positions are counted starting from 1 at the beginning of
the list. The variable ‘history-length’ controls the maximum length
of a history list. If HIST is the symbol ‘t’, history is not
recorded.
Question is how practically?
--
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
* Re: [SOLVED with `eval']: Why I cannot use this variable in macro call from function?
2021-06-10 6:56 ` Jean Louis
@ 2021-06-11 6:33 ` Robert Thorpe
2021-06-11 7:03 ` Jean Louis
0 siblings, 1 reply; 28+ messages in thread
From: Robert Thorpe @ 2021-06-11 6:33 UTC (permalink / raw)
To: Jean Louis; +Cc: help-gnu-emacs
Jean Louis <bugs@gnu.support> writes:
> Definitely good idea and now I was thinking there is some description
> pointing to it and have looked into `completing-read' and
> `read-from-minibuffer' and found nothing, I have to provide a variable
> or cons with variable to those functions. It is good idea definitely,
> but show me the practical way how to use alist or hash in those
> functions.
AFAICT, What you need to do is to populate a variable from the alist. Then pass
that variable to to `completing-read' or `read-from-minibuffer'.
>> You have a function that creates one of those variables. Why not
>> replace it with a function that enters the information in a global
>> alist? Then you only need one global variable. Then when you need to
>> call "completing-read" use an assoc to find the sub-list to use.o
>
> Your ideas go to the root or to depth of the problem. But how
> practically to do that? I don't want to change those functions, I
> want to pass something to them which will have dynamic names or
> arguments. I could assign a single global buffer-local variable
> that keeps the name of the edited column, and the function passed
> could then find that variable and fetch from alist.
>
> But how?
I'm not sure what you mean here. In one global alist you could put lots
and lots of information. There could be an entry for each history list
that you need. I don't see why you need to pass around functions here.
> (read-from-minibuffer PROMPT &optional INITIAL-CONTENTS KEYMAP READ
> HIST DEFAULT-VALUE INHERIT-INPUT-METHOD)
>
> Fifth arg HIST, if non-nil, specifies a history list and optionally
> the initial position in the list. It can be a symbol, which is the
> history list variable to use, or a cons cell (HISTVAR . HISTPOS).
> In that case, HISTVAR is the history list variable to use, and
> HISTPOS is the initial position for use by the minibuffer history
> commands. For consistency, you should also specify that element of
> the history as the value of INITIAL-CONTENTS. Positions are counted
> starting from 1 at the beginning of the list. If HIST is the symbol
> ‘t’, history is not recorded.
>
> It works this way:
>
> (let ((history '("One" "Two" "Three")))
> (read-from-minibuffer "Tell me: " nil nil nil 'history))
>
> Not this way:
>
> (let ((history (lambda () '("One" "Two" "Three"))))
> (read-from-minibuffer "Tell me: " nil nil nil 'history))
>
> Or this way:
>
> (let ((history '("One" "Two" "Three")))
> (read-from-minibuffer "Tell me: " nil nil nil '(history . 1)))
None of those three work for me. That is, none give a history list.
BR,
Robert Thorpe
^ permalink raw reply [flat|nested] 28+ messages in thread
* Re: [SOLVED with `eval']: Why I cannot use this variable in macro call from function?
2021-06-11 6:33 ` Robert Thorpe
@ 2021-06-11 7:03 ` Jean Louis
0 siblings, 0 replies; 28+ messages in thread
From: Jean Louis @ 2021-06-11 7:03 UTC (permalink / raw)
To: Robert Thorpe; +Cc: help-gnu-emacs
* Robert Thorpe <rt@robertthorpeconsulting.com> [2021-06-11 09:34]:
> Jean Louis <bugs@gnu.support> writes:
>
> > Definitely good idea and now I was thinking there is some description
> > pointing to it and have looked into `completing-read' and
> > `read-from-minibuffer' and found nothing, I have to provide a variable
> > or cons with variable to those functions. It is good idea definitely,
> > but show me the practical way how to use alist or hash in those
> > functions.
>
> AFAICT, What you need to do is to populate a variable from the
> alist. Then pass that variable to to `completing-read' or
> `read-from-minibuffer'.
I got the idea. But then... is that history just temporary or retained
over sessions? Common history variables are retained in
~/.emacs.d/history
> I'm not sure what you mean here. In one global alist you could put lots
> and lots of information. There could be an entry for each history list
> that you need. I don't see why you need to pass around functions
> here.
I do understand the idea that one history pre-variable would be used
to keep history for the generated on the fly modified history variable
that is used in `read-from-minibuffer', but then it will probably not
be retained and it would be vague, unclear to where such history
belongs. Additionally I would need to find way to keep the alist
variable somewhere stored as well.
Idea is understandable, but way too complicated.
We better conclude that the issue is solved and it works well without
problems. Using `eval' is there for a reason.
The snippet below solves it. Shorter solution is useful, if you have
one:
(defun rcd-symbol-if-not-exist (variable &optional value description)
"Return symbol for VARIABLE string.
It will generate new VARIABLE if it does not exist."
(let ((rcd-symbol (intern variable))
(description (or description (format "Generated variable `%s'" variable))))
(if (boundp rcd-symbol)
rcd-symbol
(eval (list 'defvar rcd-symbol value description)))))
(rcd-symbol-if-not-exist
"my-new-symbol" "Value here" "Some description")
⇒ my-new-symbol ⇒ "Value here"
(setq my-new-symbol 10) ⇒ 10
my-new-symbol ⇒ 10
It is handy that it will not change the existing value of the
variable, just return a symbol or generate it:
(rcd-symbol-if-not-exist
"my-new-symbol" "Value here" "Some description") ⇒ my-new-symbol ⇒ 10
for history it is then very useful to dynamically generate
history variables:
(let* ((name "Streets")
(history (concat name "-history")))
(read-from-minibuffer "Street: " nil nil nil (rcd-symbol-if-not-exist history)))
Streets-history ⇒ ("Elm Street")
It will be saved in ~/.emacs.d/history as:
(setq Streets-history '("Elm Street"))
User has to think of how such history variables should be called
as not to collide with others.
> > It works this way:
> >
> > (let ((history '("One" "Two" "Three")))
> > (read-from-minibuffer "Tell me: " nil nil nil 'history))
> >
> > Or this way:
> >
> > (let ((history '("One" "Two" "Three")))
> > (read-from-minibuffer "Tell me: " nil nil nil '(history . 1)))
>
> None of those three work for me. That is, none give a history list.
On my side these below work:
(let ((history '("One" "Two" "Three")))
(read-from-minibuffer "Tell me: " nil nil nil 'history))
(let ((history '("One" "Two" "Three" "Four")))
(read-from-minibuffer "Tell me: " nil nil nil '(history . 1)))
Press arrow up.
--
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
end of thread, other threads:[~2021-06-11 7:03 UTC | newest]
Thread overview: 28+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2021-06-08 13:10 Why I cannot use this variable in macro call from function? Jean Louis
2021-06-08 13:41 ` [External] : " Drew Adams
2021-06-08 14:47 ` Jean Louis
2021-06-08 17:14 ` Jean Louis
2021-06-08 18:31 ` tomas
2021-06-08 18:37 ` Oops function? tomas
2021-06-08 19:27 ` [SOLVED with `eval']: Why I cannot use this variable in macro call from function? Jean Louis
2021-06-08 20:03 ` tomas
2021-06-08 20:06 ` Sorry again tomas
2021-06-08 20:12 ` [SOLVED with `eval']: Why I cannot use this variable in macro call from function? Jean Louis
2021-06-08 20:23 ` tomas
2021-06-08 20:38 ` Jean Louis
2021-06-08 20:47 ` Jean Louis
2021-06-09 6:09 ` tomas
2021-06-09 6:42 ` Jean Louis
2021-06-09 6:51 ` tomas
2021-06-09 7:03 ` Jean Louis
2021-06-09 7:39 ` tomas
2021-06-09 8:22 ` Jean Louis
2021-06-09 8:54 ` tomas
2021-06-09 10:56 ` Jean Louis
2021-06-09 11:33 ` tomas
2021-06-09 14:39 ` Jean Louis
2021-06-09 16:41 ` tomas
2021-06-10 2:10 ` Robert Thorpe
2021-06-10 6:56 ` Jean Louis
2021-06-11 6:33 ` Robert Thorpe
2021-06-11 7:03 ` Jean Louis
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.