September 20, 2018 at 2:57 pm #9495Rob DudaParticipant
I would like to get an official stance from Nexj on usage of let vs let*. I have always considered it a best practice to use let when you can and only use let* when it makes the code easier to read.
Based on some research I have also found that let allows the interpreter to bind in parallel where let* must bind sequentially. So regardless of whether Nexj Scheme binds in parallel today or not, using let allows for the optimization.
Any insight or guidance would be much appreciated.
Thanks in advance,
September 20, 2018 at 4:05 pm #9504viParticipant
>I have always considered it a best practice to use let when you can and only use let* when it makes the code easier to read.
Yes, I also recommend this.
>So regardless of whether Nexj Scheme binds in parallel today or not, using let allows for the optimization.
Currently, let compiles to a more efficient code than let*.
I prefer using define at the top of the functions, to reduce the indentation in cases where the special let and let* semantics is not needed. This is also more efficient than let*.
Finally, letrec and letrec* have the same semantics as define, i.e. one can access the other variables during initialization, as an extension of the Scheme spec.
September 21, 2018 at 11:34 am #9521Louis PaceParticipant
Vi, I’m hoping you can add some clarification to your response. Are you actually suggesting that global variables (define) are preferable to local (let, etc.)?
What would be some examples of what either of you would consider to be valid use case for let or let*? Specifically, when (in your opinion) would let* make code easier to read? I’m asking this from the point of view that let, let*, etc. should be used often, as it facilitates cleaner, more readable code.
September 25, 2018 at 1:36 pm #9531viParticipant
>Are you actually suggesting that global variables (define) are preferable to local (let, etc.)?
No, these are local, so called “internal definitions”: https://people.csail.mit.edu/jaffer/r4rs_7.html#SEC43
These are mentioned briefly in later Scheme specs, but R4RS is the last readable one, IMO.
>Specifically, when (in your opinion) would let* make code easier to read?
let* is used instead of let based on dependency between the variables, rather than readability. See
https://people.csail.mit.edu/jaffer/r4rs_6.html#SEC34: “In a let expression, the initial values are computed before any of
the variables become bound; in a let* expression, the bindings and evaluations are performed sequentially”. So, if one has
(let* ((a (+ x 1)) (b (* a 3)) …), and both a and b are used within the scope established by this let*, and b is computed
in terms of a, one must use let* instead of let, otherwise b cannot be computed in terms of the just defined a: let would
use “a” from an outer scope, e.g. global. If there is no such dependency, or the variable is used only once for the
computation of another variable, one should use let instead, i.e., for the latter case, one would write just (let ((b (* (+
x 1) 3))) …).
My approach for improving code readability is keeping the procedure code short and declaring most of the variables and local
procedures on their top with internal (local) define. let and let* can be used to move a variable declaration close to where
it is used first, but often this indicates a new “theme” in the procedure, which might deserve having a dedicated named
local procedure for it.
September 26, 2018 at 2:03 pm #9541Louis PaceParticipant
Thank you for that clarification.0
- You must be logged in to reply to this topic.