<cpli>
beach, NEXT-EVENT's nested LETs are specifically { a = f; b = g a, c = h a }
<cpli>
i don't know why there even is a different macro for LET* if it makes LET entirely superfluous
rgherdt has quit [Ping timeout: 252 seconds]
marsia has quit [Ping timeout: 255 seconds]
<hayley>
LET provides "parallel" evaluation. Not as in that the values of the bound variables are produced in parallel, but that they don't observe each other.
<beach>
It doesn't make LET superfluous. You might want something like (LET ((X ...) (Y (F X))) to make X refer to an outer binding.
<beach>
cpli: But for this particular case, i.e., when the initform in a binding refers to a variable in a previous binding, LET* is the thing to use.
lagash has joined #commonlisp
<hayley>
(We only have LET and LETREC in the system I'm co-designing; the latter behaves "close enough", except for when it doesn't, of course.)
<cpli>
beach i'm sorry, it does make sense to me. but being able to occasionally shadow a symbol seems far second to being able to use the symbols that you just defined
<cpli>
the fact that X may refer to an outer binding appears to me so situational and so niche i find it ludicrous for you to bring it up at all
<splittist>
cpli: using a LET rather than a LET* also signals to the human reader of the code that you are NOT referring to variables introduced in that LET, which aids in comprehension.
frgo has quit [Ping timeout: 248 seconds]
<cpli>
when was the last time you had deliberately referred to X after a LET-clause "declaring" that symbol?
<cpli>
i.e. referring to an outer binding after assigning to the same symbol for the body of the LET
<cpli>
splittist: then does splitting { a = f; b = g a, c = h a } into two LETs instead of one LET* not make sense?
<cpli>
i.e. b and c both depend on a, but they also don't depend on another
<jackdaniel>
does it really matter if it is semantically correct and you prefer nested let (or single let*)?
<jackdaniel>
I mean - bike shedding very much thank you ,)
<jackdaniel>
something my ted talk something
<cpli>
D:< this is ultimately important! how dare you reduce my manic rambles over pragmatically equivalent code to "bike sheds"
<jackdaniel>
:)
<cpli>
the note about () not being good data though
<cpli>
do i desire NIL?
<hayley>
A list is spelled '()
<cpli>
oh
<cpli>
how does this code work
<cpli>
as in, it does
<jackdaniel>
(list #|intentionally left empty|#)
<cpli>
beautiful.
<hayley>
() and NIL read as the same object (barring infrequently asked questions-esque frobbery), and NIL evaluates to itself. So it follows () also evaluates to itself.
<cpli>
and PUSH e SOME-LIST where (EQL SOME-LIST NIL) just works?
<cpli>
i.e. it turns into (LIST e)
<semz>
it works because you push to places, not objects
<splittist>
cpli: I, personally, myself, for me, think of it this way: LET means I'm introducing some names in a scope (not using these terms with any particular precision), and LET* means I'm doing that AND ALSO IN ADDITION defining one or more of those names in terms of others. So it's a reminder to me of my intention. I don't use nested lets without intervening code, but that's just a habit, I guess. Sometimes I wonder about using one of
<splittist>
the fancy LET++s that allow for multiple values, but then that passes...
<cpli>
splittist: in my mind LET* occupies a strictly sequential space
<beach>
cpli: I agree with splittist.
<beach>
LET signals to the reader that the variables introduced are not part of the any of the forms.
<cpli>
i.e. i can replace this and only this with something less mind-numbing (LET ((A (F))) (LET ((B (G A))) (LET ((C (H B))) ; ...
<beach>
cpli: You should use LET* for sequentially dependent bindings.
<cpli>
i.e. discrete. it seems strange to me that when LET is taught as "simultaneous" bindings that one would cast away the direct structure in favor of 2 spaces of indentation
<beach>
Indentation is not the argument. It is the argument that splittist gave, and that I repeated.
<cpli>
say we had some PREPARE-THING and then tons of fields of THING we want in scope
bitblit1 has quit [Ping timeout: 240 seconds]
Duuqnd has quit [Ping timeout: 240 seconds]
dieggsy has quit [Ping timeout: 240 seconds]
paulapatience has quit [Ping timeout: 240 seconds]
edgarvincent[m] has quit [Ping timeout: 252 seconds]
AadVersteden[m] has quit [Ping timeout: 246 seconds]
artemon has quit [Ping timeout: 246 seconds]
infra_red[m] has quit [Ping timeout: 246 seconds]
hayley has quit [Ping timeout: 246 seconds]
BrownJenkin has quit [Ping timeout: 248 seconds]
Gnuxie has quit [Ping timeout: 248 seconds]
nicm[m] has quit [Ping timeout: 246 seconds]
Mrtn[m] has quit [Ping timeout: 246 seconds]
gridbugsmasher42 has quit [Ping timeout: 264 seconds]
kakuhen has quit [Ping timeout: 264 seconds]
roygbyte[m] has quit [Ping timeout: 265 seconds]
loke[m] has quit [Ping timeout: 265 seconds]
char[m] has quit [Ping timeout: 265 seconds]
VOID[m] has quit [Ping timeout: 265 seconds]
alanz has quit [Ping timeout: 260 seconds]
yitzi has quit [Ping timeout: 260 seconds]
emacsomancer[m] has quit [Ping timeout: 256 seconds]
bitspook[m] has quit [Ping timeout: 256 seconds]
<beach>
Do you mean that THING is an instance with slots in it?
<beach>
Then you use WITH-SLOTS (or even better) WITH-ACCESSORS.
<cpli>
oh sure
<cpli>
assume it's some cffi (as it is in my case)
<beach>
I never use FFI, so that's hard for me to assume.
<cpli>
as in, they're all GFs
<cpli>
in my opinion: (LET* ((THING (PREPARE-THING)) (FIELDA (GET-FIELDA THING)) (FIELDB (GET-FIELDB THING)) ;.. omitted
<beach>
For that case, it depends on how many "fields" you have, so either (let ((thing ...)) (let* ((fielda ...) (fieldb ...)) ...)...), or a big LET* if you have few "fields".
<cpli>
casts away the direct dependency all notion of dependency of FIELDA, FIELDB, .. to THING
<beach>
cpli: It is not about opinions. It is about conventions.
<beach>
But I think I have pretty much exhausted the conventions and their reasons to exist.
<cpli>
beach exactly not LET* in the former case. FIELDA, FIELDB, etc all depend only on THING
<cpli>
I don't think I'm opposing any convention, I ask two questions:
<cpli>
if people don't care about expressing the relationships between bindings in LET*, then why have LET
nicm[m] has joined #commonlisp
bitblit1 has joined #commonlisp
gridbugsmasher42 has joined #commonlisp
<cpli>
and if people do, then why use LET* anywhere other than the strictly sequential case
edgarvincent[m] has joined #commonlisp
Mrtn[m] has joined #commonlisp
artemon has joined #commonlisp
kakuhen has joined #commonlisp
frgo has joined #commonlisp
AadVersteden[m] has joined #commonlisp
dieggsy has joined #commonlisp
edwlan[m] has joined #commonlisp
bitspook[m] has joined #commonlisp
Gnuxie has joined #commonlisp
yitzi has joined #commonlisp
char[m] has joined #commonlisp
loke[m] has joined #commonlisp
Duuqnd has joined #commonlisp
roygbyte[m] has joined #commonlisp
infra_red[m] has joined #commonlisp
VOID[m] has joined #commonlisp
paulapatience has joined #commonlisp
hayley has joined #commonlisp
BrownJenkin has joined #commonlisp
<splittist>
A little bit of sequential processing in a LET* is OK. If it gets too long, a macro might make the intention clearer, eg. something like ~> for purely sequential processing or a special destructuring macro if that's what you're doing (or not bother destructuring)
<jackdaniel>
cpli: (let ((x1 (round x1)) (x2 (round x2)) (real-dist (round (- x2 x1))) ...) has quite a different meaning from when you use let*
<jackdaniel>
skip the round call around the (- x2 x1)
<cpli>
jackdaniel: this is an alright example of one of my former asks, ture
<cpli>
*true
<beach>
cpli: People do care which is why LET exists, and LET* is used pretty much only in the sequential case. I think that's what I have been saying.
<beach>
cpli: The default is LET when it works, for the reason that splittist said. It signals to the person reading the code that there are no dependencies between the bindings, so the person does not have to verify that.
neon has quit [Ping timeout: 260 seconds]
<jackdaniel>
cpli: just use your aesthetics sense to decide what looks better - I think that there are more interesting dillemas when writing programs ;p /me gets back to more interesting dillemas
tyson2 has quit [Remote host closed the connection]
<beach>
Different question: Say we have (let* ((x ...) (y ...)) (declare ... x)...) and suppose the initialization form for y references x. Does the scope of the declaration include the initialization form for y? And if so, where in the standard does it say that?