* 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
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).