help-gnu-emacs
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: Understanding the "let" construct and the setting of variables


From: steve-humphreys
Subject: Re: Understanding the "let" construct and the setting of variables
Date: Thu, 17 Dec 2020 04:12:07 +0100

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
> > 
> >
> 
>



reply via email to

[Prev in Thread] Current Thread [Next in Thread]