* Understanding the "let" construct and the setting of variables @ 2020-12-17 0:10 steve-humphreys 2020-12-17 0:21 ` Joost Kremers ` (2 more replies) 0 siblings, 3 replies; 50+ messages in thread From: steve-humphreys @ 2020-12-17 0:10 UTC (permalink / raw) To: Help Gnu Emacs I have been writing some elisp to set the time grid in the agenda. The discussion progressed towards the use of the "let" construct. But, the discussion got too advanced for me to follow the different points of view and make a decision. This message is for showing some examples, of how to set and use variables in a "let", because people criticise using "setq". But discussion needs simple examples that would not overwhelm a relative beginner. (defun timfutur () (interactive) (setq tim 845) (setq tsk 80) (setq thr (/ tim 100)) (setq tmn (- tim (* thr 100))) (setq tinc_mn (+ tmn tsk)) (setq tinc_hr (/ (+ tmn tsk) 60)) (setq tinc_mn (- tinc_mn (* tinc_hr 60)) ) (setq thr_futur (* (+ thr tinc_hr) 100) ) (setq tmn_futur tinc_mn) (setq tim_out (+ thr_futur tmn_futur)) ^ permalink raw reply [flat|nested] 50+ messages in thread
* Re: Understanding the "let" construct and the setting of variables 2020-12-17 0:10 Understanding the "let" construct and the setting of variables steve-humphreys @ 2020-12-17 0:21 ` Joost Kremers 2020-12-17 2:08 ` steve-humphreys ` (2 more replies) 2020-12-17 0:25 ` steve-humphreys 2020-12-18 15:33 ` Emanuel Berg via Users list for the GNU Emacs text editor 2 siblings, 3 replies; 50+ messages in thread From: Joost Kremers @ 2020-12-17 0:21 UTC (permalink / raw) To: steve-humphreys; +Cc: help-gnu-emacs On Thu, Dec 17 2020, steve-humphreys@gmx.com wrote: > I have been writing some elisp to set the time grid in the agenda. > The discussion progressed towards the use of the "let" construct. > > But, the discussion got too advanced for me to follow the different > points of view and make a decision. > > This message is for showing some examples, of how to set and use variables > in a "let", because people criticise using "setq". But discussion needs > simple examples that would not overwhelm a relative beginner. > > (defun timfutur () > (interactive) > (setq tim 845) > (setq tsk 80) > > (setq thr (/ tim 100)) > (setq tmn (- tim (* thr 100))) > > (setq tinc_mn (+ tmn tsk)) > (setq tinc_hr (/ (+ tmn tsk) 60)) > (setq tinc_mn (- tinc_mn (* tinc_hr 60)) ) > > (setq thr_futur (* (+ thr tinc_hr) 100) ) > (setq tmn_futur tinc_mn) > (setq tim_out (+ thr_futur tmn_futur)) I'm not sure what exactly you're asking, (I'm wondering if your message is complete or was accidentally sent before you finished it), but to understand the problem with `setq`, evaluate your function above in the `*scratch*` buffer. (Copy the function into the `*scratch*` buffer, put the cursor right after it and press `C-x C-e`; note that you need to add another closing parenthesis on the last line). That will define your function and make it available to Emacs. Then open a Lisp interaction buffer with `M-x ielm RET`. You'll get a buffer called `*ielm*` with a prompt where you can type Elisp expressions that get executed right away. Type `tim` (without parentheses) and hit RET. You should get a void variable error: *** Eval error *** Symbol’s value as variable is void: tim" Then type `(timfutur)` and hit RET. You'll get the return value 1005 (displayed also in octal and hexadecimal). Now type `tim` again at the prompt. This time, there won't be an error anymore. Instead you'll get the value 845. Running your function has created a global variable `tim` (plus all the other variables you've setq'ed), and since there are no packages or namespaces in Elisp, your variable is now available to all of Emacs. While I was writing this, your two questions arrived: > 1. In what simple circumstances would one use a "setq" in the body of a let? One common idiom would be to create or consume a list inside a loop, e.g., ``` (let ((lst (some-function-that-produces-a-list))) (while (some-condition-on (car lst)) (do-something-with (car lst)) (setq lst (cdr lst)))) ``` Nowadays such an idiom would more often be handled with a higher-order function of the map/reduce/filter-family, but there may be situations in which that doesn't work. Another example would be the case where you want to modify a value based on some set of conditions, e.g.,: ``` (let ((x (get-some-value)) (y (get-some-other-value))) (cond ((some-condition-on y) (setq x (do-something-with y))) ((some-other-condition-on y) (setq x (do-something-else-with x))) (:otherwise (setq y nil))) (now-do-something-with x y)) ``` You could probably rewrite this without `setq` using `let*` and some intermediate variables, but sometimes I find using `setq` to be clearer, especially if you have multiple values that are interdependent in complex ways. > 2. What simple option does one have that is more advantageous than using a "setq"? `let*` in the example function you gave above. For creating or consuming a list, there's the map/filter/reduce-family or cl-loop. Not sure if that makes it any easier for a relative beginner :-/ but I hope it helps a bit anyway. -- Joost Kremers Life has its moments ^ permalink raw reply [flat|nested] 50+ messages in thread
* Re: Understanding the "let" construct and the setting of variables 2020-12-17 0:21 ` Joost Kremers @ 2020-12-17 2:08 ` steve-humphreys 2020-12-17 3:12 ` steve-humphreys 2020-12-17 8:10 ` Joost Kremers 2020-12-17 2:49 ` steve-humphreys 2020-12-18 20:33 ` Emanuel Berg via Users list for the GNU Emacs text editor 2 siblings, 2 replies; 50+ messages in thread From: steve-humphreys @ 2020-12-17 2:08 UTC (permalink / raw) To: Joost Kremers; +Cc: help-gnu-emacs Finally I got some useful information (ielm). Fantastic. ACCEPTED: Running function has created a global variable `tim` (plus all the other variables you've setq'ed), and since there are no packages or namespaces in Elisp, your variable is now available to all of Emacs. QUESTION: What happens if one does a "setq" on a variable defined in the binding part of the "let"? Can one do that? QUESTION: What goes in the body of a "let"? I would think I can use the variables defined within the binding section of "let". QUESTION: Can one update a variable in the body of the "let" (the variable being defined within the binding section of "let"). > Sent: Thursday, December 17, 2020 at 1:21 AM > From: "Joost Kremers" <joostkremers@fastmail.fm> > To: steve-humphreys@gmx.com > Cc: help-gnu-emacs@gnu.org > Subject: Re: Understanding the "let" construct and the setting of variables > > > On Thu, Dec 17 2020, steve-humphreys@gmx.com wrote: > > I have been writing some elisp to set the time grid in the agenda. > > The discussion progressed towards the use of the "let" construct. > > > > But, the discussion got too advanced for me to follow the different > > points of view and make a decision. > > > > This message is for showing some examples, of how to set and use variables > > in a "let", because people criticise using "setq". But discussion needs > > simple examples that would not overwhelm a relative beginner. > > > > (defun timfutur () > > (interactive) > > (setq tim 845) > > (setq tsk 80) > > > > (setq thr (/ tim 100)) > > (setq tmn (- tim (* thr 100))) > > > > (setq tinc_mn (+ tmn tsk)) > > (setq tinc_hr (/ (+ tmn tsk) 60)) > > (setq tinc_mn (- tinc_mn (* tinc_hr 60)) ) > > > > (setq thr_futur (* (+ thr tinc_hr) 100) ) > > (setq tmn_futur tinc_mn) > > (setq tim_out (+ thr_futur tmn_futur)) > > I'm not sure what exactly you're asking, (I'm wondering if your message is > complete or was accidentally sent before you finished it), but to understand the > problem with `setq`, evaluate your function above in the `*scratch*` buffer. > (Copy the function into the `*scratch*` buffer, put the cursor right after it > and press `C-x C-e`; note that you need to add another closing parenthesis on > the last line). That will define your function and make it available to > Emacs. > > Then open a Lisp interaction buffer with `M-x ielm RET`. You'll get a buffer > called `*ielm*` with a prompt where you can type Elisp expressions that get > executed right away. Type `tim` (without parentheses) and hit RET. You should > get a void variable error: > > *** Eval error *** Symbol’s value as variable is void: tim" Correct. That's what I got. > Then type `(timfutur)` and hit RET. You'll get the return value 1005 (displayed > also in octal and hexadecimal). Ok, got that. -------- ELISP> (timfutur) 1005 (#o1755, #x3ed) > Now type `tim` again at the prompt. This time, there won't be an error anymore. > Instead you'll get the value 845. > Running your function has created a global variable `tim` (plus all the other > variables you've setq'ed), and since there are no packages or namespaces in > Elisp, your variable is now available to all of Emacs. ELISP> tim 845 (#o1515, #x34d) > While I was writing this, your two questions arrived: > > > 1. In what simple circumstances would one use a "setq" in the body of a let? > > One common idiom would be to create or consume a list inside a loop, e.g., > > ``` > (let ((lst (some-function-that-produces-a-list))) > (while (some-condition-on (car lst)) > (do-something-with (car lst)) > (setq lst (cdr lst)))) > ``` > > Nowadays such an idiom would more often be handled with a higher-order function > of the map/reduce/filter-family, but there may be situations in which that > doesn't work. > > Another example would be the case where you want to modify a value based on some > set of conditions, e.g.,: > > ``` > (let ((x (get-some-value)) > (y (get-some-other-value))) > (cond > ((some-condition-on y) > (setq x (do-something-with y))) > ((some-other-condition-on y) > (setq x (do-something-else-with x))) > (:otherwise > (setq y nil))) > (now-do-something-with x y)) > ``` > > You could probably rewrite this without `setq` using `let*` and some > intermediate variables, but sometimes I find using `setq` to be clearer, > especially if you have multiple values that are interdependent in complex ways. > > > 2. What simple option does one have that is more advantageous than using a "setq"? > > `let*` in the example function you gave above. For creating or consuming a list, > there's the map/filter/reduce-family or cl-loop. > > Not sure if that makes it any easier for a relative beginner :-/ but I hope it > helps a bit anyway. > > > -- > Joost Kremers > Life has its moments > > ^ permalink raw reply [flat|nested] 50+ messages in thread
* Re: Understanding the "let" construct and the setting of variables 2020-12-17 2:08 ` steve-humphreys @ 2020-12-17 3:12 ` steve-humphreys 2020-12-17 8:01 ` Joost Kremers 2020-12-17 8:10 ` Joost Kremers 1 sibling, 1 reply; 50+ messages in thread From: steve-humphreys @ 2020-12-17 3:12 UTC (permalink / raw) To: steve-humphreys; +Cc: Joost Kremers, help-gnu-emacs I want the function "lett" to return "tim_out". I understand that the last command is the output of the function. But should this be done in the binding part or in the body part of the "let". Or outside the "let". (defun lett (tim tsk) (let* ( (thr (/ tim 100)) (tmn (- tim (* thr 100))) (tinc_mn (+ tmn tsk)) (tinc_hr (/ (+ tmn tsk) 60)) (tinc_mn (- tinc_mn (* tinc_hr 60))) (thr_futur (* (+ thr tinc_hr) 100)) (tmn_futur tinc_mn) (tim_out (+ thr_futur tmn_futur)) ) ;; --- body of let ---- (message "tim_out: %d" tim_out) )) > Sent: Thursday, December 17, 2020 at 3:08 AM > From: steve-humphreys@gmx.com > To: "Joost Kremers" <joostkremers@fastmail.fm> > Cc: help-gnu-emacs@gnu.org > Subject: Re: Understanding the "let" construct and the setting of variables > > Finally I got some useful information (ielm). Fantastic. > > ACCEPTED: Running function has created a global variable `tim` (plus all the other > variables you've setq'ed), and since there are no packages or namespaces in > Elisp, your variable is now available to all of Emacs. > > QUESTION: What happens if one does a "setq" on a variable defined in the binding part of the > "let"? Can one do that? > > QUESTION: What goes in the body of a "let"? I would think I can use the variables defined within > the binding section of "let". > > QUESTION: Can one update a variable in the body of the "let" (the variable being defined within > the binding section of "let"). > > > > > > Sent: Thursday, December 17, 2020 at 1:21 AM > > From: "Joost Kremers" <joostkremers@fastmail.fm> > > To: steve-humphreys@gmx.com > > Cc: help-gnu-emacs@gnu.org > > Subject: Re: Understanding the "let" construct and the setting of variables > > > > > > On Thu, Dec 17 2020, steve-humphreys@gmx.com wrote: > > > I have been writing some elisp to set the time grid in the agenda. > > > The discussion progressed towards the use of the "let" construct. > > > > > > But, the discussion got too advanced for me to follow the different > > > points of view and make a decision. > > > > > > This message is for showing some examples, of how to set and use variables > > > in a "let", because people criticise using "setq". But discussion needs > > > simple examples that would not overwhelm a relative beginner. > > > > > > (defun timfutur () > > > (interactive) > > > (setq tim 845) > > > (setq tsk 80) > > > > > > (setq thr (/ tim 100)) > > > (setq tmn (- tim (* thr 100))) > > > > > > (setq tinc_mn (+ tmn tsk)) > > > (setq tinc_hr (/ (+ tmn tsk) 60)) > > > (setq tinc_mn (- tinc_mn (* tinc_hr 60)) ) > > > > > > (setq thr_futur (* (+ thr tinc_hr) 100) ) > > > (setq tmn_futur tinc_mn) > > > (setq tim_out (+ thr_futur tmn_futur)) > > > > I'm not sure what exactly you're asking, (I'm wondering if your message is > > complete or was accidentally sent before you finished it), but to understand the > > problem with `setq`, evaluate your function above in the `*scratch*` buffer. > > (Copy the function into the `*scratch*` buffer, put the cursor right after it > > and press `C-x C-e`; note that you need to add another closing parenthesis on > > the last line). That will define your function and make it available to > > Emacs. > > > > Then open a Lisp interaction buffer with `M-x ielm RET`. You'll get a buffer > > called `*ielm*` with a prompt where you can type Elisp expressions that get > > executed right away. Type `tim` (without parentheses) and hit RET. You should > > get a void variable error: > > > > *** Eval error *** Symbol’s value as variable is void: tim" > > Correct. That's what I got. > > > Then type `(timfutur)` and hit RET. You'll get the return value 1005 (displayed > > also in octal and hexadecimal). > > Ok, got that. > -------- > ELISP> (timfutur) > 1005 (#o1755, #x3ed) > > > Now type `tim` again at the prompt. This time, there won't be an error anymore. > > Instead you'll get the value 845. > > > Running your function has created a global variable `tim` (plus all the other > > variables you've setq'ed), and since there are no packages or namespaces in > > Elisp, your variable is now available to all of Emacs. > > ELISP> tim > 845 (#o1515, #x34d) > > > While I was writing this, your two questions arrived: > > > > > 1. In what simple circumstances would one use a "setq" in the body of a let? > > > > One common idiom would be to create or consume a list inside a loop, e.g., > > > > ``` > > (let ((lst (some-function-that-produces-a-list))) > > (while (some-condition-on (car lst)) > > (do-something-with (car lst)) > > (setq lst (cdr lst)))) > > ``` > > > > Nowadays such an idiom would more often be handled with a higher-order function > > of the map/reduce/filter-family, but there may be situations in which that > > doesn't work. > > > > Another example would be the case where you want to modify a value based on some > > set of conditions, e.g.,: > > > > ``` > > (let ((x (get-some-value)) > > (y (get-some-other-value))) > > (cond > > ((some-condition-on y) > > (setq x (do-something-with y))) > > ((some-other-condition-on y) > > (setq x (do-something-else-with x))) > > (:otherwise > > (setq y nil))) > > (now-do-something-with x y)) > > ``` > > > > You could probably rewrite this without `setq` using `let*` and some > > intermediate variables, but sometimes I find using `setq` to be clearer, > > especially if you have multiple values that are interdependent in complex ways. > > > > > 2. What simple option does one have that is more advantageous than using a "setq"? > > > > `let*` in the example function you gave above. For creating or consuming a list, > > there's the map/filter/reduce-family or cl-loop. > > > > Not sure if that makes it any easier for a relative beginner :-/ but I hope it > > helps a bit anyway. > > > > > > -- > > Joost Kremers > > Life has its moments > > > > > > ^ permalink raw reply [flat|nested] 50+ messages in thread
* Re: Understanding the "let" construct and the setting of variables 2020-12-17 3:12 ` steve-humphreys @ 2020-12-17 8:01 ` Joost Kremers 2020-12-17 8:31 ` steve-humphreys 0 siblings, 1 reply; 50+ messages in thread From: Joost Kremers @ 2020-12-17 8:01 UTC (permalink / raw) To: steve-humphreys; +Cc: help-gnu-emacs On Thu, Dec 17 2020, steve-humphreys@gmx.com wrote: > I want the function "lett" to return "tim_out". I understand that the last command > is the output of the function. But should this be done in the binding part or in the > body part of the "let". Or outside the "let". If `message` is in the last form in the body of the `let`, the return value of `message` is also the return value of `let`. If `let` is the last form in the body of the function, its return value is the return value of the function. `message` can also be outside the body of `let`, but in that case it cannot refer to any of the variables bound in `let`, because they are then out of scope and no longer exist. > (defun lett (tim tsk) > > (let* ( (thr (/ tim 100)) > (tmn (- tim (* thr 100))) > > (tinc_mn (+ tmn tsk)) > (tinc_hr (/ (+ tmn tsk) 60)) > (tinc_mn (- tinc_mn (* tinc_hr 60))) > > (thr_futur (* (+ thr tinc_hr) 100)) > (tmn_futur tinc_mn) > (tim_out (+ thr_futur tmn_futur)) ) > ;; --- body of let ---- > (message "tim_out: %d" tim_out) )) -- Joost Kremers Life has its moments ^ permalink raw reply [flat|nested] 50+ messages in thread
* Re: Understanding the "let" construct and the setting of variables 2020-12-17 8:01 ` Joost Kremers @ 2020-12-17 8:31 ` steve-humphreys 2020-12-17 8:50 ` Joost Kremers 0 siblings, 1 reply; 50+ messages in thread From: steve-humphreys @ 2020-12-17 8:31 UTC (permalink / raw) To: Joost Kremers; +Cc: help-gnu-emacs > Sent: Thursday, December 17, 2020 at 9:01 AM > From: "Joost Kremers" <joostkremers@fastmail.fm> > To: steve-humphreys@gmx.com > Cc: help-gnu-emacs@gnu.org > Subject: Re: Understanding the "let" construct and the setting of variables > > > On Thu, Dec 17 2020, steve-humphreys@gmx.com wrote: > > I want the function "lett" to return "tim_out". I understand that the last command > > is the output of the function. But should this be done in the binding part or in the > > body part of the "let". Or outside the "let". > > If `message` is in the last form in the body of the `let`, the return value of > `message` is also the return value of `let`. If `let` is the last form in the > body of the function, its return value is the return value of the function. I do not want the function to return the "message" (tah was for testing), but the value of tim_out. How can one return a local variable? > `message` can also be outside the body of `let`, but in that case it cannot > refer to any of the variables bound in `let`, because they are then out of scope > and no longer exist. Understood. Thank you. > > (defun lett (tim tsk) > > > > (let* ( (thr (/ tim 100)) > > (tmn (- tim (* thr 100))) > > > > (tinc_mn (+ tmn tsk)) > > (tinc_hr (/ (+ tmn tsk) 60)) > > (tinc_mn (- tinc_mn (* tinc_hr 60))) > > > > (thr_futur (* (+ thr tinc_hr) 100)) > > (tmn_futur tinc_mn) > > (tim_out (+ thr_futur tmn_futur)) ) > > ;; --- body of let ---- > > (message "tim_out: %d" tim_out) )) > > > -- > Joost Kremers > Life has its moments > > ^ permalink raw reply [flat|nested] 50+ messages in thread
* Re: Understanding the "let" construct and the setting of variables 2020-12-17 8:31 ` steve-humphreys @ 2020-12-17 8:50 ` Joost Kremers 0 siblings, 0 replies; 50+ messages in thread From: Joost Kremers @ 2020-12-17 8:50 UTC (permalink / raw) To: steve-humphreys; +Cc: help-gnu-emacs On Thu, Dec 17 2020, steve-humphreys@gmx.com wrote: > I do not want the function to return the "message" (tah was for testing), but the > value of tim_out. How can one return a local variable? `let` returns the return value of its last body form. So simply use your variable as the last body form. :-) ``` (let ((some-var (calculate-some-value))) (do-some-more-stuff-with some-var) some-var) ``` -- Joost Kremers Life has its moments ^ permalink raw reply [flat|nested] 50+ messages in thread
* Re: Understanding the "let" construct and the setting of variables 2020-12-17 2:08 ` steve-humphreys 2020-12-17 3:12 ` steve-humphreys @ 2020-12-17 8:10 ` Joost Kremers 2020-12-17 8:43 ` steve-humphreys 2020-12-18 20:39 ` Emanuel Berg via Users list for the GNU Emacs text editor 1 sibling, 2 replies; 50+ messages in thread From: Joost Kremers @ 2020-12-17 8:10 UTC (permalink / raw) To: steve-humphreys; +Cc: help-gnu-emacs On Thu, Dec 17 2020, steve-humphreys@gmx.com wrote: > Finally I got some useful information (ielm). Fantastic. > > ACCEPTED: Running function has created a global variable `tim` (plus all the other > variables you've setq'ed), and since there are no packages or namespaces in > Elisp, your variable is now available to all of Emacs. > > QUESTION: What happens if one does a "setq" on a variable defined in the binding part of the > "let"? Can one do that? Yes, inside the body of the `let`, you can. > QUESTION: What goes in the body of a "let"? I would think I can use the variables defined within > the binding section of "let". Yes. > QUESTION: Can one update a variable in the body of the "let" (the variable being defined within > the binding section of "let"). Yes, with `setq`. -- Joost Kremers Life has its moments ^ permalink raw reply [flat|nested] 50+ messages in thread
* Re: Understanding the "let" construct and the setting of variables 2020-12-17 8:10 ` Joost Kremers @ 2020-12-17 8:43 ` steve-humphreys 2020-12-17 8:56 ` Joost Kremers 2020-12-18 20:46 ` Emanuel Berg via Users list for the GNU Emacs text editor 2020-12-18 20:39 ` Emanuel Berg via Users list for the GNU Emacs text editor 1 sibling, 2 replies; 50+ messages in thread From: steve-humphreys @ 2020-12-17 8:43 UTC (permalink / raw) To: Joost Kremers; +Cc: help-gnu-emacs > Sent: Thursday, December 17, 2020 at 9:10 AM > From: "Joost Kremers" <joostkremers@fastmail.fm> > To: steve-humphreys@gmx.com > Cc: help-gnu-emacs@gnu.org > Subject: Re: Understanding the "let" construct and the setting of variables > > > On Thu, Dec 17 2020, steve-humphreys@gmx.com wrote: > > Finally I got some useful information (ielm). Fantastic. > > > > ACCEPTED: Running function has created a global variable `tim` (plus all the other > > variables you've setq'ed), and since there are no packages or namespaces in > > Elisp, your variable is now available to all of Emacs. > > > > QUESTION: What happens if one does a "setq" on a variable defined in the binding part of the > > "let"? Can one do that? > > Yes, inside the body of the `let`, you can. > > > QUESTION: What goes in the body of a "let"? I would think I can use the variables defined within > > the binding section of "let". > > Yes. > > > QUESTION: Can one update a variable in the body of the "let" (the variable being defined within > > the binding section of "let"). > > Yes, with `setq`. My mistake was that I was trying the variables using (myvar value) in the body of "let", the same way I was doing in the binding part. That was what confused me when others iterated that "setq" makes the variables available ta all of emacs. This gets me to "defvar". I have read that "setq" does net actually make a variable. It is defvar that makes a variable available. When reading the "Intro to Emacs Lisp", the focus is on using "setq". Do the question really is this. What happens when one sets an object with "setq" if elisp does not make a variable from the name? > -- > Joost Kremers > Life has its moments > > ^ permalink raw reply [flat|nested] 50+ messages in thread
* Re: Understanding the "let" construct and the setting of variables 2020-12-17 8:43 ` steve-humphreys @ 2020-12-17 8:56 ` Joost Kremers 2020-12-18 20:48 ` Emanuel Berg via Users list for the GNU Emacs text editor 2020-12-18 20:46 ` Emanuel Berg via Users list for the GNU Emacs text editor 1 sibling, 1 reply; 50+ messages in thread From: Joost Kremers @ 2020-12-17 8:56 UTC (permalink / raw) To: steve-humphreys; +Cc: help-gnu-emacs On Thu, Dec 17 2020, steve-humphreys@gmx.com wrote: > This gets me to "defvar". I have read that "setq" does net actually > make a variable. It is defvar that makes a variable available. `defvar` creates a global variable, yes. `setq` creates a global variable if the variable does not exist yet. So if you do: ``` (let ((a (some-value))) (do-something) (setq a (some-value-based-on a)) (do-something-else)) ``` Then setq updates the local binding for `a`. If you use setq on a variable that doesn't have a local binding (i.e., isn't bound in the let that contains the setq), it creates a new, global binding. > Do the question really is this. What happens when one sets an object with "setq" > if elisp does not make a variable from the name? Not sure I understand the question. With `setq`, two things can happen: either there is already a binding for the variable, in which case `setq` updates the binding (assigns a new value to the existing variable), or there is no such binding (i.e., the variable doesn't exist), and in that case the variable is created. -- Joost Kremers Life has its moments ^ permalink raw reply [flat|nested] 50+ messages in thread
* Re: Understanding the "let" construct and the setting of variables 2020-12-17 8:56 ` Joost Kremers @ 2020-12-18 20:48 ` Emanuel Berg via Users list for the GNU Emacs text editor 0 siblings, 0 replies; 50+ messages in thread From: Emanuel Berg via Users list for the GNU Emacs text editor @ 2020-12-18 20:48 UTC (permalink / raw) To: help-gnu-emacs Joost Kremers wrote: > Not sure I understand the question. With `setq`, two things > can happen: either there is already a binding for the > variable, in which case `setq` updates the binding (assigns > a new value to the existing variable), or there is no such > binding (i.e., the variable doesn't exist), and in that case > the variable is created. That's right, so use `setq' to create and manipulate global variables; inside functions, use `let/let*'. -- underground experts united http://user.it.uu.se/~embe8573 https://dataswamp.org/~incal ^ permalink raw reply [flat|nested] 50+ messages in thread
* Re: Understanding the "let" construct and the setting of variables 2020-12-17 8:43 ` steve-humphreys 2020-12-17 8:56 ` Joost Kremers @ 2020-12-18 20:46 ` Emanuel Berg via Users list for the GNU Emacs text editor 2020-12-18 21:07 ` Jean Louis 2020-12-18 22:31 ` tomas 1 sibling, 2 replies; 50+ messages in thread From: Emanuel Berg via Users list for the GNU Emacs text editor @ 2020-12-18 20:46 UTC (permalink / raw) To: help-gnu-emacs steve-humphreys wrote: > This gets me to "defvar". I have read that "setq" does net > actually make a variable. It is defvar that makes a variable > available. When reading the "Intro to Emacs Lisp", the focus > is on using "setq". `setq' is enough, it does the real job alright, but the byte-compiler will complain if there isn't a `defvar' before it. Also with defvar you can set a default value and add a docstring. None of that is mandatory and the default value can even be confusing IMO. Just think of defvar as a way of telling Emacs and everyone else, "I intend to use a variable with this name." This is enough, and always do it (_at least_ do that, of course by all means set the default and add a docstring if that fancies you), but always and at least do this: (defvar some-var) (setq some-var some-value) That's enough. You have what you need and the byte-compiler doesn't complain. -- underground experts united http://user.it.uu.se/~embe8573 https://dataswamp.org/~incal ^ permalink raw reply [flat|nested] 50+ messages in thread
* Re: Understanding the "let" construct and the setting of variables 2020-12-18 20:46 ` Emanuel Berg via Users list for the GNU Emacs text editor @ 2020-12-18 21:07 ` Jean Louis 2020-12-18 22:31 ` tomas 1 sibling, 0 replies; 50+ messages in thread From: Jean Louis @ 2020-12-18 21:07 UTC (permalink / raw) To: help-gnu-emacs * Emanuel Berg via Users list for the GNU Emacs text editor <help-gnu-emacs@gnu.org> [2020-12-18 23:48]: > (defvar some-var) > (setq some-var some-value) Instead I use (defvar some-var some-value "doc") ^ permalink raw reply [flat|nested] 50+ messages in thread
* Re: Understanding the "let" construct and the setting of variables 2020-12-18 20:46 ` Emanuel Berg via Users list for the GNU Emacs text editor 2020-12-18 21:07 ` Jean Louis @ 2020-12-18 22:31 ` tomas 1 sibling, 0 replies; 50+ messages in thread From: tomas @ 2020-12-18 22:31 UTC (permalink / raw) To: help-gnu-emacs [-- Attachment #1: Type: text/plain, Size: 488 bytes --] On Fri, Dec 18, 2020 at 09:46:38PM +0100, Emanuel Berg via Users list for the GNU Emacs text editor wrote: > steve-humphreys wrote: > > > This gets me to "defvar" [...] > Just think of defvar as a way of telling Emacs and everyone > else, "I intend to use a variable with this name." Especially the "everyone else" part. You use defvar especially when you want your package's users "hey, here is a knob you can tweak to adjust the package to your needs...". Cheers - t [-- Attachment #2: Digital signature --] [-- Type: application/pgp-signature, Size: 198 bytes --] ^ permalink raw reply [flat|nested] 50+ messages in thread
* Re: Understanding the "let" construct and the setting of variables 2020-12-17 8:10 ` Joost Kremers 2020-12-17 8:43 ` steve-humphreys @ 2020-12-18 20:39 ` Emanuel Berg via Users list for the GNU Emacs text editor 1 sibling, 0 replies; 50+ messages in thread From: Emanuel Berg via Users list for the GNU Emacs text editor @ 2020-12-18 20:39 UTC (permalink / raw) To: help-gnu-emacs Joost Kremers wrote: >> QUESTION: What happens if one does a "setq" on a variable >> defined in the binding part of the "let"? Can one do that? > > Yes, inside the body of the `let`, you can. You can, but it isn't optimal because if you make a typo you will be unaware of it and instead a global variable will silently be created. If it already exist, oh, my you will modify that instead of the intended let binding variable. So better to do all computation you reasonably can _before_ the let body, already in the varlist. Use several steps with `let*' and add supposedly unnecessary steps for clarity, better access and easier debug. In the let body, optimally, all computation is already done. There, you just _do_ whatever it is should happen, using the values you already have for the purpose. -- underground experts united http://user.it.uu.se/~embe8573 https://dataswamp.org/~incal ^ permalink raw reply [flat|nested] 50+ messages in thread
* Re: Understanding the "let" construct and the setting of variables 2020-12-17 0:21 ` Joost Kremers 2020-12-17 2:08 ` steve-humphreys @ 2020-12-17 2:49 ` steve-humphreys 2020-12-17 7:58 ` Joost Kremers 2020-12-18 20:33 ` Emanuel Berg via Users list for the GNU Emacs text editor 2 siblings, 1 reply; 50+ messages in thread From: steve-humphreys @ 2020-12-17 2:49 UTC (permalink / raw) To: Joost Kremers; +Cc: help-gnu-emacs > Sent: Thursday, December 17, 2020 at 1:21 AM > From: "Joost Kremers" <joostkremers@fastmail.fm> > To: steve-humphreys@gmx.com > Cc: help-gnu-emacs@gnu.org > Subject: Re: Understanding the "let" construct and the setting of variables > > > On Thu, Dec 17 2020, steve-humphreys@gmx.com wrote: > > I have been writing some elisp to set the time grid in the agenda. > > The discussion progressed towards the use of the "let" construct. > > > > But, the discussion got too advanced for me to follow the different > > points of view and make a decision. > > > > This message is for showing some examples, of how to set and use variables > > in a "let", because people criticise using "setq". But discussion needs > > simple examples that would not overwhelm a relative beginner. > > > > (defun timfutur () > > (interactive) > > (setq tim 845) > > (setq tsk 80) > > > > (setq thr (/ tim 100)) > > (setq tmn (- tim (* thr 100))) > > > > (setq tinc_mn (+ tmn tsk)) > > (setq tinc_hr (/ (+ tmn tsk) 60)) > > (setq tinc_mn (- tinc_mn (* tinc_hr 60)) ) > > > > (setq thr_futur (* (+ thr tinc_hr) 100) ) > > (setq tmn_futur tinc_mn) > > (setq tim_out (+ thr_futur tmn_futur)) > > I'm not sure what exactly you're asking, (I'm wondering if your message is > complete or was accidentally sent before you finished it), but to understand the > problem with `setq`, evaluate your function above in the `*scratch*` buffer. > (Copy the function into the `*scratch*` buffer, put the cursor right after it > and press `C-x C-e`; note that you need to add another closing parenthesis on > the last line). That will define your function and make it available to > Emacs. > > Then open a Lisp interaction buffer with `M-x ielm RET`. You'll get a buffer > called `*ielm*` with a prompt where you can type Elisp expressions that get > executed right away. Type `tim` (without parentheses) and hit RET. You should > get a void variable error: > > *** Eval error *** Symbol’s value as variable is void: tim" > > Then type `(timfutur)` and hit RET. You'll get the return value 1005 (displayed > also in octal and hexadecimal). > > Now type `tim` again at the prompt. This time, there won't be an error anymore. > Instead you'll get the value 845. > > Running your function has created a global variable `tim` (plus all the other > variables you've setq'ed), and since there are no packages or namespaces in > Elisp, your variable is now available to all of Emacs. I ran the following ELISP> tima (lett 845 80) "tim_out: 1005" ELISP> tim *** Eval error *** Symbol’s value as variable is void: tim ELISP> (lett 845 90) "tim_out: 1015" ELISP> tim *** Eval error *** Symbol’s value as variable is void: tim So this is quite different from using "setq". The variable "tim" is not available to all of emacs. ------- code ------ (defun lett (tim tsk) (let* ( (thr (/ tim 100)) (tmn (- tim (* thr 100))) (tinc_mn (+ tmn tsk)) (tinc_hr (/ (+ tmn tsk) 60)) (tinc_mn (- tinc_mn (* tinc_hr 60))) (thr_futur (* (+ thr tinc_hr) 100)) (tmn_futur tinc_mn) (tim_out (+ thr_futur tmn_futur)) ) ;; --- body of let ---- (message "tim_out: %d" tim_out) )) > While I was writing this, your two questions arrived: > > > 1. In what simple circumstances would one use a "setq" in the body of a let? > > One common idiom would be to create or consume a list inside a loop, e.g., > > ``` > (let ((lst (some-function-that-produces-a-list))) > (while (some-condition-on (car lst)) > (do-something-with (car lst)) > (setq lst (cdr lst)))) > ``` > > Nowadays such an idiom would more often be handled with a higher-order function > of the map/reduce/filter-family, but there may be situations in which that > doesn't work. > > Another example would be the case where you want to modify a value based on some > set of conditions, e.g.,: > > ``` > (let ((x (get-some-value)) > (y (get-some-other-value))) > (cond > ((some-condition-on y) > (setq x (do-something-with y))) > ((some-other-condition-on y) > (setq x (do-something-else-with x))) > (:otherwise > (setq y nil))) > (now-do-something-with x y)) > ``` > > You could probably rewrite this without `setq` using `let*` and some > intermediate variables, but sometimes I find using `setq` to be clearer, > especially if you have multiple values that are interdependent in complex ways. > > > 2. What simple option does one have that is more advantageous than using a "setq"? > > `let*` in the example function you gave above. For creating or consuming a list, > there's the map/filter/reduce-family or cl-loop. > > Not sure if that makes it any easier for a relative beginner :-/ but I hope it > helps a bit anyway. > > > -- > Joost Kremers > Life has its moments > > ^ permalink raw reply [flat|nested] 50+ messages in thread
* Re: Understanding the "let" construct and the setting of variables 2020-12-17 2:49 ` steve-humphreys @ 2020-12-17 7:58 ` Joost Kremers 2020-12-17 16:55 ` Drew Adams 0 siblings, 1 reply; 50+ messages in thread From: Joost Kremers @ 2020-12-17 7:58 UTC (permalink / raw) To: steve-humphreys; +Cc: help-gnu-emacs On Thu, Dec 17 2020, steve-humphreys@gmx.com wrote: > I ran the following > > ELISP> tima > (lett 845 80) > "tim_out: 1005" > > ELISP> tim > *** Eval error *** Symbol’s value as variable is void: tim > > ELISP> (lett 845 90) > "tim_out: 1015" > > ELISP> tim > *** Eval error *** Symbol’s value as variable is void: tim > > So this is quite different from using "setq". The variable "tim" is > not available to all of emacs. Yes, indeed. Variables bound with `let` or `let*` only exist inside the `let`. So as soon as you put the closing parenthesis matching the opening parenthesis directly before the `let`, the variables go out of scope and no longer exist. (There are actually a couple of subtleties involved that make this statement less than universally true, but those issues shouldn't concern a beginner.) -- Joost Kremers Life has its moments ^ permalink raw reply [flat|nested] 50+ messages in thread
* RE: Understanding the "let" construct and the setting of variables 2020-12-17 7:58 ` Joost Kremers @ 2020-12-17 16:55 ` Drew Adams 2020-12-17 20:11 ` steve-humphreys 0 siblings, 1 reply; 50+ messages in thread From: Drew Adams @ 2020-12-17 16:55 UTC (permalink / raw) To: Joost Kremers, steve-humphreys; +Cc: help-gnu-emacs > Yes, indeed. Variables bound with `let` or `let*` only exist inside the > `let`. > So as soon as you put the closing parenthesis matching the opening > parenthesis > directly before the `let`, the variables go out of scope and no longer exist. > (There are actually a couple of subtleties involved that make this statement > less than universally true, but those issues shouldn't concern a beginner.) This is not true of dynamically scoped, i.e. "special" vars. What is correct to say is that the let _binding_ of the variable no longer exists, not that the variable itself no longer exists. In the case of a dynamic variable, it continues to exist. And its binding from the let continues to exist as long as the code in the let body is executing. [Yes, some people will consider a let binding to create a _new_ variable. In that sense you can say that that var ceases to exist. But IMO that isn't as clear to users as it is to distinguish the binding from the var. And even if you use the words that way, you still need to point out that the var continues to exist as long as the code within the let body is executing (when the binding is for a dynamic var).] The best explanation of let binding in Elisp is in the Common Lisp doc, IMO. In particular, CLTL2's explanation of dynamic and lexical binding is quite clear. It applies equally to Elisp. https://www.cs.cmu.edu/Groups/AI/html/cltl/clm/node43.html ^ permalink raw reply [flat|nested] 50+ messages in thread
* Re: RE: Understanding the "let" construct and the setting of variables 2020-12-17 16:55 ` Drew Adams @ 2020-12-17 20:11 ` steve-humphreys 2020-12-17 21:57 ` Drew Adams 2020-12-17 22:35 ` Michael Heerdegen 0 siblings, 2 replies; 50+ messages in thread From: steve-humphreys @ 2020-12-17 20:11 UTC (permalink / raw) To: Drew Adams; +Cc: Joost Kremers, help-gnu-emacs > Sent: Thursday, December 17, 2020 at 5:55 PM > From: "Drew Adams" <drew.adams@oracle.com> > To: "Joost Kremers" <joostkremers@fastmail.fm>, steve-humphreys@gmx.com > Cc: help-gnu-emacs@gnu.org > Subject: RE: Understanding the "let" construct and the setting of variables > > > Yes, indeed. Variables bound with `let` or `let*` only exist inside the > > `let`. > > So as soon as you put the closing parenthesis matching the opening > > parenthesis > > directly before the `let`, the variables go out of scope and no longer exist. > > (There are actually a couple of subtleties involved that make this statement > > less than universally true, but those issues shouldn't concern a beginner.) > > This is not true of dynamically scoped, i.e. "special" > vars. > > What is correct to say is that the let _binding_ of the > variable no longer exists, not that the variable itself > no longer exists. > > In the case of a dynamic variable, it continues to exist. > And its binding from the let continues to exist as long > as the code in the let body is executing. > > [Yes, some people will consider a let binding to create > a _new_ variable. In that sense you can say that that > var ceases to exist. But IMO that isn't as clear to > users as it is to distinguish the binding from the var. > And even if you use the words that way, you still need > to point out that the var continues to exist as long as > the code within the let body is executing (when the > binding is for a dynamic var).] I would thing the variable has to be made somewhere. In fact people talk about "unboundp". > The best explanation of let binding in Elisp is in the > Common Lisp doc, IMO. In particular, CLTL2's explanation > of dynamic and lexical binding is quite clear. It applies > equally to Elisp. > > https://www.cs.cmu.edu/Groups/AI/html/cltl/clm/node43.html > > ^ permalink raw reply [flat|nested] 50+ messages in thread
* RE: RE: Understanding the "let" construct and the setting of variables 2020-12-17 20:11 ` steve-humphreys @ 2020-12-17 21:57 ` Drew Adams 2020-12-17 22:35 ` Michael Heerdegen 1 sibling, 0 replies; 50+ messages in thread From: Drew Adams @ 2020-12-17 21:57 UTC (permalink / raw) To: steve-humphreys; +Cc: Joost Kremers, help-gnu-emacs > > What is correct to say is that the let _binding_ of the > > variable no longer exists, not that the variable itself > > no longer exists. > > > > In the case of a dynamic variable, it continues to exist. > > And its binding from the let continues to exist as long > > as the code in the let body is executing. > > > > [Yes, some people will consider a let binding to create > > a _new_ variable. In that sense you can say that that > > var ceases to exist. But IMO that isn't as clear to > > users as it is to distinguish the binding from the var. > > And even if you use the words that way, you still need > > to point out that the var continues to exist as long as > > the code within the let body is executing (when the > > binding is for a dynamic var).] > > I would thing the variable has to be made somewhere. What's your point? Yes, you can think of either a variable being created or a binding being created. In the case of a local variable the two amount to different ways of talking about the same thing. But in the case of a dynamic variable, it's clearer, and more common, to talk about a new binding to the same var being created, rather than a new variable being created. In particular, a dynamic variable (its latest binding) can be accessed outside the lexical scope of the let. It's natural to think in terms of this in terms of the same var being bound, rebound, etc. in different ways over time. > In fact people talk about "unboundp". An unbound variable is a free variable with respect to some context. If a variable has no binding in any context then it's free/unbound at the top level. You can use `let' to bind a variable (dynamically or lexically). A function parameter gets bound as a local variable when the function is called. And `defvar' and `setq' can assign a value to a variable - that assignment is also a binding, of sorts. ^ permalink raw reply [flat|nested] 50+ messages in thread
* Re: Understanding the "let" construct and the setting of variables 2020-12-17 20:11 ` steve-humphreys 2020-12-17 21:57 ` Drew Adams @ 2020-12-17 22:35 ` Michael Heerdegen 2020-12-18 9:01 ` tomas 1 sibling, 1 reply; 50+ messages in thread From: Michael Heerdegen @ 2020-12-17 22:35 UTC (permalink / raw) To: help-gnu-emacs steve-humphreys@gmx.com writes: > I would thing the variable has to be made somewhere. > In fact people talk about "unboundp". A variable can be unbound. Would be hard to call `boundp' with a variable that doesn't exist. Michael. ^ permalink raw reply [flat|nested] 50+ messages in thread
* Re: Understanding the "let" construct and the setting of variables 2020-12-17 22:35 ` Michael Heerdegen @ 2020-12-18 9:01 ` tomas 2020-12-18 9:16 ` Michael Heerdegen 0 siblings, 1 reply; 50+ messages in thread From: tomas @ 2020-12-18 9:01 UTC (permalink / raw) To: help-gnu-emacs [-- Attachment #1: Type: text/plain, Size: 798 bytes --] On Thu, Dec 17, 2020 at 11:35:30PM +0100, Michael Heerdegen wrote: > steve-humphreys@gmx.com writes: > > > I would thing the variable has to be made somewhere. > > In fact people talk about "unboundp". > > A variable can be unbound. Would be hard to call `boundp' with a > variable that doesn't exist. But then, you don't call `boundp' on variables. You call it on symbols. AFAIK (but I could be wrong, corrections welcome!) there's no explicit notion of variable in Emacs Lisp, i.e. you cah't "have" a variable object and manipulate it directly. That doesn't mean they don't exist -- I fancy them living in the grey area between symbols and bindings. Again, the Elisp manual ("12 Variables" and, linked from there, "9 Symbols") makes for a good reading. Cheers - t [-- Attachment #2: Digital signature --] [-- Type: application/pgp-signature, Size: 198 bytes --] ^ permalink raw reply [flat|nested] 50+ messages in thread
* Re: Understanding the "let" construct and the setting of variables 2020-12-18 9:01 ` tomas @ 2020-12-18 9:16 ` Michael Heerdegen 2020-12-18 20:55 ` Emanuel Berg via Users list for the GNU Emacs text editor 0 siblings, 1 reply; 50+ messages in thread From: Michael Heerdegen @ 2020-12-18 9:16 UTC (permalink / raw) To: help-gnu-emacs <tomas@tuxteam.de> writes: > > > I would thing the variable has to be made somewhere. > > > In fact people talk about "unboundp". > > > > A variable can be unbound. Would be hard to call `boundp' with a > > variable that doesn't exist. > > But then, you don't call `boundp' on variables. You call it on > symbols. Yes, `boundp' is even lexical scoping agnostic, and (boundp t) ==> t, although `t' is not very...variable. > AFAIK (but I could be wrong, corrections welcome!) there's no explicit > notion of variable in Emacs Lisp, i.e. you cah't "have" a variable > object and manipulate it directly. > > That doesn't mean they don't exist -- I fancy them living in the grey > area between symbols and bindings. Well said. Regards, Michael. ^ permalink raw reply [flat|nested] 50+ messages in thread
* Re: Understanding the "let" construct and the setting of variables 2020-12-18 9:16 ` Michael Heerdegen @ 2020-12-18 20:55 ` Emanuel Berg via Users list for the GNU Emacs text editor 2020-12-19 2:17 ` Michael Heerdegen 0 siblings, 1 reply; 50+ messages in thread From: Emanuel Berg via Users list for the GNU Emacs text editor @ 2020-12-18 20:55 UTC (permalink / raw) To: help-gnu-emacs Michael Heerdegen wrote: > Yes, `boundp' is even lexical scoping agnostic, and (boundp > t) ==> t, although `t' is not very...variable. Try `defalias' 't to #'some-function... -- underground experts united http://user.it.uu.se/~embe8573 https://dataswamp.org/~incal ^ permalink raw reply [flat|nested] 50+ messages in thread
* Re: Understanding the "let" construct and the setting of variables 2020-12-18 20:55 ` Emanuel Berg via Users list for the GNU Emacs text editor @ 2020-12-19 2:17 ` Michael Heerdegen 2020-12-19 2:52 ` Drew Adams 2020-12-19 5:15 ` Stefan Monnier 0 siblings, 2 replies; 50+ messages in thread From: Michael Heerdegen @ 2020-12-19 2:17 UTC (permalink / raw) To: help-gnu-emacs Emanuel Berg via Users list for the GNU Emacs text editor <help-gnu-emacs@gnu.org> writes: > Try `defalias' 't to #'some-function... There is a sanity check in `fset' but it doesn't catch this case. It would sometimes be cool if one could funbind some constants, e.g. t -> (lambda (&rest _) t) nil -> #'ignore 1 -> #'identity but that would produce a big mess, it is probably no option in Emacs Lisp. Regards, Michael. ^ permalink raw reply [flat|nested] 50+ messages in thread
* RE: Understanding the "let" construct and the setting of variables 2020-12-19 2:17 ` Michael Heerdegen @ 2020-12-19 2:52 ` Drew Adams 2020-12-19 5:15 ` Stefan Monnier 1 sibling, 0 replies; 50+ messages in thread From: Drew Adams @ 2020-12-19 2:52 UTC (permalink / raw) To: Michael Heerdegen, help-gnu-emacs > but that would produce a big mess, it is probably > no option in Emacs Lisp. There are of course innumerable other ways Elisp lets you tie yourself in knots or shoot yourself in the foot. It even excels at that. ^ permalink raw reply [flat|nested] 50+ messages in thread
* Re: Understanding the "let" construct and the setting of variables 2020-12-19 2:17 ` Michael Heerdegen 2020-12-19 2:52 ` Drew Adams @ 2020-12-19 5:15 ` Stefan Monnier 1 sibling, 0 replies; 50+ messages in thread From: Stefan Monnier @ 2020-12-19 5:15 UTC (permalink / raw) To: help-gnu-emacs > t -> (lambda (&rest _) t) (fset t (lambda (&rest _) t)) seems to work fine here. > nil -> #'ignore This one does signal an error in `fset`. We could lift this error of course, but then we find other problems because nil is used as the marker that a function is "unbound", so subsequent calls to nil fail anyway. > 1 -> #'identity Here the problem is that 1 is not a symbol. You can do (fset '\1 #'identity) tho, after which (\1 42) returns 42. Stefan ^ permalink raw reply [flat|nested] 50+ messages in thread
* Re: Understanding the "let" construct and the setting of variables 2020-12-17 0:21 ` Joost Kremers 2020-12-17 2:08 ` steve-humphreys 2020-12-17 2:49 ` steve-humphreys @ 2020-12-18 20:33 ` Emanuel Berg via Users list for the GNU Emacs text editor 2 siblings, 0 replies; 50+ messages in thread From: Emanuel Berg via Users list for the GNU Emacs text editor @ 2020-12-18 20:33 UTC (permalink / raw) To: help-gnu-emacs Joost Kremers wrote: > I'm not sure what exactly you're asking, (I'm wondering if > your message is complete or was accidentally sent before you > finished it), but to understand the problem with `setq`, > evaluate your function above in the `*scratch*` buffer. > (Copy the function into the `*scratch*` buffer, put the > cursor right after it and press `C-x C-e`; note that you > need to add another closing parenthesis on the last line). > That will define your function and make it available > to Emacs. > > Then open a Lisp interaction buffer with `M-x ielm RET`. > You'll get a buffer called `*ielm*` with a prompt where you > can type Elisp expressions that get executed right away. > Type `tim` (without parentheses) and hit RET. You should get > a void variable error: > > *** Eval error *** Symbol’s value as variable is void: > tim" You (the OP) can also just keep it in the elisp-mode buffer where it was written, eval it (as you say) and then just invoke it interactively (with M-x) or from Lisp, to test it that way. One way to do it from Lisp is again to stay in the same file, just add a commented out line after the function ;; (some-function test-var-1 test-var-2) and the eval that. -- underground experts united http://user.it.uu.se/~embe8573 https://dataswamp.org/~incal ^ permalink raw reply [flat|nested] 50+ messages in thread
* Re: Understanding the "let" construct and the setting of variables 2020-12-17 0:10 Understanding the "let" construct and the setting of variables steve-humphreys 2020-12-17 0:21 ` Joost Kremers @ 2020-12-17 0:25 ` steve-humphreys 2020-12-17 0:35 ` steve-humphreys ` (2 more replies) 2020-12-18 15:33 ` Emanuel Berg via Users list for the GNU Emacs text editor 2 siblings, 3 replies; 50+ messages in thread From: steve-humphreys @ 2020-12-17 0:25 UTC (permalink / raw) To: steve-humphreys; +Cc: Help Gnu Emacs Let's introspect two questions. 1. In what simple circumstances would one use a "setq" in the body of a let? 2. What simple option does one have that is more advantageous than using a "setq"? > Sent: Thursday, December 17, 2020 at 1:10 AM > From: steve-humphreys@gmx.com > To: "Help Gnu Emacs" <help-gnu-emacs@gnu.org> > Subject: Understanding the "let" construct and the setting of variables > > I have been writing some elisp to set the time grid in the agenda. > The discussion progressed towards the use of the "let" construct. > > But, the discussion got too advanced for me to follow the different > points of view and make a decision. > > This message is for showing some examples, of how to set and use variables > in a "let", because people criticise using "setq". But discussion needs > simple examples that would not overwhelm a relative beginner. > > (defun timfutur () > (interactive) > (setq tim 845) > (setq tsk 80) > > (setq thr (/ tim 100)) > (setq tmn (- tim (* thr 100))) > > (setq tinc_mn (+ tmn tsk)) > (setq tinc_hr (/ (+ tmn tsk) 60)) > (setq tinc_mn (- tinc_mn (* tinc_hr 60)) ) > > (setq thr_futur (* (+ thr tinc_hr) 100) ) > (setq tmn_futur tinc_mn) > (setq tim_out (+ thr_futur tmn_futur)) > > > > > > ^ permalink raw reply [flat|nested] 50+ messages in thread
* Re: Understanding the "let" construct and the setting of variables 2020-12-17 0:25 ` steve-humphreys @ 2020-12-17 0:35 ` steve-humphreys 2020-12-17 1:05 ` Joost Kremers 2020-12-17 4:34 ` Jean Louis 2020-12-18 17:14 ` Emanuel Berg via Users list for the GNU Emacs text editor 2 siblings, 1 reply; 50+ messages in thread From: steve-humphreys @ 2020-12-17 0:35 UTC (permalink / raw) To: steve-humphreys; +Cc: Help Gnu Emacs For example, the following fails. Why? Haw can one fix the function? (defun lett (tim tsk) (let* ( (thr (/ tim 100)) (tmn (- tim (* thr 100))) (tinc_mn (+ tmn tsk)) (tinc_hr (/ (+ tmn tsk) 60)) (tinc_mn (- tinc_mn (* tinc_hr 60))) (thr_futur (* (+ thr tinc_hr) 100)) (tmn_futur tinc_mn) (tim_out (+ thr_futur tmn_futur)) (message "%d %d" tim_out) ) (message "%s" "lett") )) (lett 845 80) > Sent: Thursday, December 17, 2020 at 1:25 AM > From: steve-humphreys@gmx.com > To: steve-humphreys@gmx.com > Cc: "Help Gnu Emacs" <help-gnu-emacs@gnu.org> > Subject: Re: Understanding the "let" construct and the setting of variables > > Let's introspect two questions. > > 1. In what simple circumstances would one use a "setq" in the body of a let? > 2. What simple option does one have that is more advantageous than using a "setq"? > > > > > Sent: Thursday, December 17, 2020 at 1:10 AM > > From: steve-humphreys@gmx.com > > To: "Help Gnu Emacs" <help-gnu-emacs@gnu.org> > > Subject: Understanding the "let" construct and the setting of variables > > > > I have been writing some elisp to set the time grid in the agenda. > > The discussion progressed towards the use of the "let" construct. > > > > But, the discussion got too advanced for me to follow the different > > points of view and make a decision. > > > > This message is for showing some examples, of how to set and use variables > > in a "let", because people criticise using "setq". But discussion needs > > simple examples that would not overwhelm a relative beginner. > > > > (defun timfutur () > > (interactive) > > (setq tim 845) > > (setq tsk 80) > > > > (setq thr (/ tim 100)) > > (setq tmn (- tim (* thr 100))) > > > > (setq tinc_mn (+ tmn tsk)) > > (setq tinc_hr (/ (+ tmn tsk) 60)) > > (setq tinc_mn (- tinc_mn (* tinc_hr 60)) ) > > > > (setq thr_futur (* (+ thr tinc_hr) 100) ) > > (setq tmn_futur tinc_mn) > > (setq tim_out (+ thr_futur tmn_futur)) > > > > > > > > > > > > > > ^ permalink raw reply [flat|nested] 50+ messages in thread
* Re: Understanding the "let" construct and the setting of variables 2020-12-17 0:35 ` steve-humphreys @ 2020-12-17 1:05 ` Joost Kremers 2020-12-17 1:20 ` steve-humphreys 0 siblings, 1 reply; 50+ messages in thread From: Joost Kremers @ 2020-12-17 1:05 UTC (permalink / raw) To: steve-humphreys; +Cc: help-gnu-emacs On Thu, Dec 17 2020, steve-humphreys@gmx.com wrote: > For example, the following fails. Why? Haw can one fix the function? > > (defun lett (tim tsk) > > (let* ( (thr (/ tim 100)) > (tmn (- tim (* thr 100))) > > (tinc_mn (+ tmn tsk)) > (tinc_hr (/ (+ tmn tsk) 60)) > (tinc_mn (- tinc_mn (* tinc_hr 60))) > > (thr_futur (* (+ thr tinc_hr) 100)) > (tmn_futur tinc_mn) > (tim_out (+ thr_futur tmn_futur)) > > (message "%d %d" tim_out) ) > > (message "%s" "lett") )) > > (lett 845 80) The error is a bit cryptic, but it's telling you that you need to move the first `message` into the body of the `let*`. Right now, it's in the list of variables to bind, but it's not a valid binding form: ``` (defun lett (tim tsk) (let* ((thr (/ tim 100)) (tmn (- tim (* thr 100))) (tinc_mn (+ tmn tsk)) (tinc_hr (/ (+ tmn tsk) 60)) (tinc_mn (- tinc_mn (* tinc_hr 60))) (thr_futur (* (+ thr tinc_hr) 100)) (tmn_futur tinc_mn) (tim_out (+ thr_futur tmn_futur))) (message "%d %d" tim_out) (message "%s" "lett") )) ``` Note that this will still produce an error, because the first `message` has a format string that requires two arguments but only one is given. -- Joost Kremers Life has its moments ^ permalink raw reply [flat|nested] 50+ messages in thread
* Re: Understanding the "let" construct and the setting of variables 2020-12-17 1:05 ` Joost Kremers @ 2020-12-17 1:20 ` steve-humphreys 2020-12-18 20:58 ` Emanuel Berg via Users list for the GNU Emacs text editor 0 siblings, 1 reply; 50+ messages in thread From: steve-humphreys @ 2020-12-17 1:20 UTC (permalink / raw) To: Joost Kremers; +Cc: help-gnu-emacs > Sent: Thursday, December 17, 2020 at 2:05 AM > From: "Joost Kremers" <joostkremers@fastmail.fm> > To: steve-humphreys@gmx.com > Cc: help-gnu-emacs@gnu.org > Subject: Re: Understanding the "let" construct and the setting of variables > > > On Thu, Dec 17 2020, steve-humphreys@gmx.com wrote: > > For example, the following fails. Why? Haw can one fix the function? > > > > (defun lett (tim tsk) > > > > (let* ( (thr (/ tim 100)) > > (tmn (- tim (* thr 100))) > > > > (tinc_mn (+ tmn tsk)) > > (tinc_hr (/ (+ tmn tsk) 60)) > > (tinc_mn (- tinc_mn (* tinc_hr 60))) > > > > (thr_futur (* (+ thr tinc_hr) 100)) > > (tmn_futur tinc_mn) > > (tim_out (+ thr_futur tmn_futur)) > > > > (message "%d %d" tim_out) ) > > > > (message "%s" "lett") )) > > > > (lett 845 80) > > The error is a bit cryptic, but it's telling you that you need to move the first > `message` into the body of the `let*`. Right now, it's in the list of variables > to bind, but it's not a valid binding form: > > ``` > (defun lett (tim tsk) > > (let* ((thr (/ tim 100)) > (tmn (- tim (* thr 100))) > > (tinc_mn (+ tmn tsk)) > (tinc_hr (/ (+ tmn tsk) 60)) > (tinc_mn (- tinc_mn (* tinc_hr 60))) > > (thr_futur (* (+ thr tinc_hr) 100)) > (tmn_futur tinc_mn) > (tim_out (+ thr_futur tmn_futur))) > > (message "%d %d" tim_out) > > (message "%s" "lett") )) > ``` > > Note that this will still produce an error, because the first `message` has a > format string that requires two arguments but only one is given. This means that I can use the variables in the body of the "let". Great explanation, I fixed to. Now I need to have the function output "tim_out". > -- > Joost Kremers > Life has its moments > ^ permalink raw reply [flat|nested] 50+ messages in thread
* Re: Understanding the "let" construct and the setting of variables 2020-12-17 1:20 ` steve-humphreys @ 2020-12-18 20:58 ` Emanuel Berg via Users list for the GNU Emacs text editor 0 siblings, 0 replies; 50+ messages in thread From: Emanuel Berg via Users list for the GNU Emacs text editor @ 2020-12-18 20:58 UTC (permalink / raw) To: help-gnu-emacs steve-humphreys wrote: > This means that I can use the variables in the body of the > "let". ... I mean, yeah, that's the purpose of `let'! That, and to do computation already in the varlist, to prepare and adapt for what should happen in the body. Now we are talking normal everyday programming at a basic level, or "lexical scope" to some people :) -- underground experts united http://user.it.uu.se/~embe8573 https://dataswamp.org/~incal ^ permalink raw reply [flat|nested] 50+ messages in thread
* Re: Understanding the "let" construct and the setting of variables 2020-12-17 0:25 ` steve-humphreys 2020-12-17 0:35 ` steve-humphreys @ 2020-12-17 4:34 ` Jean Louis 2020-12-17 5:12 ` steve-humphreys ` (2 more replies) 2020-12-18 17:14 ` Emanuel Berg via Users list for the GNU Emacs text editor 2 siblings, 3 replies; 50+ messages in thread From: Jean Louis @ 2020-12-17 4:34 UTC (permalink / raw) To: steve-humphreys; +Cc: Help Gnu Emacs > -*- lexical-binding: t; -*- * steve-humphreys@gmx.com <steve-humphreys@gmx.com> [2020-12-17 03:26]: > Let's introspect two questions. > > 1. In what simple circumstances would one use a "setq" in the body > of a let? Whenever I find myself in linear programming within a function and need to change variable I will use setq. Some global variables are rather set with setq: (set-buffer buffer) (setq header-line-format (concat buffer " ➜ Finish with `q' or `h'")) (cf-org-view-mode) (insert blob) (setq org-hierarchical-todo-statistics nil) (org-update-parent-todo-statistics) (goto-char 1) But I will often use it in construction of lists: (defun rcd-cgi-parse-query-string (query-string) "Parse QUERY-STRING that normally comes from the environment variable `QUERY_STRING'. Return PLIST." (let* ((query-string (url-unhex-string query-string)) (parts (split-string query-string "&")) (length (length parts)) (plist '())) (dolist (part parts plist) (let* ((data (split-string part "=")) (prop (car data)) (val (cadr data))) (setq plist (plist-put plist (intern prop) val)))))) (defun iota (count &optional start step) "Return a list containing COUNT numbers, starting from START and adding STEP each time. The default START is 0, the default STEP is 1" (let* ((start (if start start 0)) (step (if step step 1)) (last (+ start count)) (counter 0) (list '()) (elt start)) (while (< counter count) (push elt list) (setq elt (+ elt step)) (setq counter (1+ counter))) (reverse list))) How I understand it is that `setq' I can freely use on variables already defined with and within my `let' as then the variable will not become global. (defun my-fun () (let ((my-var nil)) (setq my-var 2))) (my-fun) my-var is not defined (defun my-fun () (let ((my-var nil))) (setq my-var 2)) (my-fun) my-var is here defined as 2 and became global variable. And each time that variable is already defined with `defvar' one can then change it with setq. Jean ^ permalink raw reply [flat|nested] 50+ messages in thread
* Re: Understanding the "let" construct and the setting of variables 2020-12-17 4:34 ` Jean Louis @ 2020-12-17 5:12 ` steve-humphreys 2020-12-19 6:06 ` Emanuel Berg via Users list for the GNU Emacs text editor 2020-12-17 7:31 ` steve-humphreys 2020-12-19 5:55 ` Emanuel Berg via Users list for the GNU Emacs text editor 2 siblings, 1 reply; 50+ messages in thread From: steve-humphreys @ 2020-12-17 5:12 UTC (permalink / raw) To: Jean Louis; +Cc: Help Gnu Emacs > How I understand it is that `setq' I can freely use on variables > already defined with and within my `let' as then the variable > will not become global. > > (defun my-fun () > (let ((my-var nil)) > (setq my-var 2))) > > (my-fun) > > my-var is not defined Here the variable remains local. my-var does not become a global variable because it is defined within the let. So one can use "set" with variables defined in a "let" construct. I thought you could not do that - call "setq" on a local variable defined in a "let" expression. > (defun my-fun () > (let ((my-var nil))) > (setq my-var 2)) > > (my-fun) > > my-var is here defined as 2 and became global variable. > > And each time that variable is already defined with `defvar' one > can then change it with setq. And here "my-var" becames a global variable because my-var is set using "setq" outside the "let" expression. Thanks. Was not too difficult as I thought. > Sent: Thursday, December 17, 2020 at 5:34 AM > From: "Jean Louis" <bugs@gnu.support> > To: steve-humphreys@gmx.com > Cc: "Help Gnu Emacs" <help-gnu-emacs@gnu.org> > Subject: Re: Understanding the "let" construct and the setting of variables > > > -*- lexical-binding: t; -*- > * steve-humphreys@gmx.com <steve-humphreys@gmx.com> [2020-12-17 03:26]: > > Let's introspect two questions. > > > > 1. In what simple circumstances would one use a "setq" in the body > > of a let? > > Whenever I find myself in linear programming within a function and > need to change variable I will use setq. Some global variables are > rather set with setq: > > (set-buffer buffer) > (setq header-line-format (concat buffer " ➜ Finish with `q' or `h'")) > (cf-org-view-mode) > (insert blob) > (setq org-hierarchical-todo-statistics nil) > (org-update-parent-todo-statistics) > (goto-char 1) > > But I will often use it in construction of lists: > > (defun rcd-cgi-parse-query-string (query-string) > "Parse QUERY-STRING that normally comes from the environment > variable `QUERY_STRING'. Return PLIST." > (let* ((query-string (url-unhex-string query-string)) > (parts (split-string query-string "&")) > (length (length parts)) > (plist '())) > (dolist (part parts plist) > (let* ((data (split-string part "=")) > (prop (car data)) > (val (cadr data))) > (setq plist (plist-put plist (intern prop) val)))))) > > > (defun iota (count &optional start step) > "Return a list containing COUNT numbers, starting from START > and adding STEP each time. The default START is 0, the default > STEP is 1" > (let* ((start (if start start 0)) > (step (if step step 1)) > (last (+ start count)) > (counter 0) > (list '()) > (elt start)) > (while (< counter count) > (push elt list) > (setq elt (+ elt step)) > (setq counter (1+ counter))) > (reverse list))) > > How I understand it is that `setq' I can freely use on variables > already defined with and within my `let' as then the variable > will not become global. > > (defun my-fun () > (let ((my-var nil)) > (setq my-var 2))) > > (my-fun) > > my-var is not defined > > (defun my-fun () > (let ((my-var nil))) > (setq my-var 2)) > > (my-fun) > > my-var is here defined as 2 and became global variable. > > And each time that variable is already defined with `defvar' one > can then change it with setq. > > Jean > ^ permalink raw reply [flat|nested] 50+ messages in thread
* Re: Understanding the "let" construct and the setting of variables 2020-12-17 5:12 ` steve-humphreys @ 2020-12-19 6:06 ` Emanuel Berg via Users list for the GNU Emacs text editor 0 siblings, 0 replies; 50+ messages in thread From: Emanuel Berg via Users list for the GNU Emacs text editor @ 2020-12-19 6:06 UTC (permalink / raw) To: help-gnu-emacs steve-humphreys wrote: > Here the variable remains local. my-var does not become > a global variable because it is defined within the let. > So one can use "set" with variables defined in a "let" > construct. I thought you could not do that - call "setq" on > a local variable defined in a "let" expression. But often it isn't needed. >> (defun my-fun () >> (let ((my-var nil))) >> (setq my-var 2)) >> >> (my-fun) >> >> my-var is here defined as 2 and became global variable. >> >> And each time that variable is already defined with `defvar' one >> can then change it with setq. > > And here "my-var" becames a global variable because my-var > is set using "setq" outside the "let" expression. Yes, but here lies the problem and danger with using `setq' within `let/let*', because that will also create a global variable if it isn't in the let varlist already. Everything is global in Elisp BTW except the stuff you'll find for example within special forms like `let'. That's another reason you ought to use them as often as you can, to encapsulate all the little pieces, to hide the machinery from the rest of the world and only present a clean and easily defined/understood interface. f(x) = y so tell everyone, give f x and you'll get y. But how that happens, how y is computed from x, is f's business and there is no need, actually it should be avoided, there is no need to clutter the global space with stuff that only concerns f. Note that this mathematical example doesn't have to be math. It can be a Quake game, or whatever. Quake, which is based on linear algebra and spatial geometry. OK, bad example. -- underground experts united http://user.it.uu.se/~embe8573 https://dataswamp.org/~incal ^ permalink raw reply [flat|nested] 50+ messages in thread
* Re: Understanding the "let" construct and the setting of variables 2020-12-17 4:34 ` Jean Louis 2020-12-17 5:12 ` steve-humphreys @ 2020-12-17 7:31 ` steve-humphreys 2020-12-19 5:55 ` Emanuel Berg via Users list for the GNU Emacs text editor 2 siblings, 0 replies; 50+ messages in thread From: steve-humphreys @ 2020-12-17 7:31 UTC (permalink / raw) To: Jean Louis; +Cc: Help Gnu Emacs Can you be so kind to help me output tim_out from the following function. I do not know in which construct to insert the output. If inside the "let" variable definition area, in the body of the "let" construct , or if outside the "let". Regards (defun timfutur (tim tsk) (let* ( (thr (/ tim 100)) (tmn (- tim (* thr 100))) (tinc_mn (+ tmn tsk)) (tinc_hr (/ (+ tmn tsk) 60)) (tinc_mn (- tinc_mn (* tinc_hr 60))) (thr_futur (* (+ thr tinc_hr) 100)) (tmn_futur tinc_mn) (tim_out (+ thr_futur tmn_futur)) ) ;; --- body of let ---- (message "tim_out: %d" tim_out) )) > Sent: Thursday, December 17, 2020 at 5:34 AM > From: "Jean Louis" <bugs@gnu.support> > To: steve-humphreys@gmx.com > Cc: "Help Gnu Emacs" <help-gnu-emacs@gnu.org> > Subject: Re: Understanding the "let" construct and the setting of variables > > > -*- lexical-binding: t; -*- > * steve-humphreys@gmx.com <steve-humphreys@gmx.com> [2020-12-17 03:26]: > > Let's introspect two questions. > > > > 1. In what simple circumstances would one use a "setq" in the body > > of a let? > > Whenever I find myself in linear programming within a function and > need to change variable I will use setq. Some global variables are > rather set with setq: > > (set-buffer buffer) > (setq header-line-format (concat buffer " ➜ Finish with `q' or `h'")) > (cf-org-view-mode) > (insert blob) > (setq org-hierarchical-todo-statistics nil) > (org-update-parent-todo-statistics) > (goto-char 1) > > But I will often use it in construction of lists: > > (defun rcd-cgi-parse-query-string (query-string) > "Parse QUERY-STRING that normally comes from the environment > variable `QUERY_STRING'. Return PLIST." > (let* ((query-string (url-unhex-string query-string)) > (parts (split-string query-string "&")) > (length (length parts)) > (plist '())) > (dolist (part parts plist) > (let* ((data (split-string part "=")) > (prop (car data)) > (val (cadr data))) > (setq plist (plist-put plist (intern prop) val)))))) > > > (defun iota (count &optional start step) > "Return a list containing COUNT numbers, starting from START > and adding STEP each time. The default START is 0, the default > STEP is 1" > (let* ((start (if start start 0)) > (step (if step step 1)) > (last (+ start count)) > (counter 0) > (list '()) > (elt start)) > (while (< counter count) > (push elt list) > (setq elt (+ elt step)) > (setq counter (1+ counter))) > (reverse list))) > > How I understand it is that `setq' I can freely use on variables > already defined with and within my `let' as then the variable > will not become global. > > (defun my-fun () > (let ((my-var nil)) > (setq my-var 2))) > > (my-fun) > > my-var is not defined > > (defun my-fun () > (let ((my-var nil))) > (setq my-var 2)) > > (my-fun) > > my-var is here defined as 2 and became global variable. > > And each time that variable is already defined with `defvar' one > can then change it with setq. > > Jean > ^ permalink raw reply [flat|nested] 50+ messages in thread
* Re: Understanding the "let" construct and the setting of variables 2020-12-17 4:34 ` Jean Louis 2020-12-17 5:12 ` steve-humphreys 2020-12-17 7:31 ` steve-humphreys @ 2020-12-19 5:55 ` Emanuel Berg via Users list for the GNU Emacs text editor 2020-12-19 6:49 ` Jean Louis 2 siblings, 1 reply; 50+ messages in thread From: Emanuel Berg via Users list for the GNU Emacs text editor @ 2020-12-19 5:55 UTC (permalink / raw) To: help-gnu-emacs Jean Louis wrote: > But I will often use it in construction of lists I think you can avoid using `setq' with lists, strings etc in loops by using `cl-loop' with accumulation. In the docstring, it says: [...] Accumulation clauses: collect/append/nconc/concat/vconcat/count/sum/maximize/minimize FORM [into VAR] Try it :) -- underground experts united http://user.it.uu.se/~embe8573 https://dataswamp.org/~incal ^ permalink raw reply [flat|nested] 50+ messages in thread
* Re: Understanding the "let" construct and the setting of variables 2020-12-19 5:55 ` Emanuel Berg via Users list for the GNU Emacs text editor @ 2020-12-19 6:49 ` Jean Louis 2020-12-20 5:19 ` Emanuel Berg via Users list for the GNU Emacs text editor 0 siblings, 1 reply; 50+ messages in thread From: Jean Louis @ 2020-12-19 6:49 UTC (permalink / raw) To: help-gnu-emacs * Emanuel Berg via Users list for the GNU Emacs text editor <help-gnu-emacs@gnu.org> [2020-12-19 08:56]: > Jean Louis wrote: > > > But I will often use it in construction of lists > > I think you can avoid using `setq' with lists, strings etc in > loops by using `cl-loop' with accumulation. I am avoiding cl functions by principle to make it easier. It does not matter. ^ permalink raw reply [flat|nested] 50+ messages in thread
* Re: Understanding the "let" construct and the setting of variables 2020-12-19 6:49 ` Jean Louis @ 2020-12-20 5:19 ` Emanuel Berg via Users list for the GNU Emacs text editor 0 siblings, 0 replies; 50+ messages in thread From: Emanuel Berg via Users list for the GNU Emacs text editor @ 2020-12-20 5:19 UTC (permalink / raw) To: help-gnu-emacs Jean Louis wrote: >> I think you can avoid using `setq' with lists, strings etc >> in loops by using `cl-loop' with accumulation. > > I am avoiding cl functions by principle to make it easier. > It does not matter. They are very useful. I've used 24 of them, 86 times :) It is not really CL. cl-lib.el is in Elisp. So the cl- prefix is nothing to be afraid of, on the contrary it's great stuff :) Some of the stuff I don't know why I used tho, cl-caddr for example. Because there is a caddr, in subr.el... cl-caddr cl-case cl-concatenate cl-defun cl-digit-char-p cl-dolist cl-find-if cl-first cl-gensym cl-incf cl-labels cl-lib cl-loop cl-map cl-mapcan cl-mapcar cl-position cl-pushnew cl-remove cl-remove-if-not cl-return cl-set-exclusive-or cl-sort cl-subseq -- underground experts united http://user.it.uu.se/~embe8573 https://dataswamp.org/~incal ^ permalink raw reply [flat|nested] 50+ messages in thread
* Re: Understanding the "let" construct and the setting of variables 2020-12-17 0:25 ` steve-humphreys 2020-12-17 0:35 ` steve-humphreys 2020-12-17 4:34 ` Jean Louis @ 2020-12-18 17:14 ` Emanuel Berg via Users list for the GNU Emacs text editor 2020-12-18 17:48 ` tomas 2 siblings, 1 reply; 50+ messages in thread From: Emanuel Berg via Users list for the GNU Emacs text editor @ 2020-12-18 17:14 UTC (permalink / raw) To: help-gnu-emacs steve-humphreys wrote: > Let's introspect two questions. > > 1. In what simple circumstances would one use a "setq" in > the body of a let? When one wants to change a global variable that already exists outside of the function. Try to avoid this situation altogether but if it is there, it is there I guess, and sure, you can set it with `setq' to whatever you want :) > 2. What simple option does one have that is more > advantageous than using a "setq"? Use `let' and/or `let*' for everything else... -- underground experts united http://user.it.uu.se/~embe8573 https://dataswamp.org/~incal ^ permalink raw reply [flat|nested] 50+ messages in thread
* Re: Understanding the "let" construct and the setting of variables 2020-12-18 17:14 ` Emanuel Berg via Users list for the GNU Emacs text editor @ 2020-12-18 17:48 ` tomas 0 siblings, 0 replies; 50+ messages in thread From: tomas @ 2020-12-18 17:48 UTC (permalink / raw) To: help-gnu-emacs [-- Attachment #1: Type: text/plain, Size: 1045 bytes --] On Fri, Dec 18, 2020 at 06:14:04PM +0100, Emanuel Berg via Users list for the GNU Emacs text editor wrote: > steve-humphreys wrote: > > > Let's introspect two questions. > > > > 1. In what simple circumstances would one use a "setq" in > > the body of a let? > > When one wants to change a global variable that already exists > outside of the function. Or a local, if that has been locally bound, e.g. by a let or a function param: (defun collatz-sequence (n) ; [1] (while (> n 1) (insert (format "%5d\n" n)) (setq n (if (= (mod n 2) 0) (/ n 2) (+ (* n 3) 1))))) (collatz-sequence 11) => 11 34 17 52 26 13 40 20 10 5 16 8 4 2 Yeah, the 1 at the end is missing. Left as an exercise for the reader :) The setq in the function's last line modifies the n which is local to the function, because it's in the parameter list (which is roughly equivalent to a let list). Cheers [1] https://en.wikipedia.org/wiki/Collatz_conjecture - t [-- Attachment #2: Digital signature --] [-- Type: application/pgp-signature, Size: 198 bytes --] ^ permalink raw reply [flat|nested] 50+ messages in thread
* Re: Understanding the "let" construct and the setting of variables 2020-12-17 0:10 Understanding the "let" construct and the setting of variables steve-humphreys 2020-12-17 0:21 ` Joost Kremers 2020-12-17 0:25 ` steve-humphreys @ 2020-12-18 15:33 ` Emanuel Berg via Users list for the GNU Emacs text editor 2020-12-18 18:12 ` Jean Louis 2 siblings, 1 reply; 50+ messages in thread From: Emanuel Berg via Users list for the GNU Emacs text editor @ 2020-12-18 15:33 UTC (permalink / raw) To: help-gnu-emacs steve-humphreys wrote: > This message is for showing some examples, of how to set and > use variables in a "let", because people criticise using > "setq". But discussion needs simple examples that would not > overwhelm a relative beginner. On the contrary, it is very simple! 0. you are writing a `defun'... 1. start with `let' 2. if isn't enough because computation builds upon computation, which is very common, use `let*'. And don't be afraid to use `let's simply for code clarity. Break up computation into small steps. But also steps that makes sense (for the human brain). Such steps, small that makes sense, are the best. 3. if that isn't enough to use let/let* because several functions need to access a variable, use `setq' at the base level (i.e., first char of the line, or column 0) - not that Elisp has only one level, really, which is why you should use `setq' there to avoid confusion and errors. Because everyone can see what is created by `setq', this should be visible in the code style as well. Note that just because it would seem that two functions need access to the same variable, this actually doesn't have to be the case at all! Think it thru one extra time before you do it. 4. If a function uses a variable that has the character of an option, i.e. you are likely to fiddle with it back and forth, it can make sense to break it out and use a setq. Then you can provide it will be available to the on-line help and, if you like, you can provide it with a docstring. When you later fiddle with it to get it just right this will be less error prone than if it is embedded in the function, because then to make it come to effect, you have to re-eval the whole function. 5. If you write single function, only this function need a state (a memory) you can use setq for that outside the function. But you can also do that with properties, here [last] is an example. Bind that to, say, `C-c j'. Now, invoke with just C-c j. But with `C-u C-c j', you set the state, or in this case the pad-col property, to a new value (yeah, one would guess new, otherwise why do it?) So the next time you invoke it with just C-c j what will happen will act upon that new state. (TBH I don't know how well it works - I just wrote it :) - but it seems to work, I just tried it with this [1]) So use let, then let*, then setq outside of the functions and when you do think twice what the reason is you have to do it, and if there really inset some other way? Note that it isn't wrong to use setq even inside of functions when you know what you are doing and that's what you really intend to do and there isn't any other way to do it. It is just that 9/10 times, there is. [1] https://dataswamp.org/~incal/conf/mpv/input.conf (defun pad-to-col (&optional set-new-col) (interactive "p") (let*((plist (symbol-plist #'pad-to-col)) (prop 'pad-col) (pad-col (or (plist-get plist prop) 0)) (beg-col (or (current-column) 4)) ) (if (and set-new-col (= 4 set-new-col)) (progn (plist-put plist prop beg-col) (message "pad col set: %s" beg-col) ) (let ((step (- pad-col beg-col))) (when (> step 0) (insert (make-string step ?\s)) (forward-line 1) (forward-char beg-col) ))))) -- underground experts united http://user.it.uu.se/~embe8573 https://dataswamp.org/~incal ^ permalink raw reply [flat|nested] 50+ messages in thread
* Re: Understanding the "let" construct and the setting of variables 2020-12-18 15:33 ` Emanuel Berg via Users list for the GNU Emacs text editor @ 2020-12-18 18:12 ` Jean Louis 2020-12-18 18:20 ` Drew Adams ` (2 more replies) 0 siblings, 3 replies; 50+ messages in thread From: Jean Louis @ 2020-12-18 18:12 UTC (permalink / raw) To: help-gnu-emacs * Emanuel Berg via Users list for the GNU Emacs text editor <help-gnu-emacs@gnu.org> [2020-12-18 18:43]: > > 3. if that isn't enough to use let/let* because several > functions need to access a variable, use `setq' at the base > level (i.e., first char of the line, or column 0) - not > that Elisp has only one level, really, which is why you > should use `setq' there to avoid confusion and errors. > Because everyone can see what is created by `setq', this > should be visible in the code style as well. > > Note that just because it would seem that two functions > need access to the same variable, this actually doesn't > have to be the case at all! Think it thru one extra time > before you do it. Instructions like that belong on a website where they become easily searchable for other users to understand it. We could index all the mailing list easily and provide search engine for this. ^ permalink raw reply [flat|nested] 50+ messages in thread
* RE: Understanding the "let" construct and the setting of variables 2020-12-18 18:12 ` Jean Louis @ 2020-12-18 18:20 ` Drew Adams 2020-12-18 18:45 ` Jean Louis 2020-12-18 21:27 ` Christopher Dimech 2020-12-19 6:23 ` Emanuel Berg via Users list for the GNU Emacs text editor 2 siblings, 1 reply; 50+ messages in thread From: Drew Adams @ 2020-12-18 18:20 UTC (permalink / raw) To: Jean Louis, help-gnu-emacs > Instructions like that belong on a website where they become easily > searchable for other users to understand it. > > We could index all the mailing list easily and provide search engine > for this. https://lists.gnu.org/archive/html/help-gnu-emacs/ Searching there for "Instructions like that" I get: https://lists.gnu.org/archive/cgi-bin/namazu.cgi?query=%22Instructions+like+that%22&submit=Search%21&idxname=help-gnu-emacs&max=20&result=normal&sort=score ^ permalink raw reply [flat|nested] 50+ messages in thread
* Re: Understanding the "let" construct and the setting of variables 2020-12-18 18:20 ` Drew Adams @ 2020-12-18 18:45 ` Jean Louis 2020-12-18 19:16 ` Drew Adams 0 siblings, 1 reply; 50+ messages in thread From: Jean Louis @ 2020-12-18 18:45 UTC (permalink / raw) To: Drew Adams; +Cc: help-gnu-emacs * Drew Adams <drew.adams@oracle.com> [2020-12-18 21:23]: > > Instructions like that belong on a website where they become easily > > searchable for other users to understand it. > > > > We could index all the mailing list easily and provide search engine > > for this. > > https://lists.gnu.org/archive/html/help-gnu-emacs/ > > Searching there for "Instructions like that" I get: > > https://lists.gnu.org/archive/cgi-bin/namazu.cgi?query=%22Instructions+like+that%22&submit=Search%21&idxname=help-gnu-emacs&max=20&result=normal&sort=score Maybe. But I have got a feeling that is unused search. What I was meaning but did not express it that search should be exposed to public. I am not sure if that namazu search engine provides good relevancy: I found this link: https://lists.gnu.org/archive/cgi-bin/namazu.cgi?query=emacs+float+&submit=Search%21&idxname=help-gnu-emacs&max=20&result=normal&sort=score Then I can see there: . Re: Inconsistency: sometimes an integer, sometimes a float and if I search for: inconsistency sometime integer sometimes float https://lists.gnu.org/archive/cgi-bin/namazu.cgi?query=inconsistency+sometime+integer+sometimes+float&submit=Search%21&idxname=help-gnu-emacs&max=20&result=normal&sort=score small mistake with "sometime" instead of "sometimes" and I do not get any result. Great is to have search engine. But people are not there, they are on Reddit, stackexchange. Would this search engine offer various hyperlinks on pages like "last searches" by using GET method, then global search engines would index it better. This way I never find Emacs mailing list as one of results when I search something related to Emacs. I find other websites. ^ permalink raw reply [flat|nested] 50+ messages in thread
* RE: Understanding the "let" construct and the setting of variables 2020-12-18 18:45 ` Jean Louis @ 2020-12-18 19:16 ` Drew Adams 2020-12-18 20:00 ` Jean Louis 0 siblings, 1 reply; 50+ messages in thread From: Drew Adams @ 2020-12-18 19:16 UTC (permalink / raw) To: Jean Louis; +Cc: help-gnu-emacs > > https://lists.gnu.org/archive/html/help-gnu-emacs > > Maybe. But I have got a feeling that is unused search. What I was > meaning but did not express it that search should be exposed to > public. How is it not exposed to the public? Maybe you mean it isn't advertised as well as it could be? Feel free to advertise it. And yes, Emacs itself could advertise it by putting it in the Help menu. I think you've already filed an enhancement request for adding mailing lists to the Help menu, but if you haven't: `M-x report-emacs-bug' is the way to do that. > Great is to have search engine. But people are not there, they are on > Reddit, stackexchange. Feel free to point them from there to the mailing list and its (searchable) archive. > This way I never find Emacs mailing list as one of results when I > search something related to Emacs. I find other websites. Maybe someone else can help with that. I can't. ^ permalink raw reply [flat|nested] 50+ messages in thread
* Re: Understanding the "let" construct and the setting of variables 2020-12-18 19:16 ` Drew Adams @ 2020-12-18 20:00 ` Jean Louis 0 siblings, 0 replies; 50+ messages in thread From: Jean Louis @ 2020-12-18 20:00 UTC (permalink / raw) To: Drew Adams; +Cc: help-gnu-emacs * Drew Adams <drew.adams@oracle.com> [2020-12-18 22:19]: > > > https://lists.gnu.org/archive/html/help-gnu-emacs > > > > Maybe. But I have got a feeling that is unused search. What I was > > meaning but did not express it that search should be exposed to > > public. > > How is it not exposed to the public? > > Maybe you mean it isn't advertised as well as it could be? > Feel free to advertise it. And yes, Emacs itself could > advertise it by putting it in the Help menu. Official Emacs website points out to various other official Emacs related resources: https://www.gnu.org/software/emacs/documentation.html But who will watch the website? Just small number of actual users. Emacs is by my feeling just installed as part of GNU/Linux system by the OS package manager. From Emacs itself it is harder to find Emacs website, I do not even know how. How will users find mailing lists from within Emacs? > I think you've already filed an enhancement request for > adding mailing lists to the Help menu, but if you haven't: > `M-x report-emacs-bug' is the way to do that. Yes, who knows if it will be implemented, it requires consensus, reviews, judgments, discussions. > > Great is to have search engine. But people are not there, they are on > > Reddit, stackexchange. > > Feel free to point them from there to the mailing list > and its (searchable) archive. A curated index that points to various messages and answers some common questions is useful to be published on static pages as that would be picked up by search engines. ^ permalink raw reply [flat|nested] 50+ messages in thread
* Re: Understanding the "let" construct and the setting of variables 2020-12-18 18:12 ` Jean Louis 2020-12-18 18:20 ` Drew Adams @ 2020-12-18 21:27 ` Christopher Dimech 2020-12-19 6:23 ` Emanuel Berg via Users list for the GNU Emacs text editor 2 siblings, 0 replies; 50+ messages in thread From: Christopher Dimech @ 2020-12-18 21:27 UTC (permalink / raw) To: Jean Louis; +Cc: help-gnu-emacs > Sent: Friday, December 18, 2020 at 7:12 PM > From: "Jean Louis" <bugs@gnu.support> > To: help-gnu-emacs@gnu.org > Subject: Re: Understanding the "let" construct and the setting of variables > > * Emanuel Berg via Users list for the GNU Emacs text editor <help-gnu-emacs@gnu.org> [2020-12-18 18:43]: > > > > 3. if that isn't enough to use let/let* because several > > functions need to access a variable, use `setq' at the base > > level (i.e., first char of the line, or column 0) - not > > that Elisp has only one level, really, which is why you > > should use `setq' there to avoid confusion and errors. > > Because everyone can see what is created by `setq', this > > should be visible in the code style as well. > > > > Note that just because it would seem that two functions > > need access to the same variable, this actually doesn't > > have to be the case at all! Think it thru one extra time > > before you do it. > > Instructions like that belong on a website where they become easily > searchable for other users to understand it. > > We could index all the mailing list easily and provide search engine > for this. Right, we've got some real hot shit on this mailing list. Very good. ^ permalink raw reply [flat|nested] 50+ messages in thread
* Re: Understanding the "let" construct and the setting of variables 2020-12-18 18:12 ` Jean Louis 2020-12-18 18:20 ` Drew Adams 2020-12-18 21:27 ` Christopher Dimech @ 2020-12-19 6:23 ` Emanuel Berg via Users list for the GNU Emacs text editor 2 siblings, 0 replies; 50+ messages in thread From: Emanuel Berg via Users list for the GNU Emacs text editor @ 2020-12-19 6:23 UTC (permalink / raw) To: help-gnu-emacs Jean Louis (and I) wrote: >> 3. if that isn't enough to use let/let* because several >> functions need to access a variable, use `setq' at the >> base level (i.e., first char of the line, or column 0) - >> not that Elisp has only one level, really, which is why That should be NOTE, not "not". By that I mean a file, even a package does not have its own namespace. Everything defined is accessible from everywhere. >> you should use `setq' there to avoid confusion and >> errors. Because everyone can see what is created by >> `setq', this should be visible in the code style >> as well. By this I mean, do it like this: (defvar some-var) (setq some-var some-value) Joe Elisp Hacker then immediately thinks, "alright, a global var". And he'd be right! But do it like this: (defun some-function () (setq some-var some-value) ) it is "hm, is this a global variable? it could be, if the function was called. was it? or did the programmer forgot to put it in the let varlist? is it thus a bug? or is it defined in some other file? or [etc]" so to remove all doubt, create global vars like the first example. And do this only when let for some specific reason isn't enough. > Instructions like that belong on a website where they become > easily searchable for other users to understand it. Yeah, but to be honest ... don't everyone know that you should avoid global variables? I think that was among the first thing I learned as a programmer at age 12 or something (and I was truly a _horrible_ programmer then, and it didn't stop at 12 - but yeah, how could one be anything else at that point...). But everyone should understand it, really. It is just like putting gear in a toolbox. One box for fishing gear and one for bike repairs (yep, that'd be a big one). And nothing that has to do with fishing or bikes just lying around on the floor, for every goofball that treads it to trip on or pick up and fiddle with... > We could index all the mailing list easily and provide > search engine for this. Well, they are archived and searchable, of course! See: http://lists.gnu.org/archive/html/help-gnu-emacs/ -- underground experts united http://user.it.uu.se/~embe8573 https://dataswamp.org/~incal ^ permalink raw reply [flat|nested] 50+ messages in thread
end of thread, other threads:[~2020-12-20 5:19 UTC | newest] Thread overview: 50+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2020-12-17 0:10 Understanding the "let" construct and the setting of variables steve-humphreys 2020-12-17 0:21 ` Joost Kremers 2020-12-17 2:08 ` steve-humphreys 2020-12-17 3:12 ` steve-humphreys 2020-12-17 8:01 ` Joost Kremers 2020-12-17 8:31 ` steve-humphreys 2020-12-17 8:50 ` Joost Kremers 2020-12-17 8:10 ` Joost Kremers 2020-12-17 8:43 ` steve-humphreys 2020-12-17 8:56 ` Joost Kremers 2020-12-18 20:48 ` Emanuel Berg via Users list for the GNU Emacs text editor 2020-12-18 20:46 ` Emanuel Berg via Users list for the GNU Emacs text editor 2020-12-18 21:07 ` Jean Louis 2020-12-18 22:31 ` tomas 2020-12-18 20:39 ` Emanuel Berg via Users list for the GNU Emacs text editor 2020-12-17 2:49 ` steve-humphreys 2020-12-17 7:58 ` Joost Kremers 2020-12-17 16:55 ` Drew Adams 2020-12-17 20:11 ` steve-humphreys 2020-12-17 21:57 ` Drew Adams 2020-12-17 22:35 ` Michael Heerdegen 2020-12-18 9:01 ` tomas 2020-12-18 9:16 ` Michael Heerdegen 2020-12-18 20:55 ` Emanuel Berg via Users list for the GNU Emacs text editor 2020-12-19 2:17 ` Michael Heerdegen 2020-12-19 2:52 ` Drew Adams 2020-12-19 5:15 ` Stefan Monnier 2020-12-18 20:33 ` Emanuel Berg via Users list for the GNU Emacs text editor 2020-12-17 0:25 ` steve-humphreys 2020-12-17 0:35 ` steve-humphreys 2020-12-17 1:05 ` Joost Kremers 2020-12-17 1:20 ` steve-humphreys 2020-12-18 20:58 ` Emanuel Berg via Users list for the GNU Emacs text editor 2020-12-17 4:34 ` Jean Louis 2020-12-17 5:12 ` steve-humphreys 2020-12-19 6:06 ` Emanuel Berg via Users list for the GNU Emacs text editor 2020-12-17 7:31 ` steve-humphreys 2020-12-19 5:55 ` Emanuel Berg via Users list for the GNU Emacs text editor 2020-12-19 6:49 ` Jean Louis 2020-12-20 5:19 ` Emanuel Berg via Users list for the GNU Emacs text editor 2020-12-18 17:14 ` Emanuel Berg via Users list for the GNU Emacs text editor 2020-12-18 17:48 ` tomas 2020-12-18 15:33 ` Emanuel Berg via Users list for the GNU Emacs text editor 2020-12-18 18:12 ` Jean Louis 2020-12-18 18:20 ` Drew Adams 2020-12-18 18:45 ` Jean Louis 2020-12-18 19:16 ` Drew Adams 2020-12-18 20:00 ` Jean Louis 2020-12-18 21:27 ` Christopher Dimech 2020-12-19 6:23 ` Emanuel Berg via Users list for the GNU Emacs text editor
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).