* Closures - do you understand them well? @ 2022-12-08 15:36 Michael Heerdegen 2022-12-08 16:24 ` [External] : " Drew Adams ` (2 more replies) 0 siblings, 3 replies; 86+ messages in thread From: Michael Heerdegen @ 2022-12-08 15:36 UTC (permalink / raw) To: Emacs mailing list Hi, Maybe you will have fun with this new exercise: What is the return value of the following expression, and what's your reasoning? Answer without asking Emacs: #+begin_src emacs-lisp ;; -*- lexical-binding: t -*- (let ((i 0) (funs '())) (while (< (setq i (1+ i)) 4) (push (lambda () i) funs)) (apply #'+ (mapcar #'funcall funs))) #+end_src Please no "you better write this as ... and then it returns ..." answers: I mean this code and what it returns. Have fun! Michael. ^ permalink raw reply [flat|nested] 86+ messages in thread
* RE: [External] : Closures - do you understand them well? 2022-12-08 15:36 Closures - do you understand them well? Michael Heerdegen @ 2022-12-08 16:24 ` Drew Adams 2022-12-08 17:30 ` Michael Heerdegen 2022-12-08 19:06 ` Tassilo Horn 2022-12-08 19:44 ` Eric Abrahamsen 2 siblings, 1 reply; 86+ messages in thread From: Drew Adams @ 2022-12-08 16:24 UTC (permalink / raw) To: Michael Heerdegen, Emacs mailing list Just a mention for others, that '() == (). No need to quote t or nil (including its alter ego ()). ^ permalink raw reply [flat|nested] 86+ messages in thread
* Re: [External] : Closures - do you understand them well? 2022-12-08 16:24 ` [External] : " Drew Adams @ 2022-12-08 17:30 ` Michael Heerdegen 2022-12-08 17:56 ` Drew Adams 0 siblings, 1 reply; 86+ messages in thread From: Michael Heerdegen @ 2022-12-08 17:30 UTC (permalink / raw) To: help-gnu-emacs Drew Adams <drew.adams@oracle.com> writes: > Just a mention for others, that '() == (). > No need to quote t or nil (including its > alter ego ()). You are lucky that your remark doesn't fulfill the "you better write this as ... and then it returns ..." answer property because it doesn't change the return value ;-) But yes, like explicitly specifying a nil binding (X nil) instead of (X) this is bout readability and personal preferences. (X '()) is my hint to the reader that X will be used as a list type accumulator in the BODY. I prefer that over (X ()), (X nil) and (X). It's a stylistic habit. Why? Because I want to make clear that the variable is initialized with an empty list, compared to what the evaluation of an empty list aka nil returns (which accidentally happens to be the same again in Lisp). Thanks for mentioning this point Drew, Michael. ^ permalink raw reply [flat|nested] 86+ messages in thread
* RE: [External] : Closures - do you understand them well? 2022-12-08 17:30 ` Michael Heerdegen @ 2022-12-08 17:56 ` Drew Adams 2022-12-08 18:00 ` Drew Adams 2022-12-08 18:49 ` Michael Heerdegen 0 siblings, 2 replies; 86+ messages in thread From: Drew Adams @ 2022-12-08 17:56 UTC (permalink / raw) To: Michael Heerdegen, help-gnu-emacs@gnu.org > But yes, like explicitly specifying a nil binding (X nil) instead of (X) > this is bout readability and personal preferences. (X '()) is my > hint to the reader that X will be used as a list type accumulator in the > BODY. I prefer that over (X ()), (X nil) and (X). It's a stylistic > habit. > > Why? Because I want to make clear that the variable is initialized with > an empty list, compared to what the evaluation of an empty list aka nil > returns (which accidentally happens to be the same again in Lisp). I have _exactly_ the same concern as you: human-reader readability (and in most cases that's me). I use (let ((xs ()) (foop nil) (bar nil) (yy)) to tell me that: 1. xs and foop are bound initially. yy gets its meaningful value only from the `let' body - its initial nil value is (should be) meaningless/ignored. 2. xs has a list value (at least initially). IOW, I use () for the same reason you use '(). 3. foop and bar have non-(non-nil) values (at least initially). 4. foop is used as a Boolean (true/false). bar is likely not used just as a Boolean. (bar might have several possible values, where nil might mean some base case, which could, but need not, mean false. Wrt #4: I use the suffix code convention "p"/"-p" for variable names, as well as for function names. I find this _very_ helpful. Throughout the body, I'm reminded that foop is Boolean. ___ You say, "which accidentally happens to be the same again in Lisp". To me it's not an accident; it's by design. It's arguable, and it's been argued, but to me this design is (1) clever/elegant and (2) _very_ handy. Is #1 important? Maybe not, but to me it's lovely. ^ permalink raw reply [flat|nested] 86+ messages in thread
* RE: [External] : Closures - do you understand them well? 2022-12-08 17:56 ` Drew Adams @ 2022-12-08 18:00 ` Drew Adams 2022-12-08 18:49 ` Michael Heerdegen 1 sibling, 0 replies; 86+ messages in thread From: Drew Adams @ 2022-12-08 18:00 UTC (permalink / raw) To: Michael Heerdegen, help-gnu-emacs@gnu.org Typo - forgot to mention bar here: > I use (let ((xs ()) > (foop nil) > (bar nil) > (yy)) > to tell me that: > > 1. xs and foop are bound initially. ^^^^ and bar > yy gets its meaningful value only from > the `let' body - its initial nil value > is (should be) meaningless/ignored. ^ permalink raw reply [flat|nested] 86+ messages in thread
* Re: [External] : Closures - do you understand them well? 2022-12-08 17:56 ` Drew Adams 2022-12-08 18:00 ` Drew Adams @ 2022-12-08 18:49 ` Michael Heerdegen 2022-12-08 19:35 ` Drew Adams 2022-12-08 19:45 ` Drew Adams 1 sibling, 2 replies; 86+ messages in thread From: Michael Heerdegen @ 2022-12-08 18:49 UTC (permalink / raw) To: help-gnu-emacs Drew Adams <drew.adams@oracle.com> writes: > You say, "which accidentally happens to be > the same again in Lisp". To me it's not an > accident; it's by design. Sure it's by design, and it's convenient. But for readability purposes that doesn't matter that much. When the reader encounters "()" I expect it to construct an empty list. That's what I want, so I quote it to get exactly that when that expression is evaluated. If we do not limit ourselves to Emacs Lisp, the (not trivial) question would else be: what is the return value when evaluating an empty list? Not trivial because there can be Lisps where an empty list and a boolean "false" are different (AFAIR such Lisps exist). So the result of evaluating an empty list could be: - an empty list/ the same empty list (self-evaluating) - undefined - a Boolean value false - ...maybe something else? Because I don't want to tangent this question I prefer to quote the empty list. What are your reasons to prefer to evaluate it and use the result? Michael. ^ permalink raw reply [flat|nested] 86+ messages in thread
* RE: [External] : Closures - do you understand them well? 2022-12-08 18:49 ` Michael Heerdegen @ 2022-12-08 19:35 ` Drew Adams 2022-12-10 4:51 ` Emanuel Berg 2022-12-08 19:45 ` Drew Adams 1 sibling, 1 reply; 86+ messages in thread From: Drew Adams @ 2022-12-08 19:35 UTC (permalink / raw) To: Michael Heerdegen, help-gnu-emacs@gnu.org > When the reader encounters "()" I expect it to construct an empty list. > That's what I want, so I quote it to get exactly that when that > expression is evaluated. > > If we do not limit ourselves to Emacs Lisp, the (not trivial) question > would else be: what is the return value when evaluating an empty list? > Not trivial because there can be Lisps where an empty list and a boolean > "false" are different (AFAIR such Lisps exist). Scheme. As CLTL2 says at the outset: https://www.cs.cmu.edu/Groups/AI/html/cltl/clm/node9.html#SECTION00522000000000000000 In Common Lisp, as in most Lisp dialects, the symbol ^^^^^^^^^^^^^^^^^^^^^^^^ nil is used to represent both the empty list and the ``false'' value for Boolean tests. An empty list may, of course, also be written (); this normally denotes the same object as nil.... These two notations may be used interchangeably as far as the Lisp system is concerned. However, as a matter of style, this book uses the notation () when it is desirable to emphasize the use of an empty list, and uses the notation nil when it is desirable to emphasize the use of the Boolean ``false''. The notation 'nil (note the explicit quotation mark) is used to emphasize the use of a symbol. For example: (defun three () 3) ;Emphasize empty parameter list (append '() '()) => () ;Emphasize use of empty lists (not nil) => t ;Emphasize use as Boolean ``false'' (get 'nil 'color) ;Emphasize use as a symbol Any data object other than nil is construed to be Boolean ``not false'', that is, ``true''. The symbol t is conventionally used to mean ``true'' when no other value is more appropriate. When a function is said to ``return false'' or to ``be false'' in some circumstance, this means that it returns nil. However, when a function is said to ``return true'' or to ``be true'' in some circumstance, this means that it returns some value other than nil, but not necessarily t. (Note that the second example does what you do. (Of course at this point in the book there's been no mention of t and nil/() being self-evaluating.) https://www.cs.cmu.edu/Groups/AI/html/cltl/clm/node57.html#SECTION00911000000000000000 > Because I don't want to tangent this question I prefer > to quote the empty list. What are your reasons to > prefer to evaluate it and use the result? No reason not to do that, i.e., no reason to quote it. Why not emphasize and take advantage of the fact that (always) '() = ()? No more reason to quote it than there is (in Elisp, unlike in Common Lisp) to quote a lambda expression (not speaking about #' "quoting" here). ^ permalink raw reply [flat|nested] 86+ messages in thread
* Re: [External] : Closures - do you understand them well? 2022-12-08 19:35 ` Drew Adams @ 2022-12-10 4:51 ` Emanuel Berg 0 siblings, 0 replies; 86+ messages in thread From: Emanuel Berg @ 2022-12-10 4:51 UTC (permalink / raw) To: help-gnu-emacs Drew Adams wrote: >> What are your reasons to prefer to evaluate it and use >> the result? > > No reason not to do that, i.e., no reason to quote it. > > Why not emphasize and take advantage of the fact that > (always) '() = ()? No more reason to quote it than there is > (in Elisp, unlike in Common Lisp) to quote a lambda > expression (not speaking about #' "quoting" here). I think we need a special syntax to denote list quoting ... -- underground experts united https://dataswamp.org/~incal ^ permalink raw reply [flat|nested] 86+ messages in thread
* RE: [External] : Closures - do you understand them well? 2022-12-08 18:49 ` Michael Heerdegen 2022-12-08 19:35 ` Drew Adams @ 2022-12-08 19:45 ` Drew Adams 1 sibling, 0 replies; 86+ messages in thread From: Drew Adams @ 2022-12-08 19:45 UTC (permalink / raw) To: Michael Heerdegen, help-gnu-emacs@gnu.org I probably should have also cited these Elisp messages about nil: https://www.gnu.org/software/emacs/manual/html_node/eintr/nil-explained.html https://www.gnu.org/software/emacs/manual/html_node/elisp/nil-and-t.html ^ permalink raw reply [flat|nested] 86+ messages in thread
* Re: Closures - do you understand them well? 2022-12-08 15:36 Closures - do you understand them well? Michael Heerdegen 2022-12-08 16:24 ` [External] : " Drew Adams @ 2022-12-08 19:06 ` Tassilo Horn 2022-12-08 19:53 ` Michael Heerdegen 2022-12-08 19:44 ` Eric Abrahamsen 2 siblings, 1 reply; 86+ messages in thread From: Tassilo Horn @ 2022-12-08 19:06 UTC (permalink / raw) To: Michael Heerdegen; +Cc: help-gnu-emacs Michael Heerdegen <michael_heerdegen@web.de> writes: > What is the return value of the following expression, and what's your > reasoning? Answer without asking Emacs: Obviously 6. > #+begin_src emacs-lisp > ;; -*- lexical-binding: t -*- > > (let ((i 0) > (funs '())) > (while (< (setq i (1+ i)) > 4) > (push (lambda () i) > funs)) > (apply #'+ (mapcar #'funcall funs))) > #+end_src Shocking!!! Common Lisp agrees: --8<---------------cut here---------------start------------->8--- (let ((funs '())) (loop for i from 1 to 3 do (push (lambda () i) funs)) (apply #'+ (mapcar #'funcall funs))) ;=> 12 --8<---------------cut here---------------end--------------->8--- So I guess the reason is that the `i' is not an integer but a place where the integers 1, 2, and 3? Well, at least rust gets this right: --8<---------------cut here---------------start------------->8--- fn main() { let mut funs = vec![]; let mut i: i32 = 1; while i < 4 { funs.push(move || i); i += 1; } let result: i32 = funs.iter().map(|f| f()).sum(); println!("Result = {}", result); // 6, that's right! } --8<---------------cut here---------------end--------------->8--- Bye, Tassilo ^ permalink raw reply [flat|nested] 86+ messages in thread
* Re: Closures - do you understand them well? 2022-12-08 19:06 ` Tassilo Horn @ 2022-12-08 19:53 ` Michael Heerdegen 2022-12-08 20:01 ` Stefan Monnier via Users list for the GNU Emacs text editor 0 siblings, 1 reply; 86+ messages in thread From: Michael Heerdegen @ 2022-12-08 19:53 UTC (permalink / raw) To: help-gnu-emacs Tassilo Horn <tsdh@gnu.org> writes: > Shocking!!! The example is written in a way to suggest a wrong result. But don't we all rely on the behavior demonstrated from time to time? The implementation of `letrec' for example: (macroexpand-1 '(letrec ((f (lambda () f))))) ==> (let (f) (setq f (lambda nil f))) We expect that the value of F in the closure bound to F references the closure itself, not the initial value. > Common Lisp agrees: > > (let ((funs '())) > (loop for i from 1 to 3 > do (push (lambda () i) funs)) > (apply #'+ (mapcar #'funcall funs))) > ;=> 12 I guess this depends a bit on the implementation of `loop'. But I think the result is expected, yes. Don't you remember what you learned about shared environments that different places in the code have access to (including the ability to modify)? > So I guess the reason is that the `i' is not an integer but a place > where the integers 1, 2, and 3? It's a free variable in all the lambdas, and it refers to the binding in the same environment. When the `apply' call is made the binding in that environment is the one from the moment when it was last changed in the loop, and that is `4`. That's all. Michael. ^ permalink raw reply [flat|nested] 86+ messages in thread
* Re: Closures - do you understand them well? 2022-12-08 19:53 ` Michael Heerdegen @ 2022-12-08 20:01 ` Stefan Monnier via Users list for the GNU Emacs text editor 2022-12-08 20:49 ` Michael Heerdegen 0 siblings, 1 reply; 86+ messages in thread From: Stefan Monnier via Users list for the GNU Emacs text editor @ 2022-12-08 20:01 UTC (permalink / raw) To: help-gnu-emacs >> (let ((funs '())) >> (loop for i from 1 to 3 >> do (push (lambda () i) funs)) >> (apply #'+ (mapcar #'funcall funs))) >> ;=> 12 > > I guess this depends a bit on the implementation of `loop'. I haven't checked but for the similar code using `dolist` or `dotimes` Common Lisp indeed leaves it unspecified ig the same `i` binding is used through the loop or if a different binding is used at each iteration. In ELisp, both `dotimes` and `dolist` create a new binding for `i` at each iteration of the loop. Stefan ^ permalink raw reply [flat|nested] 86+ messages in thread
* Re: Closures - do you understand them well? 2022-12-08 20:01 ` Stefan Monnier via Users list for the GNU Emacs text editor @ 2022-12-08 20:49 ` Michael Heerdegen 2022-12-08 22:00 ` Stefan Monnier via Users list for the GNU Emacs text editor 2022-12-09 3:43 ` Emanuel Berg 0 siblings, 2 replies; 86+ messages in thread From: Michael Heerdegen @ 2022-12-08 20:49 UTC (permalink / raw) To: help-gnu-emacs Stefan Monnier via Users list for the GNU Emacs text editor <help-gnu-emacs@gnu.org> writes: > In ELisp, both `dotimes` and `dolist` create a new binding for `i` at > each iteration of the loop. This is probably what most people expect from a loop. `cl-loop' doesn't. I guess it's not good to rely on either behavior of built-in looping constructs. Michael. ^ permalink raw reply [flat|nested] 86+ messages in thread
* Re: Closures - do you understand them well? 2022-12-08 20:49 ` Michael Heerdegen @ 2022-12-08 22:00 ` Stefan Monnier via Users list for the GNU Emacs text editor 2022-12-08 22:25 ` [External] : " Drew Adams ` (2 more replies) 2022-12-09 3:43 ` Emanuel Berg 1 sibling, 3 replies; 86+ messages in thread From: Stefan Monnier via Users list for the GNU Emacs text editor @ 2022-12-08 22:00 UTC (permalink / raw) To: help-gnu-emacs >> In ELisp, both `dotimes` and `dolist` create a new binding for `i` at >> each iteration of the loop. > This is probably what most people expect from a loop. I find this behavior cleaner, indeed (which is why I changed `dotimes` and `dolist` to provide that behavior :-). > `cl-loop' doesn't. Indeed, when I looked at it, I decided it was too much trouble figuring out how to change `cl-loop` to provide that behavior :-( IMO `cl-loop` is too complex for its own good. Stefan ^ permalink raw reply [flat|nested] 86+ messages in thread
* RE: [External] : Re: Closures - do you understand them well? 2022-12-08 22:00 ` Stefan Monnier via Users list for the GNU Emacs text editor @ 2022-12-08 22:25 ` Drew Adams 2022-12-08 22:51 ` Stefan Monnier via Users list for the GNU Emacs text editor ` (2 more replies) 2022-12-09 4:49 ` tomas 2022-12-10 2:26 ` Emanuel Berg 2 siblings, 3 replies; 86+ messages in thread From: Drew Adams @ 2022-12-08 22:25 UTC (permalink / raw) To: Stefan Monnier; +Cc: 'Help-Gnu-Emacs (help-gnu-emacs@gnu.org)' [-- Attachment #1: Type: text/plain, Size: 338 bytes --] > IMO `cl-loop` is too complex for its own good. Maybe ... "Don't Loop, Iterate"? https://iterate.common-lisp.dev/doc/index.html (Dunno what binding it uses in this context.) ___ https://iterate.common-lisp.dev/doc/Don_0027t-Loop-Iterate.html#Don_0027t-Loop-Iterate https://dspace.mit.edu/handle/1721.1/41498?show=full [-- Attachment #2: winmail.dat --] [-- Type: application/ms-tnef, Size: 13481 bytes --] ^ permalink raw reply [flat|nested] 86+ messages in thread
* Re: [External] : Re: Closures - do you understand them well? 2022-12-08 22:25 ` [External] : " Drew Adams @ 2022-12-08 22:51 ` Stefan Monnier via Users list for the GNU Emacs text editor 2022-12-10 2:34 ` Emanuel Berg 2022-12-09 5:03 ` Tomas Hlavaty 2022-12-10 2:29 ` Emanuel Berg 2 siblings, 1 reply; 86+ messages in thread From: Stefan Monnier via Users list for the GNU Emacs text editor @ 2022-12-08 22:51 UTC (permalink / raw) To: help-gnu-emacs >> IMO `cl-loop` is too complex for its own good. > Maybe ... "Don't Loop, Iterate"? > https://iterate.common-lisp.dev/doc/index.html IMO it's still "too complex for its own good". > (Dunno what binding it uses in this context.) `iterate` explicitly defines those vars to use a single binding over the whole iteration (I suspect the same holds for `loop` as well, actually). IOW it's very fundamentally "imperative", where iteration variables are defined to be "uninitialized" at the beginning at are updated by side-effect during the course of the iteration. [ I tend to cringe at the idea of uninitialized variables. ] Stefan ^ permalink raw reply [flat|nested] 86+ messages in thread
* Re: [External] : Re: Closures - do you understand them well? 2022-12-08 22:51 ` Stefan Monnier via Users list for the GNU Emacs text editor @ 2022-12-10 2:34 ` Emanuel Berg 0 siblings, 0 replies; 86+ messages in thread From: Emanuel Berg @ 2022-12-10 2:34 UTC (permalink / raw) To: help-gnu-emacs Stefan Monnier via Users list for the GNU Emacs text editor wrote: > `iterate` explicitly defines those vars to use a single > binding over the whole iteration (I suspect the same holds > for `loop` as well, actually). IOW it's very fundamentally > "imperative", where iteration variables are defined to be > "uninitialized" at the beginning at are updated by > side-effect during the course of the iteration. [ I tend to > cringe at the idea of uninitialized variables. ] Iteration meaning a for loop is imperative, a traversal of a data structure is pretty functional IMO ... set, aggregate, map, higher-order ... -- underground experts united https://dataswamp.org/~incal ^ permalink raw reply [flat|nested] 86+ messages in thread
* RE: [External] : Re: Closures - do you understand them well? 2022-12-08 22:25 ` [External] : " Drew Adams 2022-12-08 22:51 ` Stefan Monnier via Users list for the GNU Emacs text editor @ 2022-12-09 5:03 ` Tomas Hlavaty 2022-12-10 2:35 ` Emanuel Berg 2022-12-10 2:29 ` Emanuel Berg 2 siblings, 1 reply; 86+ messages in thread From: Tomas Hlavaty @ 2022-12-09 5:03 UTC (permalink / raw) To: Drew Adams, Stefan Monnier Cc: 'Help-Gnu-Emacs (help-gnu-emacs@gnu.org)' On Thu 08 Dec 2022 at 22:25, Drew Adams <drew.adams@oracle.com> wrote: > Maybe ... "Don't Loop, Iterate"? > > https://iterate.common-lisp.dev/doc/index.html iterate is very bad idea i wish people would not depend on it and used the simplest form to do the job instead ^ permalink raw reply [flat|nested] 86+ messages in thread
* Re: [External] : Re: Closures - do you understand them well? 2022-12-09 5:03 ` Tomas Hlavaty @ 2022-12-10 2:35 ` Emanuel Berg 0 siblings, 0 replies; 86+ messages in thread From: Emanuel Berg @ 2022-12-10 2:35 UTC (permalink / raw) To: help-gnu-emacs Tomas Hlavaty wrote: >> Maybe ... "Don't Loop, Iterate"? [...] > > iterate is very bad idea > i wish people would not depend on it > and used the simplest form to do the job instead Donatello King of Salsa, what are you talking about? -- underground experts united https://dataswamp.org/~incal ^ permalink raw reply [flat|nested] 86+ messages in thread
* Re: [External] : Re: Closures - do you understand them well? 2022-12-08 22:25 ` [External] : " Drew Adams 2022-12-08 22:51 ` Stefan Monnier via Users list for the GNU Emacs text editor 2022-12-09 5:03 ` Tomas Hlavaty @ 2022-12-10 2:29 ` Emanuel Berg 2022-12-10 16:56 ` Drew Adams 2 siblings, 1 reply; 86+ messages in thread From: Emanuel Berg @ 2022-12-10 2:29 UTC (permalink / raw) To: help-gnu-emacs Drew Adams wrote: >> IMO `cl-loop` is too complex for its own good. > > Maybe ... "Don't Loop, Iterate"? What does that saying say? Traversal of data structures? If so, `cl-loop' can do that ... in many ways :) -- underground experts united https://dataswamp.org/~incal ^ permalink raw reply [flat|nested] 86+ messages in thread
* RE: [External] : Re: Closures - do you understand them well? 2022-12-10 2:29 ` Emanuel Berg @ 2022-12-10 16:56 ` Drew Adams 2022-12-15 8:25 ` Emanuel Berg 0 siblings, 1 reply; 86+ messages in thread From: Drew Adams @ 2022-12-10 16:56 UTC (permalink / raw) To: Emanuel Berg, help-gnu-emacs@gnu.org > > "Don't Loop, Iterate" > > What does that saying say? Just a pun: 1. "loop" and "iterate" are synonyms. 2. Common Lisp `loop' and the writer's macro `iterate' are different (but similar). The author of macro `iterate' is saying, with that title, that macro `iterate' is preferable to `loop'. The point of his paper is to say how/why he thinks that's the case. ^ permalink raw reply [flat|nested] 86+ messages in thread
* Re: [External] : Re: Closures - do you understand them well? 2022-12-10 16:56 ` Drew Adams @ 2022-12-15 8:25 ` Emanuel Berg 0 siblings, 0 replies; 86+ messages in thread From: Emanuel Berg @ 2022-12-15 8:25 UTC (permalink / raw) To: help-gnu-emacs Drew Adams wrote: >>> "Don't Loop, Iterate" >> >> What does that saying say? > > Just a pun: > > 1. "loop" and "iterate" are synonyms. No, loop is in general, iterate is a special case of loops, namely the incremental (e.g. a for loop) and/or thru a data-structure (`dolist') ... (while t (sleep-for 1)) is a loop but it doesn't iterate. Or maybe I just got it all wrong at age 12 reading "Learn C++ in 21 Days" so thank you for correcting me if so ... (to be honest that sounds logical 'cuz I still don't know C++) -- underground experts united https://dataswamp.org/~incal ^ permalink raw reply [flat|nested] 86+ messages in thread
* Re: Closures - do you understand them well? 2022-12-08 22:00 ` Stefan Monnier via Users list for the GNU Emacs text editor 2022-12-08 22:25 ` [External] : " Drew Adams @ 2022-12-09 4:49 ` tomas 2022-12-09 19:40 ` Michael Heerdegen 2022-12-10 2:26 ` Emanuel Berg 2 siblings, 1 reply; 86+ messages in thread From: tomas @ 2022-12-09 4:49 UTC (permalink / raw) To: help-gnu-emacs [-- Attachment #1: Type: text/plain, Size: 1328 bytes --] On Thu, Dec 08, 2022 at 05:00:14PM -0500, Stefan Monnier via Users list for the GNU Emacs text editor wrote: > >> In ELisp, both `dotimes` and `dolist` create a new binding for `i` at > >> each iteration of the loop. > > This is probably what most people expect from a loop. > > I find this behavior cleaner, indeed (which is why I changed `dotimes` > and `dolist` to provide that behavior :-). This is funny. I did come up with the right answer. Truth be said, Michael's "tone" was set up in a way to raise awareness ("now, look carefully"), so this has surely played a role. That said, this is actually the behaviour I expect (and like), so reading your note taught me something: expectations here seem to vary, and mine isn't the "only", much less the "right" one. And I might meet loop constructs with local bindings :) So I learnt something from the riddle, after all [1]. > > `cl-loop' doesn't. > > Indeed, when I looked at it, I decided it was too much trouble figuring > out how to change `cl-loop` to provide that behavior :-( > IMO `cl-loop` is too complex for its own good. Uh-huh. I never wanted to learn a whole language to just do looping :-) Thanks for the riddle and all the follow-up! [1] The most general rule seems still to be: "all generalisations suck" -- t [-- Attachment #2: signature.asc --] [-- Type: application/pgp-signature, Size: 195 bytes --] ^ permalink raw reply [flat|nested] 86+ messages in thread
* Re: Closures - do you understand them well? 2022-12-09 4:49 ` tomas @ 2022-12-09 19:40 ` Michael Heerdegen 2022-12-09 19:50 ` tomas ` (2 more replies) 0 siblings, 3 replies; 86+ messages in thread From: Michael Heerdegen @ 2022-12-09 19:40 UTC (permalink / raw) To: help-gnu-emacs <tomas@tuxteam.de> writes: > So I learnt something from the riddle, after all [1]. Cool that there was something to learn for some people. The second part of the exercise is now of course (this goes to everyone): how to "fix" the code so that what some people expected is the end result?...: Write an expression that returns a list of 100 functions accepting zero arguments. `funcall'ing the Nth function must return N. Use a `while' loop or whatever you like but please not `dolist' or any tool that already handles this "problem" specifically. > [1] The most general rule seems still to be: "all generalisations > suck" I think this is the first instance of Russell's paradox I have ever met in real life. Michael. ^ permalink raw reply [flat|nested] 86+ messages in thread
* Re: Closures - do you understand them well? 2022-12-09 19:40 ` Michael Heerdegen @ 2022-12-09 19:50 ` tomas 2022-12-09 20:55 ` Tassilo Horn 2022-12-10 0:12 ` Michael Heerdegen 2 siblings, 0 replies; 86+ messages in thread From: tomas @ 2022-12-09 19:50 UTC (permalink / raw) To: help-gnu-emacs [-- Attachment #1: Type: text/plain, Size: 1097 bytes --] On Fri, Dec 09, 2022 at 08:40:50PM +0100, Michael Heerdegen wrote: > <tomas@tuxteam.de> writes: > > > So I learnt something from the riddle, after all [1]. > > Cool that there was something to learn for some people. It was enjoyable, yes :) > The second part of the exercise is now of course (this goes to > everyone): how to "fix" the code so that what some people expected is > the end result?...: > > Write an expression that returns a list of 100 functions accepting zero > arguments. `funcall'ing the Nth function must return N. Use a `while' > loop or whatever you like but please not `dolist' or any tool that > already handles this "problem" specifically. Hm. I imagine in the middle of my code "fred's function factory", like so: (defun fred-s-function-factory (n) ...) (i won't tell more now ;) > > [1] The most general rule seems still to be: "all generalisations > > suck" > > I think this is the first instance of Russell's paradox I have ever met > in real life. Then I would like you to meet my barber... Cheers -- t [-- Attachment #2: signature.asc --] [-- Type: application/pgp-signature, Size: 195 bytes --] ^ permalink raw reply [flat|nested] 86+ messages in thread
* Re: Closures - do you understand them well? 2022-12-09 19:40 ` Michael Heerdegen 2022-12-09 19:50 ` tomas @ 2022-12-09 20:55 ` Tassilo Horn 2022-12-09 21:21 ` Michael Heerdegen ` (2 more replies) 2022-12-10 0:12 ` Michael Heerdegen 2 siblings, 3 replies; 86+ messages in thread From: Tassilo Horn @ 2022-12-09 20:55 UTC (permalink / raw) To: Michael Heerdegen; +Cc: help-gnu-emacs Michael Heerdegen <michael_heerdegen@web.de> writes: > everyone): how to "fix" the code so that what some people expected is > the end result?...: > > Write an expression that returns a list of 100 functions accepting zero > arguments. `funcall'ing the Nth function must return N. Use a `while' > loop or whatever you like but please not `dolist' or any tool that > already handles this "problem" specifically. This time I'm prepared and have three versions making a new binding. Take this, Michael! :-) --8<---------------cut here---------------start------------->8--- (let ((i 0) (m (lambda (i) (lambda () i))) funs) (while (< i 100) (push (funcall m i) funs) (cl-incf i)) (mapcar #'funcall funs)) (let ((i 0) funs) (while (< i 100) (let ((j i)) (push (lambda () j) funs)) (cl-incf i)) (mapcar #'funcall funs)) (let ((i 0) funs) (while (< i 100) (push `(lambda () ,i) funs) (cl-incf i)) (mapcar #'funcall funs)) --8<---------------cut here---------------end--------------->8--- Oh, I forgot to `nreverse` funs so my Nth function returns 99-N instead. Good enough... Bye, Tassilo ^ permalink raw reply [flat|nested] 86+ messages in thread
* Re: Closures - do you understand them well? 2022-12-09 20:55 ` Tassilo Horn @ 2022-12-09 21:21 ` Michael Heerdegen 2022-12-09 21:31 ` Emanuel Berg 2022-12-09 21:23 ` Emanuel Berg 2022-12-10 4:46 ` Emanuel Berg 2 siblings, 1 reply; 86+ messages in thread From: Michael Heerdegen @ 2022-12-09 21:21 UTC (permalink / raw) To: help-gnu-emacs Tassilo Horn <tsdh@gnu.org> writes: > This time I'm prepared and have three versions making a new binding. > Take this, Michael! :-) Wow - ok, let's see... > (let ((i 0) > (m (lambda (i) > (lambda () i))) > funs) > (while (< i 100) > (push (funcall m i) funs) > (cl-incf i)) > (mapcar #'funcall funs)) Yes, I think one can do this (the argument variable i shadows the variable of the same in the `let', but it also exists to conserve the value from the outside i so one can argue that it's ok to use the same name - it's semantically not incorrect anyway). Nice solution. > (let ((i 0) > funs) > (while (< i 100) > (let ((j i)) > (push (lambda () j) funs)) > (cl-incf i)) > (mapcar #'funcall funs)) This is the trick that is used in the implementation of `dolist': create a binding that lives only inside the evaluation of the body of the loop in one iteration step. > (let ((i 0) > funs) > (while (< i 100) > (push `(lambda () ,i) funs) > (cl-incf i)) > (mapcar #'funcall funs)) Hmm...hmm. No, we don't want to quote lambdas. When Stefan sees that he might install a patch that will make the above error (he really could do this!). Better only do that privately. > Oh, I forgot to `nreverse` funs so my Nth function returns 99-N instead. > Good enough... Ok, it still counts (but maybe backwards). Regards, Michael. ^ permalink raw reply [flat|nested] 86+ messages in thread
* Re: Closures - do you understand them well? 2022-12-09 21:21 ` Michael Heerdegen @ 2022-12-09 21:31 ` Emanuel Berg 0 siblings, 0 replies; 86+ messages in thread From: Emanuel Berg @ 2022-12-09 21:31 UTC (permalink / raw) To: help-gnu-emacs Michael Heerdegen wrote: >> (let ((i 0) >> (m (lambda (i) >> (lambda () i))) >> funs) >> (while (< i 100) >> (push (funcall m i) funs) >> (cl-incf i)) >> (mapcar #'funcall funs)) > > Yes, I think one can do this (the argument variable > i shadows the variable of the same in the `let', but it also > exists to conserve the value from the outside i so one can > argue that it's ok to use the same name - it's semantically > not incorrect anyway). Nice solution. Okay so now it works for me as well, maybe some encoding in messed up evaluation ... >> (let ((i 0) >> funs) >> (while (< i 100) >> (let ((j i)) >> (push (lambda () j) funs)) >> (cl-incf i)) >> (mapcar #'funcall funs)) > > This is the trick that is used in the implementation of > `dolist': create a binding that lives only inside the > evaluation of the body of the loop in one iteration step. Same, works. -- underground experts united https://dataswamp.org/~incal ^ permalink raw reply [flat|nested] 86+ messages in thread
* Re: Closures - do you understand them well? 2022-12-09 20:55 ` Tassilo Horn 2022-12-09 21:21 ` Michael Heerdegen @ 2022-12-09 21:23 ` Emanuel Berg 2022-12-10 11:40 ` tomas 2022-12-10 4:46 ` Emanuel Berg 2 siblings, 1 reply; 86+ messages in thread From: Emanuel Berg @ 2022-12-09 21:23 UTC (permalink / raw) To: help-gnu-emacs Tassilo Horn wrote: > This time I'm prepared and have three versions making a new > binding. Take this, Michael! :-) > > (let ((i 0) > (m (lambda (i) > (lambda () i))) > funs) > (while (< i 100) > (push (funcall m i) funs) > (cl-incf i)) > (mapcar #'funcall funs)) Same. > (let ((i 0) > funs) > (while (< i 100) > (let ((j i)) > (push (lambda () j) funs)) > (cl-incf i)) > (mapcar #'funcall funs)) DNC ... > (let ((i 0) > funs) > (while (< i 100) > (push `(lambda () ,i) funs) > (cl-incf i)) > (mapcar #'funcall funs)) Yes, but here there is no "new binding" exactly, rather the value is hard-coded onto the lambda ... -- underground experts united https://dataswamp.org/~incal ^ permalink raw reply [flat|nested] 86+ messages in thread
* Re: Closures - do you understand them well? 2022-12-09 21:23 ` Emanuel Berg @ 2022-12-10 11:40 ` tomas 2022-12-12 1:18 ` Michael Heerdegen 2022-12-22 4:00 ` Emanuel Berg 0 siblings, 2 replies; 86+ messages in thread From: tomas @ 2022-12-10 11:40 UTC (permalink / raw) To: help-gnu-emacs [-- Attachment #1: Type: text/plain, Size: 493 bytes --] On Fri, Dec 09, 2022 at 10:23:21PM +0100, Emanuel Berg wrote: > Tassilo Horn wrote: [...] > > (let ((i 0) > > funs) > > (while (< i 100) > > (push `(lambda () ,i) funs) > > (cl-incf i)) > > (mapcar #'funcall funs)) > > Yes, but here there is no "new binding" exactly, rather the > value is hard-coded onto the lambda ... Look closely. There is one. Just at macro expansion (aka compile) time. Welcome to Lisp's multiple personality :-) Cheers -- t [-- Attachment #2: signature.asc --] [-- Type: application/pgp-signature, Size: 195 bytes --] ^ permalink raw reply [flat|nested] 86+ messages in thread
* Re: Closures - do you understand them well? 2022-12-10 11:40 ` tomas @ 2022-12-12 1:18 ` Michael Heerdegen 2022-12-12 5:16 ` tomas 2022-12-22 4:00 ` Emanuel Berg 1 sibling, 1 reply; 86+ messages in thread From: Michael Heerdegen @ 2022-12-12 1:18 UTC (permalink / raw) To: tomas; +Cc: help-gnu-emacs <tomas@tuxteam.de> writes: > > > (let ((i 0) > > > funs) > > > (while (< i 100) > > > (push `(lambda () ,i) funs) > > > (cl-incf i)) > > > (mapcar #'funcall funs)) > > > > Yes, but here there is no "new binding" exactly, rather the > > value is hard-coded onto the lambda ... > > Look closely. There is one. Just at macro expansion (aka compile) > time. ?!? The expansion of (push `(lambda () ,i) funs) is #+begin_src emacs-lisp (setq funs (cons (list 'lambda nil i) funs)) #+end_src No binding is created here, neither at compile time (where the symbol i is not touched), nor at run-time (where the value of `i` is just passed as an argument to `list'). Stefan would say that this accumulates a list of function expressions in FUNS, not a list of functions, strictly speaking. Works only because the Lisp interpreter is made to be nice to everyone. Michael. ^ permalink raw reply [flat|nested] 86+ messages in thread
* Re: Closures - do you understand them well? 2022-12-12 1:18 ` Michael Heerdegen @ 2022-12-12 5:16 ` tomas 2022-12-12 6:09 ` Michael Heerdegen 2023-01-18 12:11 ` Emanuel Berg 0 siblings, 2 replies; 86+ messages in thread From: tomas @ 2022-12-12 5:16 UTC (permalink / raw) To: Michael Heerdegen; +Cc: help-gnu-emacs [-- Attachment #1: Type: text/plain, Size: 1436 bytes --] On Mon, Dec 12, 2022 at 02:18:04AM +0100, Michael Heerdegen wrote: > <tomas@tuxteam.de> writes: > > > > > (let ((i 0) > > > > funs) > > > > (while (< i 100) > > > > (push `(lambda () ,i) funs) > > > > (cl-incf i)) > > > > (mapcar #'funcall funs)) > > > > > > Yes, but here there is no "new binding" exactly, rather the > > > value is hard-coded onto the lambda ... > > > > Look closely. There is one. Just at macro expansion (aka compile) > > time. > > ?!? > > The expansion of (push `(lambda () ,i) funs) is ^^^ To me, that one (well, if you squint, the others too) counts as a compile time binding, of sorts. Or well, pre-compile or something. It was the "poor human's closure" in pre-lexical times, after all. > #+begin_src emacs-lisp > (setq funs > (cons > (list 'lambda nil i) > funs)) > #+end_src Yes, the binding of i is effective before the lambda expression is "compiled" (whatever that means when you are playing interpreter, but it still means something, no?) > Stefan would say that this accumulates a list of function expressions in > FUNS, not a list of functions, strictly speaking. Works only because > the Lisp interpreter is made to be nice to everyone. FWIW, I find those languages (the ones trying to be nice) the most interesting. But they can be confusing, too :-) Cheers -- t [-- Attachment #2: signature.asc --] [-- Type: application/pgp-signature, Size: 195 bytes --] ^ permalink raw reply [flat|nested] 86+ messages in thread
* Re: Closures - do you understand them well? 2022-12-12 5:16 ` tomas @ 2022-12-12 6:09 ` Michael Heerdegen 2023-01-18 12:13 ` Emanuel Berg 2023-01-18 12:11 ` Emanuel Berg 1 sibling, 1 reply; 86+ messages in thread From: Michael Heerdegen @ 2022-12-12 6:09 UTC (permalink / raw) To: help-gnu-emacs tomas@tuxteam.de writes: > > The expansion of (push `(lambda () ,i) funs) is > ^^^ > It was the "poor human's closure" in pre-lexical times, > after all. I wonder if that's a reason why lambda expressions where originally made to be treated as functions. > > #+begin_src emacs-lisp > > (setq funs > > (cons > > (list 'lambda nil i) > > funs)) > > #+end_src > > Yes, the binding of i is effective before the lambda > expression is "compiled" (whatever that means when you > are playing interpreter, but it still means something, > no?) That's a somewhat quite meta question - but it very probably does mean something (at least I know what you mean...) Michael. ^ permalink raw reply [flat|nested] 86+ messages in thread
* Re: Closures - do you understand them well? 2022-12-12 6:09 ` Michael Heerdegen @ 2023-01-18 12:13 ` Emanuel Berg 2023-01-19 13:21 ` Michael Heerdegen 0 siblings, 1 reply; 86+ messages in thread From: Emanuel Berg @ 2023-01-18 12:13 UTC (permalink / raw) To: help-gnu-emacs Michael Heerdegen wrote: >>> The expansion of (push `(lambda () ,i) funs) is >> ^^^ >> It was the "poor human's closure" in pre-lexical times, >> after all. > > I wonder if that's a reason why lambda expressions where > originally made to be treated as functions. Why should the not be, aren't they anonymous functions? -- underground experts united https://dataswamp.org/~incal ^ permalink raw reply [flat|nested] 86+ messages in thread
* Re: Closures - do you understand them well? 2023-01-18 12:13 ` Emanuel Berg @ 2023-01-19 13:21 ` Michael Heerdegen 2023-01-27 20:24 ` Emanuel Berg 0 siblings, 1 reply; 86+ messages in thread From: Michael Heerdegen @ 2023-01-19 13:21 UTC (permalink / raw) To: help-gnu-emacs Emanuel Berg <incal@dataswamp.org> writes: > Michael Heerdegen wrote: > > >>> The expansion of (push `(lambda () ,i) funs) is > >> ^^^ > >> It was the "poor human's closure" in pre-lexical times, > >> after all. > > > > I wonder if that's a reason why lambda expressions where > > originally made to be treated as functions. > > Why should the not be, aren't they anonymous functions? Note I mean the expression, not the values they eval to. The (unevaluated) expressions are just lists. As values they are "quoted lambdas" with all of the problems they come with. The Elisp interpreter still accepts them as function values. Michael. ^ permalink raw reply [flat|nested] 86+ messages in thread
* Re: Closures - do you understand them well? 2023-01-19 13:21 ` Michael Heerdegen @ 2023-01-27 20:24 ` Emanuel Berg 2023-01-28 0:44 ` Michael Heerdegen 0 siblings, 1 reply; 86+ messages in thread From: Emanuel Berg @ 2023-01-27 20:24 UTC (permalink / raw) To: help-gnu-emacs Michael Heerdegen wrote: > The (unevaluated) expressions are just lists. As values they > are "quoted lambdas" with all of the problems they come > with. The Elisp interpreter still accepts them as > function values. Okay, why, for technical reasons? And what values are the correct function values then? -- underground experts united https://dataswamp.org/~incal ^ permalink raw reply [flat|nested] 86+ messages in thread
* Re: Closures - do you understand them well? 2023-01-27 20:24 ` Emanuel Berg @ 2023-01-28 0:44 ` Michael Heerdegen 2023-02-26 12:45 ` Emanuel Berg 0 siblings, 1 reply; 86+ messages in thread From: Michael Heerdegen @ 2023-01-28 0:44 UTC (permalink / raw) To: help-gnu-emacs Emanuel Berg <incal@dataswamp.org> writes: > Michael Heerdegen wrote: > > > The (unevaluated) expressions are just lists. As values they > > are "quoted lambdas" with all of the problems they come > > with. The Elisp interpreter still accepts them as > > function values. > > Okay, why, for technical reasons? Is your question why they are (still) accepted? I'm not an expert, but I'll try to give an answer. In the dynamical binding dialect, lambda expressions were self-evaluating expressions: the function value was identical (`equal') to the evaluated expression (when interpreting uncompiled code). See the definition of `lambda' in subr.el. That fact could be exploited to build function values with certain properties in a copy-and-paste like style (using backquote expressions, typically). "Poor-mans closures" already had been mentioned. Old code still uses such techniques so I guess it would break too much of such stuff if such values would not be supported any more. Oh, and of course, since the Emacs interpreter has to support both dialects at the same time (you can use packages with lexical binding enabled and disabled in one and the same session), the interpreter has to support such values anyway since they are valid in one dialect. AFAIU, conceptually the type of binding is a property of the code - the interpreter just can run both types of code. > And what values are the correct function values then? Lexical closures use a different representation - see (info "(elisp) Closures") The actual structure is not interesting for programming any more. And in compiled code or natively compiled code function values are not such nicely explorable lists anyway. Michael. ^ permalink raw reply [flat|nested] 86+ messages in thread
* Re: Closures - do you understand them well? 2023-01-28 0:44 ` Michael Heerdegen @ 2023-02-26 12:45 ` Emanuel Berg 2023-02-27 8:33 ` tomas 2023-02-28 10:13 ` Michael Heerdegen 0 siblings, 2 replies; 86+ messages in thread From: Emanuel Berg @ 2023-02-26 12:45 UTC (permalink / raw) To: help-gnu-emacs Michael Heerdegen wrote: > AFAIU, conceptually the type of binding is a property of the > code - the interpreter just can run both types of code. I think lexical/static is much better than dynamic in general, and was thinking about the other discussion where dynamic typing resulted in much slower compiled code compared with static typing, so what about the binding dialect/variable scope, how does that (lexical vs dynamic) affect the execution speed of the compiled code? Obviously both Elisp and CL has both ... Maybe some optimizations to be made with lexical/static because of the increased enclosure (ha), modularity and predictability? >> And what values are the correct function values then? > > Lexical closures use a different representation - see > > (info "(elisp) Closures") > > The actual structure is not interesting for programming > any more. Are we talking lexical let-closures? Why not? -- underground experts united https://dataswamp.org/~incal ^ permalink raw reply [flat|nested] 86+ messages in thread
* Re: Closures - do you understand them well? 2023-02-26 12:45 ` Emanuel Berg @ 2023-02-27 8:33 ` tomas 2023-02-28 10:13 ` Michael Heerdegen 1 sibling, 0 replies; 86+ messages in thread From: tomas @ 2023-02-27 8:33 UTC (permalink / raw) To: help-gnu-emacs [-- Attachment #1: Type: text/plain, Size: 420 bytes --] On Sun, Feb 26, 2023 at 01:45:56PM +0100, Emanuel Berg wrote: [...] > Maybe some optimizations to be made with lexical/static > because of the increased enclosure (ha), modularity > and predictability? That's the biggest part of it, yes: the compiler has a chance of knowing what's "going on" and whether "someone else" will be able to change a variable's value "behind its back" or not. Cheers - t [-- Attachment #2: signature.asc --] [-- Type: application/pgp-signature, Size: 195 bytes --] ^ permalink raw reply [flat|nested] 86+ messages in thread
* Re: Closures - do you understand them well? 2023-02-26 12:45 ` Emanuel Berg 2023-02-27 8:33 ` tomas @ 2023-02-28 10:13 ` Michael Heerdegen 2023-03-01 20:42 ` Emanuel Berg 2023-03-02 11:08 ` Michael Heerdegen 1 sibling, 2 replies; 86+ messages in thread From: Michael Heerdegen @ 2023-02-28 10:13 UTC (permalink / raw) To: help-gnu-emacs Emanuel Berg <incal@dataswamp.org> writes: > >> And what values are the correct function values then? > > > > Lexical closures use a different representation - see > > > > (info "(elisp) Closures") > > > > The actual structure is not interesting for programming > > any more. > > Are we talking lexical let-closures? Why not? Unless I still misunderstand your question: Lisp is a high-level language, not Assembler, so like you don't modify the bytes of byte-code functions by hand, you also don't edit the internal representation of closures. Michael. ^ permalink raw reply [flat|nested] 86+ messages in thread
* Re: Closures - do you understand them well? 2023-02-28 10:13 ` Michael Heerdegen @ 2023-03-01 20:42 ` Emanuel Berg 2023-03-03 12:09 ` Michael Heerdegen 2023-03-02 11:08 ` Michael Heerdegen 1 sibling, 1 reply; 86+ messages in thread From: Emanuel Berg @ 2023-03-01 20:42 UTC (permalink / raw) To: help-gnu-emacs Michael Heerdegen wrote: >> Are we talking lexical let-closures? Why not? > > Unless I still misunderstand your question: Lisp is > a high-level language, not Assembler, so like you don't > modify the bytes of byte-code functions by hand, you also > don't edit the internal representation of closures. ??? Assembler? It seems to be some big misunderstanding here, yes :) I simply mean this: (let ((...)) (defun () ...) ) -- underground experts united https://dataswamp.org/~incal ^ permalink raw reply [flat|nested] 86+ messages in thread
* Re: Closures - do you understand them well? 2023-03-01 20:42 ` Emanuel Berg @ 2023-03-03 12:09 ` Michael Heerdegen 0 siblings, 0 replies; 86+ messages in thread From: Michael Heerdegen @ 2023-03-03 12:09 UTC (permalink / raw) To: help-gnu-emacs Emanuel Berg <incal@dataswamp.org> writes: > Michael Heerdegen wrote: > > >> Are we talking lexical let-closures? Why not? > > > > Unless I still misunderstand your question: Lisp is > > a high-level language, not Assembler, so like you don't > > modify the bytes of byte-code functions by hand, you also > > don't edit the internal representation of closures. > > ??? Assembler? > > It seems to be some big misunderstanding here, yes :) > > I simply mean this: > > (let ((...)) > (defun () ...) ) Yes, I'm aware that this is what you are thinking about now. But I think you diverged a bit from the question I had answered in this subthread. I had answered something different. This answer was about (please go some messages up...) your question about why we don't use to change function values (destructively) as we once did with lambda forms before lexical binding existed. Michael. ^ permalink raw reply [flat|nested] 86+ messages in thread
* Re: Closures - do you understand them well? 2023-02-28 10:13 ` Michael Heerdegen 2023-03-01 20:42 ` Emanuel Berg @ 2023-03-02 11:08 ` Michael Heerdegen 2023-03-02 18:25 ` Emanuel Berg ` (2 more replies) 1 sibling, 3 replies; 86+ messages in thread From: Michael Heerdegen @ 2023-03-02 11:08 UTC (permalink / raw) To: help-gnu-emacs Michael Heerdegen <michael_heerdegen@web.de> writes: > > > The actual structure is not interesting for programming > > > any more. > > > > Are we talking lexical let-closures? Why not? > > Unless I still misunderstand your question: Lisp is a high-level > language, not Assembler, so like you don't modify the bytes of byte-code > functions by hand, you also don't edit the internal representation of > closures. Maybe I should mention oclosures where you can access variables with accessor functions "from the outside". But this is also a high-level thing, the internal structure of oclosures is not important and an implementation like for "normal" function values. Micha. ^ permalink raw reply [flat|nested] 86+ messages in thread
* Re: Closures - do you understand them well? 2023-03-02 11:08 ` Michael Heerdegen @ 2023-03-02 18:25 ` Emanuel Berg 2023-03-02 20:48 ` Emanuel Berg 2023-03-02 18:37 ` Emanuel Berg 2023-03-02 18:50 ` Emanuel Berg 2 siblings, 1 reply; 86+ messages in thread From: Emanuel Berg @ 2023-03-02 18:25 UTC (permalink / raw) To: help-gnu-emacs Michael Heerdegen wrote: >>> Are we talking lexical let-closures? Why not? >> >> Unless I still misunderstand your question: Lisp is >> a high-level language, not Assembler, so like you don't >> modify the bytes of byte-code functions by hand, you also >> don't edit the internal representation of closures. > > Maybe I should mention oclosures where you can access > variables with accessor functions "from the outside". > But this is also a high-level thing, the internal structure > of oclosures is not important and an implementation like for > "normal" function values. https://www.iro.umontreal.ca/~monnier/oclosure.pdf For some reason I'm not attracted to that idea like I was top-level lexical let-closures, i.e. (let ((...)) (defun (...) ...) ) but I should take a look at that document and not just make up my mind, alltho that works most of the time by now since I trust my intuition which is a trained skill like any other. Okay, so when are oclosures used? When they are useful, right? -- underground experts united https://dataswamp.org/~incal ^ permalink raw reply [flat|nested] 86+ messages in thread
* Re: Closures - do you understand them well? 2023-03-02 18:25 ` Emanuel Berg @ 2023-03-02 20:48 ` Emanuel Berg 2023-03-03 6:56 ` Eli Zaretskii 2023-03-03 12:19 ` Michael Heerdegen 0 siblings, 2 replies; 86+ messages in thread From: Emanuel Berg @ 2023-03-02 20:48 UTC (permalink / raw) To: help-gnu-emacs > https://www.iro.umontreal.ca/~monnier/oclosure.pdf A better link is https://zenodo.org/record/6228797 here we see SEO on the basis of the URL isn't a thing of the past, at least not for very unfrequent searches. -- underground experts united https://dataswamp.org/~incal ^ permalink raw reply [flat|nested] 86+ messages in thread
* Re: Closures - do you understand them well? 2023-03-02 20:48 ` Emanuel Berg @ 2023-03-03 6:56 ` Eli Zaretskii 2023-03-03 12:19 ` Michael Heerdegen 1 sibling, 0 replies; 86+ messages in thread From: Eli Zaretskii @ 2023-03-03 6:56 UTC (permalink / raw) To: help-gnu-emacs > From: Emanuel Berg <incal@dataswamp.org> > Date: Thu, 02 Mar 2023 21:48:54 +0100 > > > https://www.iro.umontreal.ca/~monnier/oclosure.pdf > > A better link is > > https://zenodo.org/record/6228797 A much better link, since the former gives you 404. ^ permalink raw reply [flat|nested] 86+ messages in thread
* Re: Closures - do you understand them well? 2023-03-02 20:48 ` Emanuel Berg 2023-03-03 6:56 ` Eli Zaretskii @ 2023-03-03 12:19 ` Michael Heerdegen 1 sibling, 0 replies; 86+ messages in thread From: Michael Heerdegen @ 2023-03-03 12:19 UTC (permalink / raw) To: help-gnu-emacs Emanuel Berg <incal@dataswamp.org> writes: > A better link is > > https://zenodo.org/record/6228797 > > here we see SEO on the basis of the URL isn't a thing of the > past, at least not for very unfrequent searches. They are now also described in the manual. If you look at the Emacs sources you'll see that there are a few quite simple uses (e.g. keyboard macros). Note that my intention was not to advertise oclosures to you, I just wanted to mention them because we were speaking (at least I was speaking) about modification of functions. Michael. ^ permalink raw reply [flat|nested] 86+ messages in thread
* Re: Closures - do you understand them well? 2023-03-02 11:08 ` Michael Heerdegen 2023-03-02 18:25 ` Emanuel Berg @ 2023-03-02 18:37 ` Emanuel Berg 2023-03-02 18:50 ` Emanuel Berg 2 siblings, 0 replies; 86+ messages in thread From: Emanuel Berg @ 2023-03-02 18:37 UTC (permalink / raw) To: help-gnu-emacs Michael Heerdegen wrote: >>>> The actual structure is not interesting for programming >>>> any more. >>> >>> Are we talking lexical let-closures? Why not? >> >> Unless I still misunderstand your question: Lisp is >> a high-level language, not Assembler, so like you don't >> modify the bytes of byte-code functions by hand, you also >> don't edit the internal representation of closures. > > Maybe I should mention oclosures where you can access > variables with accessor functions "from the outside". > But this is also a high-level thing, the internal structure > of oclosures is not important and an implementation like for > "normal" function values. Open closures BTW, isn't that a contradiction in terms, even? :) Smells too much OO but maybe they were there before the OO paradigm ... -- underground experts united https://dataswamp.org/~incal ^ permalink raw reply [flat|nested] 86+ messages in thread
* Re: Closures - do you understand them well? 2023-03-02 11:08 ` Michael Heerdegen 2023-03-02 18:25 ` Emanuel Berg 2023-03-02 18:37 ` Emanuel Berg @ 2023-03-02 18:50 ` Emanuel Berg 2 siblings, 0 replies; 86+ messages in thread From: Emanuel Berg @ 2023-03-02 18:50 UTC (permalink / raw) To: help-gnu-emacs Michael Heerdegen wrote: > Maybe I should mention oclosures where you can access > variables with accessor functions "from the outside". > But this is also a high-level thing, the internal structure > of oclosures is not important and an implementation like for > "normal" function values. Here is the abstract: While folklore teaches us that closures and objects are two sides of the same coin, they remain quite different in practice, most notably because closures are opaque, the only supported operation being to call them. In this article we discuss a few cases where we need functions to be less opaque, and propose to satisfy this need by extending our beloved 𝜆 so as to expose as sorts of record fields some of the variables it captures. These open closures are close relatives of CLOS’s funcallable objects as well as of the function objects of traditional object-oriented languages like Java, except that they are functions made to behave like objects rather than the reverse. We present the design and implementation of such a feature in the context of Emacs Lisp. [1] There is a list of use case, they seem to have a lot to do with really specific situations and fringe cases were one would previous hack one's way thru it each time, and not rely on ideomatic, clean code, so now with oclosures that's much easier. Good, but if so it's maybe nothing indispensible for the Joe Emacs Hacker, whereas the top-level lexical let-closures are one or two small steps forward with the three use cases I have identified (no/less global varaibles, share variables between functions, preserved variable values between function calls). But I'm all for the esoteric stuff as well so it's all good. [1] https://www.iro.umontreal.ca/~monnier/oclosure.pdf -- underground experts united https://dataswamp.org/~incal ^ permalink raw reply [flat|nested] 86+ messages in thread
* Re: Closures - do you understand them well? 2022-12-12 5:16 ` tomas 2022-12-12 6:09 ` Michael Heerdegen @ 2023-01-18 12:11 ` Emanuel Berg 1 sibling, 0 replies; 86+ messages in thread From: Emanuel Berg @ 2023-01-18 12:11 UTC (permalink / raw) To: help-gnu-emacs tomas wrote: > It was the "poor human's closure" in pre-lexical times, > after all. What are the differences, are we talking closures as in lexical-let and defun(s)? -- underground experts united https://dataswamp.org/~incal ^ permalink raw reply [flat|nested] 86+ messages in thread
* Re: Closures - do you understand them well? 2022-12-10 11:40 ` tomas 2022-12-12 1:18 ` Michael Heerdegen @ 2022-12-22 4:00 ` Emanuel Berg 2022-12-23 6:27 ` tomas 1 sibling, 1 reply; 86+ messages in thread From: Emanuel Berg @ 2022-12-22 4:00 UTC (permalink / raw) To: help-gnu-emacs tomas wrote: > Just at macro expansion (aka compile) time Side question, how many 'times' are there and what, at least conceptually, happens in each? Figure or ascii diagram, anyone? > Welcome to Lisp's multiple personality :-) Explain :-) :-( -- underground experts united https://dataswamp.org/~incal ^ permalink raw reply [flat|nested] 86+ messages in thread
* Re: Closures - do you understand them well? 2022-12-22 4:00 ` Emanuel Berg @ 2022-12-23 6:27 ` tomas 2023-01-18 12:23 ` Emanuel Berg 0 siblings, 1 reply; 86+ messages in thread From: tomas @ 2022-12-23 6:27 UTC (permalink / raw) To: help-gnu-emacs [-- Attachment #1: Type: text/plain, Size: 1574 bytes --] On Thu, Dec 22, 2022 at 05:00:25AM +0100, Emanuel Berg wrote: > tomas wrote: > > > Just at macro expansion (aka compile) time > > Side question, how many 'times' are there and what, > at least conceptually, happens in each? Figure or ascii > diagram, anyone? It's turtles [1] all the way down! Since you have eval, you are empowered to compile at run time and thus have a compile time in there. Still, there are (at least) two phases (at least whenever you have anything more than "just" a naive interpreter), one where your "source" is being analysed to find opportunities ("this variable is always bound to 3 here [2] (or to the identity fun, or...) so we can roll that constant into the compile product"), and the run time, where that product is "run". > > Welcome to Lisp's multiple personality :-) > > Explain :-) :-( Other languages (e.g. C) have clearly distinct sub-languages to do things at compile time (C, again, has CPP, which is clearly distinct from C proper). In Lisp, you can use Lisp at compile time (the language you use to transform your source is Lisp), but at the same time, your environment is completely different at those two phases. Some go as far as to say that they are different languages. Typically there are devices to control that (in Emacs Lisp `eval-when-compile' and `eval-and-compile', I'll let more knowledgeable folks chime in and complete that list). Cheers [1] https://en.wikipedia.org/wiki/It%27s_turtles_all_the_way_down [2] That's why lexical is easier for optimising compilers -- t [-- Attachment #2: signature.asc --] [-- Type: application/pgp-signature, Size: 195 bytes --] ^ permalink raw reply [flat|nested] 86+ messages in thread
* Re: Closures - do you understand them well? 2022-12-23 6:27 ` tomas @ 2023-01-18 12:23 ` Emanuel Berg 0 siblings, 0 replies; 86+ messages in thread From: Emanuel Berg @ 2023-01-18 12:23 UTC (permalink / raw) To: help-gnu-emacs tomas wrote: >> Side question, how many 'times' are there and what, at >> least conceptually, happens in each? Figure or ascii >> diagram, anyone? > > It's turtles [1] all the way down! Since you have eval, you > are empowered to compile at run time and thus have a compile > time in there. Still, there are (at least) two phases (at > least whenever you have anything more than "just" a naive > interpreter), one where your "source" is being analysed to > find opportunities ("this variable is always bound to 3 here > [2] (or to the identity fun, or...) so we can roll that > constant into the compile product"), and the run time, where > that product is "run". > >>> Welcome to Lisp's multiple personality :-) >> >> Explain :-) :-( > > Other languages (e.g. C) have clearly distinct sub-languages > to do things at compile time (C, again, has CPP, which is > clearly distinct from C proper). In Lisp, you can use Lisp > at compile time (the language you use to transform your > source is Lisp), but at the same time, your environment is > completely different at those two phases. Some go as far as > to say that they are different languages. Typically there > are devices to control that (in Emacs Lisp > `eval-when-compile' and `eval-and-compile', I'll let more > knowledgeable folks chime in and complete that list). The byte-compiler is written in Elisp and it transforms Elisp including performing various optimization efforts know to the world of compilers, then the resulting transformed/optimized Elisp is or can be run independently. The environment are different since first it's the environment of the byte-compiler, after that it's the environment of the compiled program ... -- underground experts united https://dataswamp.org/~incal ^ permalink raw reply [flat|nested] 86+ messages in thread
* Re: Closures - do you understand them well? 2022-12-09 20:55 ` Tassilo Horn 2022-12-09 21:21 ` Michael Heerdegen 2022-12-09 21:23 ` Emanuel Berg @ 2022-12-10 4:46 ` Emanuel Berg 2 siblings, 0 replies; 86+ messages in thread From: Emanuel Berg @ 2022-12-10 4:46 UTC (permalink / raw) To: help-gnu-emacs Tassilo Horn wrote: > (let ((i 0) > (m (lambda (i) > (lambda () i))) > funs) > (while (< i 100) > (push (funcall m i) funs) > (cl-incf i)) > (mapcar #'funcall funs)) > > (let ((i 0) > funs) > (while (< i 100) > (let ((j i)) > (push (lambda () j) funs)) > (cl-incf i)) > (mapcar #'funcall funs)) OK, so `lexical-binding' required, that's why they don't work in the article buffer but suddenly work when I yank them into an Elisp buffer ... (setq-default lexical-binding t) anyone? -- underground experts united https://dataswamp.org/~incal ^ permalink raw reply [flat|nested] 86+ messages in thread
* Re: Closures - do you understand them well? 2022-12-09 19:40 ` Michael Heerdegen 2022-12-09 19:50 ` tomas 2022-12-09 20:55 ` Tassilo Horn @ 2022-12-10 0:12 ` Michael Heerdegen 2022-12-10 9:34 ` Tassilo Horn 2 siblings, 1 reply; 86+ messages in thread From: Michael Heerdegen @ 2022-12-10 0:12 UTC (permalink / raw) To: help-gnu-emacs Michael Heerdegen <michael_heerdegen@web.de> writes: > Write an expression that returns a list of 100 functions accepting zero > arguments. `funcall'ing the Nth function must return N. Use a `while' > loop or whatever you like but please not `dolist' or any tool that > already handles this "problem" specifically. Would this be a valid solution? #+begin_src emacs-lisp (let ((i 0) (funs)) (while (<= (cl-incf i) 100) (push (apply-partially #'identity i) funs)) (nreverse funs)) #+end_src Michael. ^ permalink raw reply [flat|nested] 86+ messages in thread
* Re: Closures - do you understand them well? 2022-12-10 0:12 ` Michael Heerdegen @ 2022-12-10 9:34 ` Tassilo Horn 2022-12-10 10:02 ` Emanuel Berg ` (2 more replies) 0 siblings, 3 replies; 86+ messages in thread From: Tassilo Horn @ 2022-12-10 9:34 UTC (permalink / raw) To: help-gnu-emacs Michael Heerdegen <michael_heerdegen@web.de> writes: >> Write an expression that returns a list of 100 functions accepting >> zero arguments. `funcall'ing the Nth function must return N. Use a >> `while' loop or whatever you like but please not `dolist' or any >> tool that already handles this "problem" specifically. > > Would this be a valid solution? > > #+begin_src emacs-lisp > (let ((i 0) (funs)) > (while (<= (cl-incf i) 100) > (push (apply-partially #'identity i) funs)) > (nreverse funs)) > #+end_src Apparently it works although I don't see why. Where's the difference to this inlined version which returns (101 ... 101)? --8<---------------cut here---------------start------------->8--- (let ((i 0) (funs)) (while (<= (cl-incf i) 100) (push (lambda (&rest args2) (apply #'identity (append (list i) args2))) funs)) (mapcar #'funcall (nreverse funs))) --8<---------------cut here---------------end--------------->8--- Bye, Tassilo ^ permalink raw reply [flat|nested] 86+ messages in thread
* Re: Closures - do you understand them well? 2022-12-10 9:34 ` Tassilo Horn @ 2022-12-10 10:02 ` Emanuel Berg 2022-12-10 16:28 ` Mutation - do you understand it really? (was: Closures - do you understand them well?) Stefan Monnier via Users list for the GNU Emacs text editor 2022-12-11 2:24 ` Closures - do you understand them well? Michael Heerdegen 2 siblings, 0 replies; 86+ messages in thread From: Emanuel Berg @ 2022-12-10 10:02 UTC (permalink / raw) To: help-gnu-emacs Tassilo Horn wrote: > Apparently it works although I don't see why. Where's the > difference to this inlined version which returns (101 ... > 101)? > > (let ((i 0) (funs)) > (while (<= (cl-incf i) 100) > (push (lambda (&rest args2) > (apply #'identity (append (list i) args2))) > funs)) > (mapcar #'funcall (nreverse funs))) I doesn't work for me and I also don't see why ... (101 ... 101) -- underground experts united https://dataswamp.org/~incal ^ permalink raw reply [flat|nested] 86+ messages in thread
* Mutation - do you understand it really? (was: Closures - do you understand them well?) 2022-12-10 9:34 ` Tassilo Horn 2022-12-10 10:02 ` Emanuel Berg @ 2022-12-10 16:28 ` Stefan Monnier via Users list for the GNU Emacs text editor 2022-12-10 18:29 ` Mutation - do you understand it really? Michael Heerdegen 2022-12-11 2:24 ` Closures - do you understand them well? Michael Heerdegen 2 siblings, 1 reply; 86+ messages in thread From: Stefan Monnier via Users list for the GNU Emacs text editor @ 2022-12-10 16:28 UTC (permalink / raw) To: help-gnu-emacs Tassilo Horn [2022-12-10 10:34:24] wrote: > Michael Heerdegen <michael_heerdegen@web.de> writes: >>> Write an expression that returns a list of 100 functions accepting >>> zero arguments. `funcall'ing the Nth function must return N. Use a >>> `while' loop or whatever you like but please not `dolist' or any >>> tool that already handles this "problem" specifically. >> >> Would this be a valid solution? >> >> #+begin_src emacs-lisp >> (let ((i 0) (funs)) >> (while (<= (cl-incf i) 100) >> (push (apply-partially #'identity i) funs)) >> (nreverse funs)) >> #+end_src > > Apparently it works although I don't see why. BTW, for those people here who find this all confusing. I'll point out that the culprit is not "closures" but `setq` (here hidden within `cl-incf`). Immutable variables are just a lot better behaved (and easier to work with for the compiler, which is why GCC/LLVM/... use an SSA conversion to replace those nasty mutable variables with immutable ones). Stefan ^ permalink raw reply [flat|nested] 86+ messages in thread
* Re: Mutation - do you understand it really? 2022-12-10 16:28 ` Mutation - do you understand it really? (was: Closures - do you understand them well?) Stefan Monnier via Users list for the GNU Emacs text editor @ 2022-12-10 18:29 ` Michael Heerdegen 2023-01-18 10:58 ` Emanuel Berg 0 siblings, 1 reply; 86+ messages in thread From: Michael Heerdegen @ 2022-12-10 18:29 UTC (permalink / raw) To: help-gnu-emacs Stefan Monnier via Users list for the GNU Emacs text editor <help-gnu-emacs@gnu.org> writes: > Immutable variables are just a lot better behaved (and easier to work > with for the compiler, which is why GCC/LLVM/... use an SSA conversion > to replace those nasty mutable variables with immutable ones). The original question used `setq'. I presented it to a friend that knows lambda calculus and Haskell very well, but Lisp not at all. When he asked "what does this setq do" and I gave an answer he was shocked that these bindings are mutual in Lisp and his reaction was like "WTF?...Ok, then...". But mutable variable bindings are a legitimate aspect of semantics of closures in Lisp - I hope I didn't scare anybody. When there is an intention then it is to hint at pitfalls so that people know them before they cause trouble. Michael. ^ permalink raw reply [flat|nested] 86+ messages in thread
* Re: Mutation - do you understand it really? 2022-12-10 18:29 ` Mutation - do you understand it really? Michael Heerdegen @ 2023-01-18 10:58 ` Emanuel Berg 2023-01-19 13:59 ` Michael Heerdegen 0 siblings, 1 reply; 86+ messages in thread From: Emanuel Berg @ 2023-01-18 10:58 UTC (permalink / raw) To: help-gnu-emacs Michael Heerdegen wrote: >> Immutable variables are just a lot better behaved (and >> easier to work with for the compiler, which is why >> GCC/LLVM/... use an SSA conversion to replace those nasty >> mutable variables with immutable ones). > > The original question used `setq'. I presented it to > a friend that knows lambda calculus and Haskell very well, > but Lisp not at all. A mathematician who has learned one computer language (Haskell) and pretends to be unable to/takes pride in not ever doing it again? > When he asked "what does this setq do" and I gave an answer > he was shocked Okay, but what did you say then? > that these bindings are mutual in Lisp and his reaction was > like "WTF?...Ok, then...". First the variables are mutable, now the bindings are mutual ... Symbols can have values, that value can change so it's mutable, but the symbol can be assigned something else (or nothing), so that's mutable as well. It's all mutable, that's what you mean? So when you compile you don't do that, instead generate a new one for each time the binding is reassociated? -- underground experts united https://dataswamp.org/~incal ^ permalink raw reply [flat|nested] 86+ messages in thread
* Re: Mutation - do you understand it really? 2023-01-18 10:58 ` Emanuel Berg @ 2023-01-19 13:59 ` Michael Heerdegen 2023-01-19 17:47 ` [External] : " Drew Adams 0 siblings, 1 reply; 86+ messages in thread From: Michael Heerdegen @ 2023-01-19 13:59 UTC (permalink / raw) To: help-gnu-emacs Emanuel Berg <incal@dataswamp.org> writes: > Symbols can have values, that value can change so it's > mutable, but the symbol can be assigned something else (or > nothing), so that's mutable as well. It's all mutable, that's > what you mean? > > So when you compile you don't do that, instead generate a new > one for each time the binding is reassociated? In Haskell you can't change variable bindings like in Lisp. You program in a completely different style. Read an introduction into Haskell if you are interested, then you'll understand the reaction. Michael. ^ permalink raw reply [flat|nested] 86+ messages in thread
* RE: [External] : Re: Mutation - do you understand it really? 2023-01-19 13:59 ` Michael Heerdegen @ 2023-01-19 17:47 ` Drew Adams 0 siblings, 0 replies; 86+ messages in thread From: Drew Adams @ 2023-01-19 17:47 UTC (permalink / raw) To: Michael Heerdegen, help-gnu-emacs@gnu.org > In Haskell you can't change variable bindings like in Lisp. You > program in a completely different style. Read an introduction into > Haskell if you are interested, then you'll understand the reaction. Yes - _completely_ different style, behavior, and meaning. This isn't specific to Haskell. But sure, that's a good example of a popular programming language that's _purely_ functional. (We should just say "functional", but that term has come to encompass even languages such as Lisp, and it pretty much just means languages that emphasize expression evaluation, with nesting and return values.) Languages that are purely functional (or purely logic(al)) use variables only in the _math_ sense: the value of a variable doesn't "vary". Variables aren't memory locations that are assigned values (more than once). In a given definitional context a variable has the same value everywhere. Same thing for function names. That, however, with the proviso that at the _top_ level such languages typically _do_ treat function names, and sometimes variable names, dynamically, i.e., as dynamic variables - variables in the traditional programming (assignment) sense: memory locations to be filled and refilled. E.g., you can redefine a function. There's no `let' at the top level, within which everything is defined. Note that Lisp - even "pure" lisp: only lexically scoped etc. - isn't a purely functional language. The mere presence of `quote' makes it referentially opaque. And even applicative evaluation order is a problem - not what you want in a useful functional language, in general. Lisp isn't lambda calculus or combinatory logic. And it doesn't pretend to be. Its impurity isn't shamefaced. ;-) Lisp is, well, loosey-goosey. ^ permalink raw reply [flat|nested] 86+ messages in thread
* Re: Closures - do you understand them well? 2022-12-10 9:34 ` Tassilo Horn 2022-12-10 10:02 ` Emanuel Berg 2022-12-10 16:28 ` Mutation - do you understand it really? (was: Closures - do you understand them well?) Stefan Monnier via Users list for the GNU Emacs text editor @ 2022-12-11 2:24 ` Michael Heerdegen 2022-12-11 9:13 ` Tassilo Horn 2 siblings, 1 reply; 86+ messages in thread From: Michael Heerdegen @ 2022-12-11 2:24 UTC (permalink / raw) To: help-gnu-emacs Tassilo Horn <tsdh@gnu.org> writes: > > Would this be a valid solution? > > > > #+begin_src emacs-lisp > > (let ((i 0) (funs)) > > (while (<= (cl-incf i) 100) > > (push (apply-partially #'identity i) funs)) > > (nreverse funs)) > > #+end_src > > Apparently it works although I don't see why. I do think the above is a valid solution. > Where's the difference to > this inlined version which returns (101 ... 101)? > > (let ((i 0) (funs)) > (while (<= (cl-incf i) 100) > (push (lambda (&rest args2) > (apply #'identity (append (list i) args2))) > funs)) > (mapcar #'funcall (nreverse funs))) Well - `apply-partially' is a function and I use a simple function call, so it is precisely not just something inlined: The important point is that only the _value_ of the variable i passed, not the variable or a reference to it: #+begin_src emacs-lisp (let ((i 27)) (apply-partially #'identity i)) ==> (closure ((args . (27)) (fun . identity)) (&rest args2) (apply fun (append args args2))) #+end_src Michael. ^ permalink raw reply [flat|nested] 86+ messages in thread
* Re: Closures - do you understand them well? 2022-12-11 2:24 ` Closures - do you understand them well? Michael Heerdegen @ 2022-12-11 9:13 ` Tassilo Horn 0 siblings, 0 replies; 86+ messages in thread From: Tassilo Horn @ 2022-12-11 9:13 UTC (permalink / raw) To: Michael Heerdegen; +Cc: help-gnu-emacs Michael Heerdegen <michael_heerdegen@web.de> writes: >> Where's the difference to >> this inlined version which returns (101 ... 101)? >> >> (let ((i 0) (funs)) >> (while (<= (cl-incf i) 100) >> (push (lambda (&rest args2) >> (apply #'identity (append (list i) args2))) >> funs)) >> (mapcar #'funcall (nreverse funs))) > > Well - `apply-partially' is a function and I use a simple function call, > so it is precisely not just something inlined: The important point is > that only the _value_ of the variable i passed, not the variable or > a reference to it: > > #+begin_src emacs-lisp > (let ((i 27)) > (apply-partially #'identity i)) > ==> > (closure > ((args . (27)) > (fun . identity)) > (&rest args2) > (apply fun (append args args2))) > #+end_src Thanks, that explains it. Bye, Tassilo ^ permalink raw reply [flat|nested] 86+ messages in thread
* Re: Closures - do you understand them well? 2022-12-08 22:00 ` Stefan Monnier via Users list for the GNU Emacs text editor 2022-12-08 22:25 ` [External] : " Drew Adams 2022-12-09 4:49 ` tomas @ 2022-12-10 2:26 ` Emanuel Berg 2022-12-10 17:20 ` [External] : " Drew Adams 2 siblings, 1 reply; 86+ messages in thread From: Emanuel Berg @ 2022-12-10 2:26 UTC (permalink / raw) To: help-gnu-emacs Stefan Monnier via Users list for the GNU Emacs text editor wrote: > Indeed, when I looked at it, I decided it was too much > trouble figuring out how to change `cl-loop` to provide that > behavior :-( IMO `cl-loop` is too complex for its own good. All of Lisp is, and the reason is it's so simple to begin with ... -- underground experts united https://dataswamp.org/~incal ^ permalink raw reply [flat|nested] 86+ messages in thread
* RE: [External] : Re: Closures - do you understand them well? 2022-12-10 2:26 ` Emanuel Berg @ 2022-12-10 17:20 ` Drew Adams 2022-12-10 18:02 ` Iteration macros (was: [External] : Re: Closures - do you understand them well?) Stefan Monnier via Users list for the GNU Emacs text editor 2022-12-21 23:53 ` [External] : Re: Closures - do you understand them well? Emanuel Berg 0 siblings, 2 replies; 86+ messages in thread From: Drew Adams @ 2022-12-10 17:20 UTC (permalink / raw) To: Emanuel Berg, help-gnu-emacs@gnu.org > > Indeed, when I looked at it, I decided it was too much > > trouble figuring out how to change `cl-loop` to provide that > > behavior :-( IMO `cl-loop` is too complex for its own good. > > All of Lisp is, and the reason is it's so simple to begin with ... Most likely Stefan meant that the code implementing `cl-loop' is complex - even too complex for its own good (it's a bother to maintain/improve/correct). But it's also the case that for a _user_ the syntax of `(cl-)loop' is complex - certainly much more complex than the usual Lisp syntax. You essentially have to learn another language - `loop' - to use it. That's one of the arguments in favor of using macro `iterate' instead: its syntax is more "lispy". Users can of course learn the language of `loop', just as they can learn the language of Unix `find', and just as they can learn the language (patterns) of regular expressions, or those of `pcase'. And for the simplest, most common `loop' cases they need not learn/memorize everything in the language. Nevertheless, it remains true that a second/separate language is introduced. That can present advantages (code can often look like simple English commands), but it also presents disadvantages. It's largely a question of taste/style, and "Des goûts et des couleurs, on ne discute pas". https://dictionary.reverso.net/french-english/des+go%C3%BBts+et+des+couleurs+on+ne+discute+pas On the other hand, Occam might have something to say here about multiplying things unnecessarily. https://en.wikipedia.org/wiki/Occam%27s_razor (The rule behind Occam's taste & color preferences, perhaps, but a good rule of thumb nevertheless. The taste question comes in when deciding just which multiplying is "unnecessary".) ^ permalink raw reply [flat|nested] 86+ messages in thread
* Iteration macros (was: [External] : Re: Closures - do you understand them well?) 2022-12-10 17:20 ` [External] : " Drew Adams @ 2022-12-10 18:02 ` Stefan Monnier via Users list for the GNU Emacs text editor 2022-12-10 20:38 ` Drew Adams 2023-01-18 11:08 ` Emanuel Berg 2022-12-21 23:53 ` [External] : Re: Closures - do you understand them well? Emanuel Berg 1 sibling, 2 replies; 86+ messages in thread From: Stefan Monnier via Users list for the GNU Emacs text editor @ 2022-12-10 18:02 UTC (permalink / raw) To: help-gnu-emacs > But it's also the case that for a _user_ the syntax > of `(cl-)loop' is complex - certainly much more > complex than the usual Lisp syntax. You essentially > have to learn another language - `loop' - to use it. That's what I meant, actually, yes. I'm not opposed to introducing specialized sublanguages (after all, I've done that myself for `pcase`, `setf`, and `bindat`, and I'm not opposed to things like `rx` or `peg`), but I think what annoys me in `cl-loop` is that you cannot understand each subelement independently because the effect of each element often depends on the presence/absence of other elements or the place where it appears, ...: it's not just a separate language but that language is not modular (and hence in my view is a bad language design). Shiver's [Anatomy of a Loop](https://www.ccs.neu.edu/home/shivers/papers/loop.pdf) is much better in this respect, but I'm still not a big fan because for example (bind <bindings>) changes the environment of *subsequent* expressions, which I find ugly (admittedly, he does that in Scheme where `define` already suffers from the same problem). Stefan "who votes for `named-let` :-)" ^ permalink raw reply [flat|nested] 86+ messages in thread
* RE: Iteration macros (was: [External] : Re: Closures - do you understand them well?) 2022-12-10 18:02 ` Iteration macros (was: [External] : Re: Closures - do you understand them well?) Stefan Monnier via Users list for the GNU Emacs text editor @ 2022-12-10 20:38 ` Drew Adams 2023-01-18 11:10 ` Emanuel Berg 2023-01-18 11:08 ` Emanuel Berg 1 sibling, 1 reply; 86+ messages in thread From: Drew Adams @ 2022-12-10 20:38 UTC (permalink / raw) To: Stefan Monnier; +Cc: 'Help-Gnu-Emacs (help-gnu-emacs@gnu.org)' [-- Attachment #1: Type: text/plain, Size: 1244 bytes --] > > But it's also the case that for a _user_ the syntax > > of `(cl-)loop' is complex - certainly much more > > complex than the usual Lisp syntax. You essentially > > have to learn another language - `loop' - to use it. > > That's what I meant, actually, yes. > > I'm not opposed to introducing specialized sublanguages (after all, I've > done that myself for `pcase`, `setf`, and `bindat`, and I'm not opposed > to things like `rx` or `peg`), but I think what annoys me in `cl-loop` > is that you cannot understand each subelement independently because the > effect of each element often depends on the presence/absence of other > elements or the place where it appears, ...: it's not just a separate > language but that language is not modular (and hence in my view is a bad > language design). 100% agreement. > Shiver's [Anatomy of a Loop]( > https://www.ccs.neu.edu/home/shivers/papers/loop.pdf) is much > better in this respect, but I'm still not a big fan because for example > (bind <bindings>) changes the environment of *subsequent* expressions, > which I find ugly (admittedly, he does that in Scheme where `define` > already suffers from the same problem). Thanks for that; wasn't familiar with it. [-- Attachment #2: winmail.dat --] [-- Type: application/ms-tnef, Size: 14573 bytes --] ^ permalink raw reply [flat|nested] 86+ messages in thread
* Re: Iteration macros (was: [External] : Re: Closures - do you understand them well?) 2022-12-10 20:38 ` Drew Adams @ 2023-01-18 11:10 ` Emanuel Berg 0 siblings, 0 replies; 86+ messages in thread From: Emanuel Berg @ 2023-01-18 11:10 UTC (permalink / raw) To: help-gnu-emacs Drew Adams wrote: >>> But it's also the case that for a _user_ the syntax of >>> `(cl-)loop' is complex - certainly much more complex than >>> the usual Lisp syntax. You essentially have to learn >>> another language - `loop' - to use it. >> >> That's what I meant, actually, yes. >> >> I'm not opposed to introducing specialized sublanguages >> (after all, I've done that myself for `pcase`, `setf`, and >> `bindat`, and I'm not opposed to things like `rx` or >> `peg`), but I think what annoys me in `cl-loop` is that you >> cannot understand each subelement independently because the >> effect of each element often depends on the >> presence/absence of other elements or the place where it >> appears, ...: it's not just a separate language but that >> language is not modular (and hence in my view is a bad >> language design). > > 100% agreement. But first add/do everything, then reduce ... is a method. -- underground experts united https://dataswamp.org/~incal ^ permalink raw reply [flat|nested] 86+ messages in thread
* Re: Iteration macros (was: [External] : Re: Closures - do you understand them well?) 2022-12-10 18:02 ` Iteration macros (was: [External] : Re: Closures - do you understand them well?) Stefan Monnier via Users list for the GNU Emacs text editor 2022-12-10 20:38 ` Drew Adams @ 2023-01-18 11:08 ` Emanuel Berg 1 sibling, 0 replies; 86+ messages in thread From: Emanuel Berg @ 2023-01-18 11:08 UTC (permalink / raw) To: help-gnu-emacs Stefan Monnier via Users list for the GNU Emacs text editor wrote: >> But it's also the case that for a _user_ the syntax of >> `(cl-)loop' is complex - certainly much more complex than >> the usual Lisp syntax. You essentially have to learn >> another language - `loop' - to use it. > > That's what I meant, actually, yes. > > I'm not opposed to introducing specialized sublanguages > (after all, I've done that myself for `pcase`, `setf`, and > `bindat`, and I'm not opposed to things like `rx` or `peg`) On the contrary, they are cool, perhaps one shouldn't have one language completely made up of them, but here and there they are interesting for sure, add spice ... > but I think what annoys me in `cl-loop` is that you cannot > understand each subelement independently because the effect > of each element often depends on the presence/absence of > other elements or the place where it appears, ...: it's not > just a separate language but that language is not modular > (and hence in my view is a bad language design). But `cl-loop' has cool features as well, the multiple for loops "for" example ... Can't we have a `leap' (the Advanced Elisp to-the-Point Loop) that implements all loops known to programming but without the redundancy/intertanglement of keywords that in practice is a problem using `cl-loop' and understanding it's documentation ... -- underground experts united https://dataswamp.org/~incal ^ permalink raw reply [flat|nested] 86+ messages in thread
* Re: [External] : Re: Closures - do you understand them well? 2022-12-10 17:20 ` [External] : " Drew Adams 2022-12-10 18:02 ` Iteration macros (was: [External] : Re: Closures - do you understand them well?) Stefan Monnier via Users list for the GNU Emacs text editor @ 2022-12-21 23:53 ` Emanuel Berg 1 sibling, 0 replies; 86+ messages in thread From: Emanuel Berg @ 2022-12-21 23:53 UTC (permalink / raw) To: help-gnu-emacs Drew Adams wrote: >>> Indeed, when I looked at it, I decided it was too much >>> trouble figuring out how to change `cl-loop` to provide >>> that behavior :-( IMO `cl-loop` is too complex for its >>> own good. >> >> All of Lisp is, and the reason is it's so simple to begin >> with ... > > Most likely Stefan meant that the code implementing > `cl-loop' is complex - even too complex for its own good > (it's a bother to maintain/improve/correct). Okay, maybe that complexity have something to do with the huge scope of what you can do with that in so many ways? And why I think it's cool with things that breaks the pattern ... I don't want a lot of Lisp, the Lisp I use, to be like that. But it's fun, it feels like the land of total loop freedom which I didn't know existed :) In the computer books I read as a kid they always said the for loop was much more modern an better than the while loop, the do ... until loop, and wasn't there a 'wend' loop as well, whatever that did. I believed it then, now I'm so sure. The while loop is useful and the for loop is useful, but, for specific datastructures, there should be specific loops, one shouldn't, IMO, iterate that manually with the for-increment-i unless there is some extra spanner one wants to throw somewhere in particular which the standard datastructure-loop function doesn't do ... The result of that will also be a nice set of often use datastructures, all with associated, trusted loop functions people can the compete to optimize. So it's de facto standardization which leads to, yeah, better code and better software I guess. So yeah, in a way cl-loop in all it's scope is like the opposite of that, instead of nicely dedicated it can do everything - including being dedicated because it has that as well - but again, I'm a maximalist, I don't want what's best or makes the most sense, well I want that as well, because I want EVERYTHING! > But it's also the case that for a _user_ the syntax > of `(cl-)loop' is complex - certainly much more > complex than the usual Lisp syntax. You essentially > have to learn another language - `loop' - to use it. Maybe an exaggeration but in a matter of speaking, yes, in particular the 'with i = 0' looks like, I don't now, some dialect of SQL? > That's one of the arguments in favor of using macro > `iterate' instead: its syntax is more "lispy". `cl-loop' is, or can be, much less lispy, yes. > Users can of course learn the language of `loop', > just as they can learn the language of Unix `find', > and just as they can learn the language (patterns) > of regular expressions, or those of `pcase'. With `cl-loop' it's too much, no doubt about it, still it's there so why reduce it if it's useful. I would stop using it if all of Elisp was like that but it isn't so hey, relax. `cl-loop is cool B) It is much more powerful (expressive) than the C or C++ for loop in ways that I do understand, and I don't understand all if (cl-lib), by far :) > Nevertheless, it remains true that a second/separate > language is introduced. That can present advantages (code > can often look like simple English commands), but it also > presents disadvantages. Indeed, keep Lisp the old way, no more `cl-loop' style stuff and where it appear, don't put everything in one function, is what I wouldn't do! > It's largely a question of taste/style, and > "Des goûts Interesting so "circumflex DNC" (line 83) in the Linux VT: https://dataswamp.org/~incal/conf/vt/remap.inc > (The rule behind Occam's taste & color preferences, perhaps, > but a good rule of thumb nevertheless. The taste question > comes in when deciding just which multiplying is > "unnecessary".) Whaat??? -- underground experts united https://dataswamp.org/~incal ^ permalink raw reply [flat|nested] 86+ messages in thread
* Re: Closures - do you understand them well? 2022-12-08 20:49 ` Michael Heerdegen 2022-12-08 22:00 ` Stefan Monnier via Users list for the GNU Emacs text editor @ 2022-12-09 3:43 ` Emanuel Berg 2022-12-09 4:01 ` Michael Heerdegen 1 sibling, 1 reply; 86+ messages in thread From: Emanuel Berg @ 2022-12-09 3:43 UTC (permalink / raw) To: help-gnu-emacs Michael Heerdegen wrote: >> In ELisp, both `dotimes` and `dolist` create a new binding >> for `i` at each iteration of the loop. > > This is probably what most people expect from a loop. > `cl-loop' doesn't. > > I guess it's not good to rely on either behavior of built-in > looping constructs. OK, so is it the closures? Or the loops? Or ... the lamdas? (setq x 111) (setq f (lambda () x)) (funcall f) (setq x 222) (funcall f) -- underground experts united https://dataswamp.org/~incal ^ permalink raw reply [flat|nested] 86+ messages in thread
* Re: Closures - do you understand them well? 2022-12-09 3:43 ` Emanuel Berg @ 2022-12-09 4:01 ` Michael Heerdegen 2022-12-09 4:38 ` tomas 2022-12-10 4:52 ` Emanuel Berg 0 siblings, 2 replies; 86+ messages in thread From: Michael Heerdegen @ 2022-12-09 4:01 UTC (permalink / raw) To: help-gnu-emacs Emanuel Berg <incal@dataswamp.org> writes: > OK, so is it the closures? Or the loops? > > Or ... the lamdas? > > (setq x 111) > > (setq f (lambda () x)) > > (funcall f) > > (setq x 222) > > (funcall f) Maybe I'm too tired, but I don't understand the question. What's "it" in the first question? Michael. ^ permalink raw reply [flat|nested] 86+ messages in thread
* Re: Closures - do you understand them well? 2022-12-09 4:01 ` Michael Heerdegen @ 2022-12-09 4:38 ` tomas 2022-12-09 5:37 ` Emanuel Berg 2022-12-10 4:52 ` Emanuel Berg 1 sibling, 1 reply; 86+ messages in thread From: tomas @ 2022-12-09 4:38 UTC (permalink / raw) To: help-gnu-emacs [-- Attachment #1: Type: text/plain, Size: 565 bytes --] On Fri, Dec 09, 2022 at 05:01:23AM +0100, Michael Heerdegen wrote: > Emanuel Berg <incal@dataswamp.org> writes: > > > OK, so is it the closures? Or the loops? > > > > Or ... the lamdas? > > > > (setq x 111) > > > > (setq f (lambda () x)) > > > > (funcall f) > > > > (setq x 222) > > > > (funcall f) > > Maybe I'm too tired, but I don't understand the question. What's "it" > in the first question? My gut reaction was such that the answer to Emanuel's question would have been "it's the bindings". But I may be wrong. Cheers -- t [-- Attachment #2: signature.asc --] [-- Type: application/pgp-signature, Size: 195 bytes --] ^ permalink raw reply [flat|nested] 86+ messages in thread
* Re: Closures - do you understand them well? 2022-12-09 4:38 ` tomas @ 2022-12-09 5:37 ` Emanuel Berg 2022-12-09 16:55 ` Michael Heerdegen 0 siblings, 1 reply; 86+ messages in thread From: Emanuel Berg @ 2022-12-09 5:37 UTC (permalink / raw) To: help-gnu-emacs tomas wrote: >>> OK, so is it the closures? Or the loops? >>> >>> Or ... the lamdas? >>> >>> (setq x 111) >>> >>> (setq f (lambda () x)) >>> >>> (funcall f) >>> >>> (setq x 222) >>> >>> (funcall f) >> >> Maybe I'm too tired, but I don't understand the question. >> What's "it" in the first question? > > My gut reaction was such that the answer to Emanuel's > question would have been "it's the bindings". This is why you should never quote lambdas because if you do, you get the intuitive result: (let ((i 0) (funs '())) (while (< (setq i (1+ i)) 4) (push `(lambda () ,i) funs)) (apply #'+ (mapcar #'funcall funs))) ; 6 -- underground experts united https://dataswamp.org/~incal ^ permalink raw reply [flat|nested] 86+ messages in thread
* Re: Closures - do you understand them well? 2022-12-09 5:37 ` Emanuel Berg @ 2022-12-09 16:55 ` Michael Heerdegen 0 siblings, 0 replies; 86+ messages in thread From: Michael Heerdegen @ 2022-12-09 16:55 UTC (permalink / raw) To: help-gnu-emacs Emanuel Berg <incal@dataswamp.org> writes: > This is why you should never quote lambdas because if you do, > you get the intuitive result: > > (let ((i 0) > (funs '())) > (while (< (setq i (1+ i)) > 4) > (push `(lambda () ,i) > funs)) > (apply #'+ (mapcar #'funcall funs))) ; 6 I think the intended goal was to see that shortcuts can cause trouble, not to try to find a better shortcut... Michael. ^ permalink raw reply [flat|nested] 86+ messages in thread
* Re: Closures - do you understand them well? 2022-12-09 4:01 ` Michael Heerdegen 2022-12-09 4:38 ` tomas @ 2022-12-10 4:52 ` Emanuel Berg 1 sibling, 0 replies; 86+ messages in thread From: Emanuel Berg @ 2022-12-10 4:52 UTC (permalink / raw) To: help-gnu-emacs Michael Heerdegen wrote: >> OK, so is it the closures? Or the loops? >> >> Or ... the lamdas? >> >> (setq x 111) >> >> (setq f (lambda () x)) >> >> (funcall f) >> >> (setq x 222) >> >> (funcall f) > > Maybe I'm too tired, but I don't understand the question. What's "it" > in the first question? I don't know, and I studied it at the university even ... -- underground experts united https://dataswamp.org/~incal ^ permalink raw reply [flat|nested] 86+ messages in thread
* Re: Closures - do you understand them well? 2022-12-08 15:36 Closures - do you understand them well? Michael Heerdegen 2022-12-08 16:24 ` [External] : " Drew Adams 2022-12-08 19:06 ` Tassilo Horn @ 2022-12-08 19:44 ` Eric Abrahamsen 2022-12-08 20:11 ` Emanuel Berg 2022-12-08 20:53 ` Michael Heerdegen 2 siblings, 2 replies; 86+ messages in thread From: Eric Abrahamsen @ 2022-12-08 19:44 UTC (permalink / raw) To: help-gnu-emacs Michael Heerdegen <michael_heerdegen@web.de> writes: > Hi, > > Maybe you will have fun with this new exercise: > > What is the return value of the following expression, and what's your > reasoning? Answer without asking Emacs: I lost! I really thought that with lexical-binding non-nil it would do what I expected. I guess this is why I try not to use closures. ^ permalink raw reply [flat|nested] 86+ messages in thread
* Re: Closures - do you understand them well? 2022-12-08 19:44 ` Eric Abrahamsen @ 2022-12-08 20:11 ` Emanuel Berg 2022-12-08 20:53 ` Michael Heerdegen 1 sibling, 0 replies; 86+ messages in thread From: Emanuel Berg @ 2022-12-08 20:11 UTC (permalink / raw) To: help-gnu-emacs Eric Abrahamsen wrote: > I lost! I really thought that with lexical-binding non-nil > it would do what I expected. I guess this is why I try not > to use closures. Oh, use them! They are very useful :) I understand the two use cases I've found (share access to variables between functions, persistent values in variables between function calls) and it works well for those. Example with both those: https://dataswamp.org/~incal/emacs-init/w3m/w3m-survivor.el But I'd like to understand this riddle as well ... -- underground experts united https://dataswamp.org/~incal ^ permalink raw reply [flat|nested] 86+ messages in thread
* Re: Closures - do you understand them well? 2022-12-08 19:44 ` Eric Abrahamsen 2022-12-08 20:11 ` Emanuel Berg @ 2022-12-08 20:53 ` Michael Heerdegen 2022-12-08 23:25 ` Michael Heerdegen 1 sibling, 1 reply; 86+ messages in thread From: Michael Heerdegen @ 2022-12-08 20:53 UTC (permalink / raw) To: help-gnu-emacs Eric Abrahamsen <eric@ericabrahamsen.net> writes: > I lost! I really thought that with lexical-binding non-nil it would do > what I expected. I guess this is why I try not to use closures. No no, sharpen your mental model. The exercise originates from a mistake I made myself a while ago. Sometimes your brain establishes shortcuts that lead to wrong assumptions. It's human to fall into such traps. Michael. ^ permalink raw reply [flat|nested] 86+ messages in thread
* Re: Closures - do you understand them well? 2022-12-08 20:53 ` Michael Heerdegen @ 2022-12-08 23:25 ` Michael Heerdegen 2022-12-09 16:50 ` Eric Abrahamsen 0 siblings, 1 reply; 86+ messages in thread From: Michael Heerdegen @ 2022-12-08 23:25 UTC (permalink / raw) To: help-gnu-emacs Michael Heerdegen <michael_heerdegen@web.de> writes: > The exercise originates from a mistake I made myself a while ago. > Sometimes your brain establishes shortcuts that lead to wrong > assumptions. It's human to fall into such traps. But I see that exercises that are just traps can be demotivating. I'm not sure how to write more motivating exercises, however, how would they look like? Maybe like, you think it returns 3 but instead it returns...the perfect Christmas present you were looking for? #+begin_src emacs-lisp (if (you-think-this-is-non-nil-but-isnt) 3 "You should buy XYZ.") #+end_src Have to think about it... Michael. ^ permalink raw reply [flat|nested] 86+ messages in thread
* Re: Closures - do you understand them well? 2022-12-08 23:25 ` Michael Heerdegen @ 2022-12-09 16:50 ` Eric Abrahamsen 2022-12-09 18:48 ` Emanuel Berg 2022-12-09 19:25 ` Michael Heerdegen 0 siblings, 2 replies; 86+ messages in thread From: Eric Abrahamsen @ 2022-12-09 16:50 UTC (permalink / raw) To: help-gnu-emacs Michael Heerdegen <michael_heerdegen@web.de> writes: > Michael Heerdegen <michael_heerdegen@web.de> writes: > >> The exercise originates from a mistake I made myself a while ago. >> Sometimes your brain establishes shortcuts that lead to wrong >> assumptions. It's human to fall into such traps. > > But I see that exercises that are just traps can be demotivating. > > I'm not sure how to write more motivating exercises, however, how would > they look like? Maybe like, you think it returns 3 but instead it > returns...the perfect Christmas present you were looking for? > > #+begin_src emacs-lisp > (if (you-think-this-is-non-nil-but-isnt) > 3 > "You should buy XYZ.") > #+end_src > > Have to think about it... It's true I don't enjoy "exercises" in general -- a nice Christmas present would be a motivation. I would love to know closures well enough to put them into use without having to spend extra time thinking and testing. But the fact is I *do* need to spend extra time on it, and I rarely hit upon a problem that's begging to be resolved with a closure, so... ^ permalink raw reply [flat|nested] 86+ messages in thread
* Re: Closures - do you understand them well? 2022-12-09 16:50 ` Eric Abrahamsen @ 2022-12-09 18:48 ` Emanuel Berg 2022-12-09 19:25 ` Michael Heerdegen 1 sibling, 0 replies; 86+ messages in thread From: Emanuel Berg @ 2022-12-09 18:48 UTC (permalink / raw) To: help-gnu-emacs Eric Abrahamsen wrote: > I would love to know closures well enough to put them into > use without having to spend extra time thinking and testing. > But the fact is I *do* need to spend extra time on it Eval this: (lambda () x) Same thing, no let-closure. Aren't lambdas like that everywhere? let-closures are not hard to understand, put a bunch of `defun' in a `let' and use the variables like they were globals, only they are not ... > and I rarely hit upon a problem that's begging to be > resolved with a closure, so... Grep your source for global variables. Those are the ones you can get rid of using let-closures, and without changing the code using them. (Possible exception, for practical reasons: Emacs options.) -- underground experts united https://dataswamp.org/~incal ^ permalink raw reply [flat|nested] 86+ messages in thread
* Re: Closures - do you understand them well? 2022-12-09 16:50 ` Eric Abrahamsen 2022-12-09 18:48 ` Emanuel Berg @ 2022-12-09 19:25 ` Michael Heerdegen 2022-12-11 18:42 ` Eric Abrahamsen 1 sibling, 1 reply; 86+ messages in thread From: Michael Heerdegen @ 2022-12-09 19:25 UTC (permalink / raw) To: help-gnu-emacs Eric Abrahamsen <eric@ericabrahamsen.net> writes: > I would love to know closures well enough to put them into use without > having to spend extra time thinking and testing. But the fact is I *do* > need to spend extra time on it, and I rarely hit upon a problem that's > begging to be resolved with a closure, so... Or maybe you don't hear them begging? What were your resources for learning? Michael. ^ permalink raw reply [flat|nested] 86+ messages in thread
* Re: Closures - do you understand them well? 2022-12-09 19:25 ` Michael Heerdegen @ 2022-12-11 18:42 ` Eric Abrahamsen 2023-01-18 12:08 ` Emanuel Berg 0 siblings, 1 reply; 86+ messages in thread From: Eric Abrahamsen @ 2022-12-11 18:42 UTC (permalink / raw) To: help-gnu-emacs Michael Heerdegen <michael_heerdegen@web.de> writes: > Eric Abrahamsen <eric@ericabrahamsen.net> writes: > >> I would love to know closures well enough to put them into use without >> having to spend extra time thinking and testing. But the fact is I *do* >> need to spend extra time on it, and I rarely hit upon a problem that's >> begging to be resolved with a closure, so... > > Or maybe you don't hear them begging? I'm sure if I had a better intuitive grasp, they would present themselves as the right solution more often. > What were your resources for learning? Nothing, I guess -- like all my programming knowledge it started with trying to solve a specific problem, and ended with more in-depth reading. But I've always found multiple layers of indirection confusing (recursion/TCO and nested macros included), and any time anything starts looking like references to references to... I try "fix it" by doing something else. ^ permalink raw reply [flat|nested] 86+ messages in thread
* Re: Closures - do you understand them well? 2022-12-11 18:42 ` Eric Abrahamsen @ 2023-01-18 12:08 ` Emanuel Berg 0 siblings, 0 replies; 86+ messages in thread From: Emanuel Berg @ 2023-01-18 12:08 UTC (permalink / raw) To: help-gnu-emacs Eric Abrahamsen wrote: > But I've always found multiple layers of indirection > confusing (recursion/TCO and nested macros included) TCO = Tail-Call Optimization, so you can use recursion without blowing up the stack ... But recursion isn't confusing, it makes for elegant/textbook programs, it's not really a layer of indirection, is it? Nested macros tho are like the definition of that (extra layer/indirection) since instead of you program -> a program -> that does stuff it is you program -> a program -> that expands into a program -> that does stuff It makes the programming language programmable ... -- underground experts united https://dataswamp.org/~incal ^ permalink raw reply [flat|nested] 86+ messages in thread
end of thread, other threads:[~2023-03-03 12:19 UTC | newest] Thread overview: 86+ messages (download: mbox.gz / follow: Atom feed) -- links below jump to the message on this page -- 2022-12-08 15:36 Closures - do you understand them well? Michael Heerdegen 2022-12-08 16:24 ` [External] : " Drew Adams 2022-12-08 17:30 ` Michael Heerdegen 2022-12-08 17:56 ` Drew Adams 2022-12-08 18:00 ` Drew Adams 2022-12-08 18:49 ` Michael Heerdegen 2022-12-08 19:35 ` Drew Adams 2022-12-10 4:51 ` Emanuel Berg 2022-12-08 19:45 ` Drew Adams 2022-12-08 19:06 ` Tassilo Horn 2022-12-08 19:53 ` Michael Heerdegen 2022-12-08 20:01 ` Stefan Monnier via Users list for the GNU Emacs text editor 2022-12-08 20:49 ` Michael Heerdegen 2022-12-08 22:00 ` Stefan Monnier via Users list for the GNU Emacs text editor 2022-12-08 22:25 ` [External] : " Drew Adams 2022-12-08 22:51 ` Stefan Monnier via Users list for the GNU Emacs text editor 2022-12-10 2:34 ` Emanuel Berg 2022-12-09 5:03 ` Tomas Hlavaty 2022-12-10 2:35 ` Emanuel Berg 2022-12-10 2:29 ` Emanuel Berg 2022-12-10 16:56 ` Drew Adams 2022-12-15 8:25 ` Emanuel Berg 2022-12-09 4:49 ` tomas 2022-12-09 19:40 ` Michael Heerdegen 2022-12-09 19:50 ` tomas 2022-12-09 20:55 ` Tassilo Horn 2022-12-09 21:21 ` Michael Heerdegen 2022-12-09 21:31 ` Emanuel Berg 2022-12-09 21:23 ` Emanuel Berg 2022-12-10 11:40 ` tomas 2022-12-12 1:18 ` Michael Heerdegen 2022-12-12 5:16 ` tomas 2022-12-12 6:09 ` Michael Heerdegen 2023-01-18 12:13 ` Emanuel Berg 2023-01-19 13:21 ` Michael Heerdegen 2023-01-27 20:24 ` Emanuel Berg 2023-01-28 0:44 ` Michael Heerdegen 2023-02-26 12:45 ` Emanuel Berg 2023-02-27 8:33 ` tomas 2023-02-28 10:13 ` Michael Heerdegen 2023-03-01 20:42 ` Emanuel Berg 2023-03-03 12:09 ` Michael Heerdegen 2023-03-02 11:08 ` Michael Heerdegen 2023-03-02 18:25 ` Emanuel Berg 2023-03-02 20:48 ` Emanuel Berg 2023-03-03 6:56 ` Eli Zaretskii 2023-03-03 12:19 ` Michael Heerdegen 2023-03-02 18:37 ` Emanuel Berg 2023-03-02 18:50 ` Emanuel Berg 2023-01-18 12:11 ` Emanuel Berg 2022-12-22 4:00 ` Emanuel Berg 2022-12-23 6:27 ` tomas 2023-01-18 12:23 ` Emanuel Berg 2022-12-10 4:46 ` Emanuel Berg 2022-12-10 0:12 ` Michael Heerdegen 2022-12-10 9:34 ` Tassilo Horn 2022-12-10 10:02 ` Emanuel Berg 2022-12-10 16:28 ` Mutation - do you understand it really? (was: Closures - do you understand them well?) Stefan Monnier via Users list for the GNU Emacs text editor 2022-12-10 18:29 ` Mutation - do you understand it really? Michael Heerdegen 2023-01-18 10:58 ` Emanuel Berg 2023-01-19 13:59 ` Michael Heerdegen 2023-01-19 17:47 ` [External] : " Drew Adams 2022-12-11 2:24 ` Closures - do you understand them well? Michael Heerdegen 2022-12-11 9:13 ` Tassilo Horn 2022-12-10 2:26 ` Emanuel Berg 2022-12-10 17:20 ` [External] : " Drew Adams 2022-12-10 18:02 ` Iteration macros (was: [External] : Re: Closures - do you understand them well?) Stefan Monnier via Users list for the GNU Emacs text editor 2022-12-10 20:38 ` Drew Adams 2023-01-18 11:10 ` Emanuel Berg 2023-01-18 11:08 ` Emanuel Berg 2022-12-21 23:53 ` [External] : Re: Closures - do you understand them well? Emanuel Berg 2022-12-09 3:43 ` Emanuel Berg 2022-12-09 4:01 ` Michael Heerdegen 2022-12-09 4:38 ` tomas 2022-12-09 5:37 ` Emanuel Berg 2022-12-09 16:55 ` Michael Heerdegen 2022-12-10 4:52 ` Emanuel Berg 2022-12-08 19:44 ` Eric Abrahamsen 2022-12-08 20:11 ` Emanuel Berg 2022-12-08 20:53 ` Michael Heerdegen 2022-12-08 23:25 ` Michael Heerdegen 2022-12-09 16:50 ` Eric Abrahamsen 2022-12-09 18:48 ` Emanuel Berg 2022-12-09 19:25 ` Michael Heerdegen 2022-12-11 18:42 ` Eric Abrahamsen 2023-01-18 12:08 ` Emanuel Berg
Code repositories for project(s) associated with this external index https://git.savannah.gnu.org/cgit/emacs.git https://git.savannah.gnu.org/cgit/emacs/org-mode.git This is an external index of several public inboxes, see mirroring instructions on how to clone and mirror all data and code used by this external index.