* Real-life examples of lexical binding in Emacs Lisp @ 2015-05-29 8:28 Marcin Borkowski 2015-05-30 8:28 ` Tassilo Horn [not found] ` <mailman.3950.1432974543.904.help-gnu-emacs@gnu.org> 0 siblings, 2 replies; 32+ messages in thread From: Marcin Borkowski @ 2015-05-29 8:28 UTC (permalink / raw) To: Help Gnu Emacs mailing list Hi all, I googled a bit, and could not find /real-world/ examples of using lexical binding and its advantages /in Emacs Lisp/. I understand that it's a nice thing to be able to create closures, and that lexical binding is in general faster than dynamic binding (which is a bonus in itself), but could anyone show me a real /text editing/ problem that lexical binding solves, like something that is easier done with l.b. than with d.b.? (Examples of general-purpose programming problems made easier with l.b. are more or less obvious/easy to find, but Emacs is a text editor, after all, and this is its primary area.) TIA, -- Marcin Borkowski http://octd.wmi.amu.edu.pl/en/Marcin_Borkowski Faculty of Mathematics and Computer Science Adam Mickiewicz University ^ permalink raw reply [flat|nested] 32+ messages in thread
* Re: Real-life examples of lexical binding in Emacs Lisp 2015-05-29 8:28 Real-life examples of lexical binding in Emacs Lisp Marcin Borkowski @ 2015-05-30 8:28 ` Tassilo Horn 2015-06-14 10:52 ` Marcin Borkowski [not found] ` <mailman.4976.1434279182.904.help-gnu-emacs@gnu.org> [not found] ` <mailman.3950.1432974543.904.help-gnu-emacs@gnu.org> 1 sibling, 2 replies; 32+ messages in thread From: Tassilo Horn @ 2015-05-30 8:28 UTC (permalink / raw) To: Marcin Borkowski; +Cc: Help Gnu Emacs mailing list Marcin Borkowski <mbork@mbork.pl> writes: Hi Marcin, > I googled a bit, and could not find /real-world/ examples of using > lexical binding and its advantages /in Emacs Lisp/. I understand that > it's a nice thing to be able to create closures, and that lexical > binding is in general faster than dynamic binding (which is a bonus in > itself), but could anyone show me a real /text editing/ problem that > lexical binding solves, like something that is easier done with > l.b. than with d.b.? (Examples of general-purpose programming > problems made easier with l.b. are more or less obvious/easy to find, > but Emacs is a text editor, after all, and this is its primary area.) The emacs paper has a section explaining why emacs used dynamic binding from the start: http://www.gnu.org/software/emacs/emacs-paper.html#SEC17 However, to me the two example use-cases only motivate why you want to be able to use dynamic scoping for special variables (defvar), not really for local variables (let) or function parameters, although the first Edit Picture example explicitly speaks of binding command arguments but I don't understand it. To me, having lexical scoping in general plus special, dynamically bound variables is the ideal model. If there wouldn't be special variables anymore, the examples from the paper would need to be implemented by setq-ing the variables and later re-setting them to their old value which would be error-prone and wouldn't work if we ever get concurrency. You can make special variables thread-local like in Clojure thus hiding this additional complexity from programmers. But there are good use-cases for dynamic variables also in "normal" programs. One example is to be able to bind some *error-handler* dynamically in order to customize how to cope with errors that happen far below the call stack. I'm not able to come up with benefits of lexical scoping which are especially important for editing text. The general benefits of being safer, faster, and having closures are still valid of course. Bye, Tassilo ^ permalink raw reply [flat|nested] 32+ messages in thread
* Re: Real-life examples of lexical binding in Emacs Lisp 2015-05-30 8:28 ` Tassilo Horn @ 2015-06-14 10:52 ` Marcin Borkowski [not found] ` <mailman.4976.1434279182.904.help-gnu-emacs@gnu.org> 1 sibling, 0 replies; 32+ messages in thread From: Marcin Borkowski @ 2015-06-14 10:52 UTC (permalink / raw) To: Help Gnu Emacs mailing list OK, so I finally got to study this discussion. (It seems I have kind of a talent for inadvertently starting long discussions...) On 2015-05-30, at 10:28, Tassilo Horn <tsdh@gnu.org> wrote: > Marcin Borkowski <mbork@mbork.pl> writes: > > Hi Marcin, > >> I googled a bit, and could not find /real-world/ examples of using >> lexical binding and its advantages /in Emacs Lisp/. I understand that >> it's a nice thing to be able to create closures, and that lexical >> binding is in general faster than dynamic binding (which is a bonus in >> itself), but could anyone show me a real /text editing/ problem that >> lexical binding solves, like something that is easier done with >> l.b. than with d.b.? (Examples of general-purpose programming >> problems made easier with l.b. are more or less obvious/easy to find, >> but Emacs is a text editor, after all, and this is its primary area.) > > The emacs paper has a section explaining why emacs used dynamic binding > from the start: http://www.gnu.org/software/emacs/emacs-paper.html#SEC17 Yes, I'm aware of that, and I read this paper some time ago (even before asking my question). > However, to me the two example use-cases only motivate why you want to > be able to use dynamic scoping for special variables (defvar), not > really for local variables (let) or function parameters, although the > first Edit Picture example explicitly speaks of binding command > arguments but I don't understand it. > > To me, having lexical scoping in general plus special, dynamically bound > variables is the ideal model. If there wouldn't be special variables > anymore, the examples from the paper would need to be implemented by > setq-ing the variables and later re-setting them to their old value > which would be error-prone and wouldn't work if we ever get concurrency. > You can make special variables thread-local like in Clojure thus hiding > this additional complexity from programmers. > > But there are good use-cases for dynamic variables also in "normal" > programs. One example is to be able to bind some *error-handler* > dynamically in order to customize how to cope with errors that happen > far below the call stack. > > I'm not able to come up with benefits of lexical scoping which are > especially important for editing text. The general benefits of being > safer, faster, and having closures are still valid of course. Exactly. What I'm curious is how lexical scoping might make some tasks *connected to editing* easier/more natural. > Bye, > Tassilo Thanks, -- Marcin Borkowski http://octd.wmi.amu.edu.pl/en/Marcin_Borkowski Faculty of Mathematics and Computer Science Adam Mickiewicz University ^ permalink raw reply [flat|nested] 32+ messages in thread
[parent not found: <mailman.4976.1434279182.904.help-gnu-emacs@gnu.org>]
* Re: Real-life examples of lexical binding in Emacs Lisp [not found] ` <mailman.4976.1434279182.904.help-gnu-emacs@gnu.org> @ 2015-06-14 11:31 ` Pascal J. Bourguignon 2015-06-16 23:48 ` Jim Diamond 0 siblings, 1 reply; 32+ messages in thread From: Pascal J. Bourguignon @ 2015-06-14 11:31 UTC (permalink / raw) To: help-gnu-emacs Marcin Borkowski <mbork@mbork.pl> writes: > Exactly. What I'm curious is how lexical scoping might make some tasks > *connected to editing* easier/more natural. It depends what you mean by "editing". Until a few decades ago, editing was performed using red pens, paper, scissors, glue. Then, lexical scoping was totally useless. Nowdays, editing is performed by software programs. Writing programs is easier and more natural with lexical scoping, IN GENERAL! Therefore, it is easier and mode natural IN PARTICULAR, to write editing programs. Writing programs in general is not *connected to editing*. But writing editor programs in particular is particularly *connected to editing*, even if programming has nothing to do with editing at all, ever. Actually, the programming activity has never anything to do with the application domain! When programming a four legged robot running across fields and parkings, the programmer DOES NOT run across fields and parkings, on his four. I repeat, this is very important: when programming a four legged robot running across fields and parkings, the programmer DOES NOT run across fields and parkings, on his four. No, what the programmer does, is sit on his ass, think, and type a program into a computer, using a keyboard. Now with editing, there may be some understandable confusion, since the programmer will actually use an editor to edit his program, notably when writing an editing program. But you must distinguish the editor being used to write the program from the editor program being written! For example, you could use ed to edit the emacs editor program. The fact that you will be happier and write a better emacs editor program using lexical scoping has NOTHING to do with how the ed editor edits your editor program! Just like you don't run in the fields when you write a robot that runs in the fields. -- __Pascal Bourguignon__ http://www.informatimago.com/ “The factory of the future will have only two employees, a man and a dog. The man will be there to feed the dog. The dog will be there to keep the man from touching the equipment.” -- Carl Bass CEO Autodesk ^ permalink raw reply [flat|nested] 32+ messages in thread
* Re: Real-life examples of lexical binding in Emacs Lisp 2015-06-14 11:31 ` Pascal J. Bourguignon @ 2015-06-16 23:48 ` Jim Diamond 2015-06-17 0:06 ` Emanuel Berg ` (3 more replies) 0 siblings, 4 replies; 32+ messages in thread From: Jim Diamond @ 2015-06-16 23:48 UTC (permalink / raw) To: help-gnu-emacs On 2015-06-14 at 08:31 ADT, Pascal J. Bourguignon <pjb@informatimago.com> wrote: > Marcin Borkowski <mbork@mbork.pl> writes: > >> Exactly. What I'm curious is how lexical scoping might make some tasks >> *connected to editing* easier/more natural. <snip> > Writing programs is easier and more natural with lexical scoping, IN > GENERAL! <snip> Really? Are there well-agreed-upon studies showing those things? Or are they your opinion? It strikes me that lexical scoping is easier to implement for compiled languages (that is an "off the cuff" comment from someone (me) with basic knowledge of compiler construction). But if lexical scoping is "more natural", is that because more people were "brought up" with lexically-scoped languages than dynamically-scoped languages? The first language I "learned" was lexically scoped. But the first language I used a lot was dynamically scoped. It seemed quite reasonable and natural to me at the time. A few versions of emacs ago something I was using went from dynamic scoping to lexical scoping. Working around that change was not trivial, casting suspicion on the universality of "easier". Cheers. Jim ^ permalink raw reply [flat|nested] 32+ messages in thread
* Re: Real-life examples of lexical binding in Emacs Lisp 2015-06-16 23:48 ` Jim Diamond @ 2015-06-17 0:06 ` Emanuel Berg 2015-06-17 6:23 ` Andreas Röhler [not found] ` <mailman.5136.1434522217.904.help-gnu-emacs@gnu.org> 2015-06-17 0:43 ` Pascal J. Bourguignon ` (2 subsequent siblings) 3 siblings, 2 replies; 32+ messages in thread From: Emanuel Berg @ 2015-06-17 0:06 UTC (permalink / raw) To: help-gnu-emacs Jim Diamond <Jim.Diamond@deletethis.AcadiaU.ca> writes: > Really? Are there well-agreed-upon studies showing > those things? Or are they your opinion? > > It strikes me that lexical scoping is easier to > implement for compiled languages (that is an "off > the cuff" comment from someone (me) with basic > knowledge of compiler construction). But if lexical > scoping is "more natural", is that because more > people were "brought up" with lexically-scoped > languages than dynamically-scoped languages? This discussion is much easier to have if that confusing terminology is dropped for a second and we instead study the simple example of a `let' form: (let ((scratch-buffer "*scratch*")) (when (bufferp scratch-buffer) (kill-buffer scratch-buffer) )) Here we have one piece of data which is used twice, so that data is named and when it is used it is indirectly refered to. In this example, what is natural to me? Answer: I don't expect `let' to affect any other code than the code in the `let' itself! And this is "lexical scoping". Is it really so, that you expect it to be in another way? If so - OK. I don't think most people feel like that and I certainly don't, because I don't program that way and the impression is made even stronger with the LISP syntax of enclosed lists. -- underground experts united http://user.it.uu.se/~embe8573 ^ permalink raw reply [flat|nested] 32+ messages in thread
* Re: Real-life examples of lexical binding in Emacs Lisp 2015-06-17 0:06 ` Emanuel Berg @ 2015-06-17 6:23 ` Andreas Röhler [not found] ` <mailman.5136.1434522217.904.help-gnu-emacs@gnu.org> 1 sibling, 0 replies; 32+ messages in thread From: Andreas Röhler @ 2015-06-17 6:23 UTC (permalink / raw) To: help-gnu-emacs Am 17.06.2015 um 02:06 schrieb Emanuel Berg: > Jim Diamond <Jim.Diamond@deletethis.AcadiaU.ca> > writes: > >> Really? Are there well-agreed-upon studies showing >> those things? Or are they your opinion? >> >> It strikes me that lexical scoping is easier to >> implement for compiled languages (that is an "off >> the cuff" comment from someone (me) with basic >> knowledge of compiler construction). But if lexical >> scoping is "more natural", is that because more >> people were "brought up" with lexically-scoped >> languages than dynamically-scoped languages? > This discussion is much easier to have if that > confusing terminology is dropped for a second and we > instead study the simple example of a `let' form: > > (let ((scratch-buffer "*scratch*")) > (when (bufferp scratch-buffer) > (kill-buffer scratch-buffer) )) > > Here we have one piece of data which is used twice, so > that data is named and when it is used it is > indirectly refered to. > > In this example, what is natural to me? Answer: > I don't expect `let' to affect any other code than the > code in the `let' itself! And this is "lexical > scoping". Nonetheless, that's the way Emacs acted all the time, while called "dynamically" scoped. Now with "lexical" we have instead an injection, if a function with same arguments' symbol is called inside let. Seems neither "lexical" nor "dynamic" express the real thing. ^ permalink raw reply [flat|nested] 32+ messages in thread
[parent not found: <mailman.5136.1434522217.904.help-gnu-emacs@gnu.org>]
* Re: Real-life examples of lexical binding in Emacs Lisp [not found] ` <mailman.5136.1434522217.904.help-gnu-emacs@gnu.org> @ 2015-06-17 10:49 ` Pascal J. Bourguignon 2015-06-17 10:53 ` Pascal J. Bourguignon 2015-06-17 20:33 ` Real-life examples of lexical binding in Emacs Lisp Emanuel Berg 1 sibling, 1 reply; 32+ messages in thread From: Pascal J. Bourguignon @ 2015-06-17 10:49 UTC (permalink / raw) To: help-gnu-emacs Andreas Röhler <andreas.roehler@easy-emacs.de> writes: > Am 17.06.2015 um 02:06 schrieb Emanuel Berg: >> Jim Diamond <Jim.Diamond@deletethis.AcadiaU.ca> >> writes: >> >>> Really? Are there well-agreed-upon studies showing >>> those things? Or are they your opinion? >>> >>> It strikes me that lexical scoping is easier to >>> implement for compiled languages (that is an "off >>> the cuff" comment from someone (me) with basic >>> knowledge of compiler construction). But if lexical >>> scoping is "more natural", is that because more >>> people were "brought up" with lexically-scoped >>> languages than dynamically-scoped languages? >> This discussion is much easier to have if that >> confusing terminology is dropped for a second and we >> instead study the simple example of a `let' form: >> >> (let ((scratch-buffer "*scratch*")) >> (when (bufferp scratch-buffer) >> (kill-buffer scratch-buffer) )) >> >> Here we have one piece of data which is used twice, so >> that data is named and when it is used it is >> indirectly refered to. >> >> In this example, what is natural to me? Answer: >> I don't expect `let' to affect any other code than the >> code in the `let' itself! And this is "lexical >> scoping". > > Nonetheless, that's the way Emacs acted all the time, while called > "dynamically" scoped. > > Now with "lexical" we have instead an injection, if a function with > same arguments' symbol is called inside let. > > Seems neither "lexical" nor "dynamic" express the real thing. To be more concrete, here is a case where something wrong happens: (setf lexical-binding nil) (defun do-something (arg) (format "\n%S\n" arg)) (defun some-function (arg) (setf scratch-buffer (get-buffer-create " *some-function scratch buffer*")) (with-current-buffer scratch-buffer (insert (do-something arg)))) (defun some-other-function () (with-current-buffer scratch-buffer (buffer-substring (point-min) (point-max)))) ;; and then in some unrelated code in a different file: (setq lexical-binding nil) (let ((scratch-buffer (get-buffer-create "*scratch*"))) (with-current-buffer scratch-buffer (insert "hello")) (some-function "Howdy?") (with-current-buffer scratch-buffer (buffer-substring (point-min) (point-max)))) --> " \"Howdy?\" \"Howdy?\" " ; instead of "hello" !!! On the other hand, if you use lexical binding: (setq lexical-binding t) (let ((scratch-buffer (get-buffer-create "*scratch*"))) (with-current-buffer scratch-buffer (insert "hello")) (some-function "Howdy?") (with-current-buffer scratch-buffer (buffer-substring-no-properties (point-min) (point-max)))) --> ";; This buffer is for notes you don't want to save, and for Lisp evaluation. ;; If you want to create a file, visit that file with C-x C-f, ;; then enter the text in that file's own buffer. hello" then this independent code stays independent and clean, and no other function may fuck it. -- __Pascal Bourguignon__ http://www.informatimago.com/ “The factory of the future will have only two employees, a man and a dog. The man will be there to feed the dog. The dog will be there to keep the man from touching the equipment.” -- Carl Bass CEO Autodesk ^ permalink raw reply [flat|nested] 32+ messages in thread
* Re: Real-life examples of lexical binding in Emacs Lisp 2015-06-17 10:49 ` Pascal J. Bourguignon @ 2015-06-17 10:53 ` Pascal J. Bourguignon 2015-06-17 14:42 ` Stefan Monnier 0 siblings, 1 reply; 32+ messages in thread From: Pascal J. Bourguignon @ 2015-06-17 10:53 UTC (permalink / raw) To: help-gnu-emacs "Pascal J. Bourguignon" <pjb@informatimago.com> writes: > ;; and then in some unrelated code in a different file: > > (setq lexical-binding nil) > (let ((scratch-buffer (get-buffer-create "*scratch*"))) > (with-current-buffer scratch-buffer (insert "hello")) > (some-function "Howdy?") > (with-current-buffer scratch-buffer > (buffer-substring (point-min) (point-max)))) Without lexical binding, to try to get some independence from other functions, you would have to PREFIX ALL THE LOCAL VARIABLES WITH FUNCTION SPECIFIC PREFIXES! (defun pjb-package--pjb-example-function () (let ((pjb-package--pjb-example-function--scratch-buffer (get-buffer-create "*scratch*"))) (with-current-buffer pjb-package--pjb-example-function--scratch-buffer (insert "hello")) (some-function "Howdy?") (with-current-buffer pjb-package--pjb-example-function--scratch-buffer (buffer-substring (point-min) (point-max))))) And this is only a convention that wouldn't prevent another-package--evil-function to modify pjb-package--pjb-example-function--scratch-buffer anyways. Now look at all the el code arround, and count how many local variables are named like this!!! -- __Pascal Bourguignon__ http://www.informatimago.com/ “The factory of the future will have only two employees, a man and a dog. The man will be there to feed the dog. The dog will be there to keep the man from touching the equipment.” -- Carl Bass CEO Autodesk ^ permalink raw reply [flat|nested] 32+ messages in thread
* Re: Real-life examples of lexical binding in Emacs Lisp 2015-06-17 10:53 ` Pascal J. Bourguignon @ 2015-06-17 14:42 ` Stefan Monnier 2015-06-17 16:19 ` Andreas Röhler ` (2 more replies) 0 siblings, 3 replies; 32+ messages in thread From: Stefan Monnier @ 2015-06-17 14:42 UTC (permalink / raw) To: help-gnu-emacs > Without lexical binding, to try to get some independence from other > functions, you would have to PREFIX ALL THE LOCAL VARIABLES WITH > FUNCTION SPECIFIC PREFIXES! Actually, not really. The Elisp convention to only use prefixes for global variables is 99% sufficient. In your example, the problem is that `some-function' modifies the (presumably global) variable `scratch-buffer' and that this variable does not have an appropriate prefix. The only case where non-prefixed local variables cause problem is when you introduce higher-order functions, as in: (defun my-map (f l) (if l (cons (funcall f (car l)) (my-map f (cdr l))))) (defun my-function (input) (let ((l ...)) (my-map (lambda (x) (unless (memq x l) (error "invalid mapping"))) input))) Suddenly the `l' used inside the lambda will not refer to the `l' nearby but to the `l' argument of `my-map'. For this reason, some higher-order functions used to use weird argument names to try and avoid such name capture. Nowadays they can use lexical scoping and hence choose their variable names sanely and without fear. Stefan ^ permalink raw reply [flat|nested] 32+ messages in thread
* Re: Real-life examples of lexical binding in Emacs Lisp 2015-06-17 14:42 ` Stefan Monnier @ 2015-06-17 16:19 ` Andreas Röhler 2015-06-17 19:30 ` Tassilo Horn [not found] ` <mailman.5171.1434557990.904.help-gnu-emacs@gnu.org> 2015-06-17 20:22 ` Emanuel Berg 2 siblings, 1 reply; 32+ messages in thread From: Andreas Röhler @ 2015-06-17 16:19 UTC (permalink / raw) To: help-gnu-emacs Am 17.06.2015 um 16:42 schrieb Stefan Monnier: >> Without lexical binding, to try to get some independence from other >> functions, you would have to PREFIX ALL THE LOCAL VARIABLES WITH >> FUNCTION SPECIFIC PREFIXES! > Actually, not really. The Elisp convention to only use prefixes for > global variables is 99% sufficient. In your example, the problem is > that `some-function' modifies the (presumably global) variable > `scratch-buffer' and that this variable does not have an > appropriate prefix. > > The only case where non-prefixed local variables cause problem is when > you introduce higher-order functions, as in: > > (defun my-map (f l) > (if l (cons (funcall f (car l)) (my-map f (cdr l))))) > > (defun my-function (input) > (let ((l ...)) > (my-map (lambda (x) (unless (memq x l) (error "invalid mapping"))) > input))) > > Suddenly the `l' used inside the lambda will not refer to the `l' nearby > but to the `l' argument of `my-map'. For this reason, some higher-order > functions used to use weird argument names to try and avoid such > name capture. Nowadays they can use lexical scoping and hence choose > their variable names sanely and without fear. > > Checked this with ;;; -*- lexical-binding: t; -*- (defun my-map (f l) (if l (cons (funcall f (car l)) (my-map f (cdr l))))) (defun my-function (input) (let ((l ())) (my-map (lambda (x) (unless (memq x l) (error "invalid mapping"))) input))) (my-function '(4 5)) Got identic results also without lexical-binding seen here. l is taken from inside lambda in both modes. ^ permalink raw reply [flat|nested] 32+ messages in thread
* Re: Real-life examples of lexical binding in Emacs Lisp 2015-06-17 16:19 ` Andreas Röhler @ 2015-06-17 19:30 ` Tassilo Horn 0 siblings, 0 replies; 32+ messages in thread From: Tassilo Horn @ 2015-06-17 19:30 UTC (permalink / raw) To: Andreas Röhler; +Cc: help-gnu-emacs Andreas Röhler <andreas.roehler@easy-emacs.de> writes: > ;;; -*- lexical-binding: t; -*- > > (defun my-map (f l) > (if l (cons (funcall f (car l)) (my-map f (cdr l))))) > > (defun my-function (input) > (let ((l ())) > (my-map (lambda (x) (unless (memq x l) (error "invalid mapping"))) > input))) > > (my-function '(4 5)) > > Got identic results also without lexical-binding seen here. l is > taken from inside lambda in both modes. You have to byte-compile. Then you get for the lexical version: --8<---------------cut here---------------start------------->8--- byte code for my-function: doc: ... args: 257 0 constant nil 1 constant my-map 2 constant make-byte-code 3 constant 257 4 constant "\211\300>?\205\n.\301\302!\207" 5 constant vconcat 6 constant vector 7 stack-ref 6 9 call 1 10 constant [error "invalid mapping"] 11 call 2 12 constant 3 13 constant "\n\n(fn X)" 14 call 5 15 stack-ref 3 16 call 2 17 return --8<---------------cut here---------------end--------------->8--- That gives: (my-function '(4 5)) => Lisp error: (error "invalid mapping") For the dynamic version: --8<---------------cut here---------------start------------->8--- byte code for my-function: args: (input) 0 constant nil 1 varbind l 2 constant my-map 3 constant <compiled-function> args: (x) 0 varref x 1 varref l 2 memq 3 not 4 goto-if-nil-else-pop 1 7 constant error 8 constant "invalid mapping" 9 call 1 10:1 return 4 varref input 5 call 2 6 unbind 1 7 return --8<---------------cut here---------------end--------------->8--- Note the varref l. When the lambda is called in the dynamic version, l will refer to the l argument from my-map. That gives: (my-function '(4 5)) => (nil nil) Bye, Tassilo ^ permalink raw reply [flat|nested] 32+ messages in thread
[parent not found: <mailman.5171.1434557990.904.help-gnu-emacs@gnu.org>]
* Re: Real-life examples of lexical binding in Emacs Lisp [not found] ` <mailman.5171.1434557990.904.help-gnu-emacs@gnu.org> @ 2015-06-17 17:12 ` Stefan Monnier 0 siblings, 0 replies; 32+ messages in thread From: Stefan Monnier @ 2015-06-17 17:12 UTC (permalink / raw) To: help-gnu-emacs > Got identical results also without lexical-binding seen here. You obviously botched the test for when lexical-binding is nil. My crystal ball tells me you just changed the ":t" to ":nil" without making sure this directive is re-evaluated (which happens when the file is opened). > l is taken from inside lambda in both modes. This doesn't make any sense: there is no `l' bound inside the lambda. Stefan ^ permalink raw reply [flat|nested] 32+ messages in thread
* Re: Real-life examples of lexical binding in Emacs Lisp 2015-06-17 14:42 ` Stefan Monnier 2015-06-17 16:19 ` Andreas Röhler [not found] ` <mailman.5171.1434557990.904.help-gnu-emacs@gnu.org> @ 2015-06-17 20:22 ` Emanuel Berg 2015-06-17 22:13 ` Pascal J. Bourguignon 2015-06-18 14:57 ` Udyant Wig 2 siblings, 2 replies; 32+ messages in thread From: Emanuel Berg @ 2015-06-17 20:22 UTC (permalink / raw) To: help-gnu-emacs Stefan Monnier <monnier@iro.umontreal.ca> writes: >> independence from other functions, you would have >> to PREFIX ALL THE LOCAL VARIABLES WITH FUNCTION >> SPECIFIC PREFIXES! > > Actually, not really. The Elisp convention to only > use prefixes for global variables is 99% sufficient. > In your example, the problem is that `some-function' > modifies the (presumably global) variable > `scratch-buffer' and that this variable does not > have an appropriate prefix. I'm curious, the techno-science books always speak of LISP as a language for "symbolic manipulation". Sometimes they mention AI. Anyone care to explain this? Does it somehow relate to the "dynamic scope"? Or is an implementation-derived situation, i.e. a practical measure somewhere along the way? > The only case where non-prefixed local variables > cause problem is when you introduce higher-order > functions, as in: > > (defun my-map (f l) (if l (cons (funcall f (car l)) > (my-map f (cdr l))))) > > (defun my-function (input) (let ((l ...)) (my-map > (lambda (x) (unless (memq x l) (error "invalid > mapping"))) input))) > > Suddenly the `l' used inside the lambda will not > refer to the `l' nearby but to the `l' argument of > `my-map'. For this reason, some higher-order > functions used to use weird argument names to try > and avoid such name capture. Nowadays they can use > lexical scoping and hence choose their variable > names sanely and without fear. And that is not only desired for that reason but also for "1-order functions" (? - i.e., a plebeian function with non-function arguments only) because then you can just name your variables whatever comes to mind - be it good or bad, you don't want to worry about the world outside that cozy form. It is the blue collar bottom up, contrary to the "top-down" (yuk!) hysteria of white collar hackers... I once read that "the programmer has the whole program in his head" (pseudo-quote). That's not how I experience it. I have some general knowledge of the entire program for sure, but the only thing I have 100% in my head is the function or even code block I'm currently typing. The dynamic scope breaks that zone of comfort, which here, is where you want to be. This "dynamic scope" as a method is like programming on acid with the ant queen communicating to her minions through telepathy telling them what to do all the time. "Lexical scope" is layed-back, having the ants do their work semi-autonomously, now and then interfering to solve a well-defined and delimited problem. ... Right? -- underground experts united http://user.it.uu.se/~embe8573 ^ permalink raw reply [flat|nested] 32+ messages in thread
* Re: Real-life examples of lexical binding in Emacs Lisp 2015-06-17 20:22 ` Emanuel Berg @ 2015-06-17 22:13 ` Pascal J. Bourguignon 2015-06-17 23:46 ` Emanuel Berg 2015-06-18 14:57 ` Udyant Wig 1 sibling, 1 reply; 32+ messages in thread From: Pascal J. Bourguignon @ 2015-06-17 22:13 UTC (permalink / raw) To: help-gnu-emacs Emanuel Berg <embe8573@student.uu.se> writes: > Stefan Monnier <monnier@iro.umontreal.ca> writes: > >>> independence from other functions, you would have >>> to PREFIX ALL THE LOCAL VARIABLES WITH FUNCTION >>> SPECIFIC PREFIXES! >> >> Actually, not really. The Elisp convention to only >> use prefixes for global variables is 99% sufficient. >> In your example, the problem is that `some-function' >> modifies the (presumably global) variable >> `scratch-buffer' and that this variable does not >> have an appropriate prefix. > > I'm curious, the techno-science books always speak of > LISP as a language for "symbolic manipulation". > Sometimes they mention AI. Anyone care to explain > this? This is because the stress the language puts on symbols and symbolic expressions (sexps) and the availability of operators to easily process them. Consider a simple function to derivate functions (it's about 100 lines of lisp code), allowing to do things like: (simplify (deriv-expr '(+ (* 3 x x) (* 9 x) 3) 'x)) --> (+ (* 6 x) 9) Or consider some natural language processing program, like eliza, or this expression generator: http://paste.lisp.org/+37QP In early eliza, the natural language words were represented using symbols (nowadays, lisp NLP programs would use strings for the representation of words, or even CLOS objects, but there would still be good arguments for the use of symbols with property lists in terms of simplicity and flexibility). Anyways, in expressions like: (defvar insults '( ("accapareur" (nm)) ("aérolithe" (nm)) ("amiral de bateaulavoir" (gnm)) ("anacoluthe" (nf)) ("analphabète" (n a)) ("athlète complet" (n)) ("boitsanssoif" (ni)) ("vieux" (a)) ;; … )) (defvar nm (remove-if-not (lambda (x) (intersection '(n np nm gnm) (second x))) insults)) (defvar nf (remove-if-not (lambda (x) (intersection '(nf np) (second x))) insults)) (defvar ad (remove-if-not (lambda (x) (member 'a (second x))) insults)) the use of symbols to denote the grammatical categories, and their manipulation to sort out the lexicon is very easy and natural. In lisp, it's easy to program something like that, because you don't need to do anything special to encode a symbol like x or nm. In other programming language, the stress is often on some other data type, like int in C (if you don't write a type when declaring a variable, which is possible in C, it is int by default!). And you will also have vectors instead of lists, so as soon as you write a collection of data, you will HAVE to use integers, to index into those vectors (in lisp when using lists, you don't need integers, just the functions first and rest). So in those non-lisp languages, you will have to invent a representation for these symbolic data, using integers (constants, or enums), or strings, (or even objects! in OO languages). And naturally you will have to encode the data using those vectors of integers (and what if you need to mix integers representing integers and integer representing symbols as in (+ (* 3 x x) (* 9 x) 3)? Dang! Now you need some more complex representtion, perhaps a structure or an object with variants for integers and symbols. And soon you're re-implementing a half-assed buggy lisp: you are greenspunning. A function to perform symbolic derivation was one of the first lisp programs written by John McCarthy, this was exactly the kind of application he had in mind for lisp; nowadays we have maxima :-) (And mathematica which is to maxima what ruby is to lisp). For an early symbolic application have a look at Wang's algorithm for propositional calculus: http://www.informatimago.com/develop/lisp/com/informatimago/small-cl-pgms/wang.html > Does it somehow relate to the "dynamic scope"? Not at all. Dynamic scope was just an implementation accident, because not enough about language design was know when lisp was invented. When you don't have theory, programs may just happen to behave a certain way depending on how they're implemented. This is what occured for lisp. McCarthy wanted to be able to define anonymous functions using Church's lambda notation, and it was implemented, but since we didn't have the language design theory about scopes and bindings, it just happened that dynamic binding as implemented, and then somebody remarked that this was a problem (the so called funarg problem), and they spent ten years developing the theory and practical solution with lexical binding. > Or is an implementation-derived situation, i.e. > a practical measure somewhere along the way? Yes. > I once read that "the programmer has the whole program > in his head" (pseudo-quote). That's not how > I experience it. I have some general knowledge of the > entire program for sure, but the only thing I have > 100% in my head is the function or even code block I'm > currently typing. The dynamic scope breaks that zone > of comfort, which here, is where you want to be. Of course. You could have the whole program in your head, when computers had 4 Kwords of memory, and the whole program was at most a ten-page listing. But nowadays programs are tens of megabytes of sources! (Firefox sources were more than 50 megabytes last time I checked; there are more than 50 MB; emacs are 51 MB compressed! $ ls -lh /usr/local/src/emacs-24.3.tar.gz -rw-r--r-- 1 pjb pjb 51M Dec 1 2013 /usr/local/src/emacs-24.3.tar.gz I've got more than 2.5 GIGA bytes of Common Lisp libraries sources! $ du -shc ~/quicklisp/dists/ 2.6G /home/pjb/quicklisp/dists/ Granted, this is not a single program, but a given program could use any subset of those libraries, so it is very important to ensure encapsulation, data hiding and locality of effects, and only lexical binding does that, not dynamic binding. > This "dynamic scope" as a method is like programming > on acid with the ant queen communicating to her > minions through telepathy telling them what to do all > the time. "Lexical scope" is layed-back, having the > ants do their work semi-autonomously, now and then > interfering to solve a well-defined and delimited > problem. ... Right? Indeed. A dynamic variable is global for the time of the dynamic scope. A lexical variable is local, for the space of the lexical scope. Notice time/space. This is important. Lexical means space, something that is statical and easily observable, eternal, with delimited contours. Dynamic means time, something that is dynamic, changing with time, and therefore more difficult to conceptualize and observe. We cannot "observe" time, we have to transform it into slowly moving mechanisms, so that we observe the SPACIAL position of the hands. Also, it's proven scientifically, that the brain constructs time perception in a non monotonous and linear way (check the experience, where we flash successive dots aligned on a screen at a given rythm, red dots on the left side, and green dot on the right side. People will tell you that the dots changed color right in the middle between the red and green dots, which is not possible, because they didn't know that the next dot would be green at the time the imaginary moving dot passed on this middle! So time is hard on us, and dynamic is difficult to reason about, and therefore it leads to more bugs. -- __Pascal Bourguignon__ http://www.informatimago.com/ “The factory of the future will have only two employees, a man and a dog. The man will be there to feed the dog. The dog will be there to keep the man from touching the equipment.” -- Carl Bass CEO Autodesk ^ permalink raw reply [flat|nested] 32+ messages in thread
* Re: Real-life examples of lexical binding in Emacs Lisp 2015-06-17 22:13 ` Pascal J. Bourguignon @ 2015-06-17 23:46 ` Emanuel Berg 0 siblings, 0 replies; 32+ messages in thread From: Emanuel Berg @ 2015-06-17 23:46 UTC (permalink / raw) To: help-gnu-emacs "Pascal J. Bourguignon" <pjb@informatimago.com> writes: > This is because the stress the language puts on > symbols and symbolic expressions (sexps) and the > availability of operators to easily process them ... Man, you should send this post to a magazine! -- underground experts united http://user.it.uu.se/~embe8573 ^ permalink raw reply [flat|nested] 32+ messages in thread
* Re: Real-life examples of lexical binding in Emacs Lisp 2015-06-17 20:22 ` Emanuel Berg 2015-06-17 22:13 ` Pascal J. Bourguignon @ 2015-06-18 14:57 ` Udyant Wig 2015-06-18 15:47 ` Emanuel Berg 1 sibling, 1 reply; 32+ messages in thread From: Udyant Wig @ 2015-06-18 14:57 UTC (permalink / raw) To: help-gnu-emacs Emanuel Berg <embe8573@student.uu.se> writes: > I'm curious, the techno-science books always speak of LISP as a > language for "symbolic manipulation". I really wish they'd get on with the times and start speaking of "Lisp" instead of "LISP". -- Udyant Wig GitHub: https://github.com/udyant Poetry: http://www.writing.com/main/profile/biography/frosthrone ^ permalink raw reply [flat|nested] 32+ messages in thread
* Re: Real-life examples of lexical binding in Emacs Lisp 2015-06-18 14:57 ` Udyant Wig @ 2015-06-18 15:47 ` Emanuel Berg 2015-06-19 13:49 ` Udyant Wig 0 siblings, 1 reply; 32+ messages in thread From: Emanuel Berg @ 2015-06-18 15:47 UTC (permalink / raw) To: help-gnu-emacs Udyant Wig <udyantw@gmail.com> writes: >> I'm curious, the techno-science books always speak >> of LISP as a language for "symbolic manipulation". > > I really wish they'd get on with the times and start > speaking of "Lisp" instead of "LISP". Is there an agreed-upon rule what is what? I use "LISP" in the context of the history and origin of the technology but I don't have a defined endpoint at what time history gives way to your everyday "Lisp". -- underground experts united http://user.it.uu.se/~embe8573 ^ permalink raw reply [flat|nested] 32+ messages in thread
* Re: Real-life examples of lexical binding in Emacs Lisp 2015-06-18 15:47 ` Emanuel Berg @ 2015-06-19 13:49 ` Udyant Wig 2015-06-19 17:41 ` acronymania (was: Re: Real-life examples of lexical binding in Emacs Lisp) Emanuel Berg 0 siblings, 1 reply; 32+ messages in thread From: Udyant Wig @ 2015-06-19 13:49 UTC (permalink / raw) To: help-gnu-emacs Emanuel Berg <embe8573@student.uu.se> writes: > I use "LISP" in the context of the history and origin > of the technology but I don't have a defined endpoint > at what time history gives way to your everyday > "Lisp". It seems to have been a byproduct of the general attitude that also made "UNIX" "Unix", "COBOL" "Cobol", "FORTH" "Forth", "EMACS" "Emacs", etc. -- Udyant Wig GitHub: https://github.com/udyant Poetry: http://www.writing.com/main/profile/biography/frosthrone ^ permalink raw reply [flat|nested] 32+ messages in thread
* acronymania (was: Re: Real-life examples of lexical binding in Emacs Lisp) 2015-06-19 13:49 ` Udyant Wig @ 2015-06-19 17:41 ` Emanuel Berg 2015-06-19 17:53 ` Rusi 0 siblings, 1 reply; 32+ messages in thread From: Emanuel Berg @ 2015-06-19 17:41 UTC (permalink / raw) To: help-gnu-emacs Udyant Wig <udyantw@gmail.com> writes: >> I use "LISP" in the context of the history and >> origin of the technology but I don't have a defined >> endpoint at what time history gives way to your >> everyday "Lisp". > > It seems to have been a byproduct of the general > attitude that also made "UNIX" "Unix", "COBOL" > "Cobol", "FORTH" "Forth", "EMACS" "Emacs", etc. UNIX, despite being uppercased, isn't an acronym but a pun/poke on Multics - which by the was *is* an acronym: Multiplexed Information and Computing Service Only "Multi" should be put within quotation marks as that part never worked out, which is where the fun begins. With UNIX/Unix the distinction is clearer (?) than with LISP/Lisp as UNIX is the trademark that is awarded/sold to (at that point) official implementations - and Unix is everything else. I consider GNU/Linux to be Unix tho some people insist it is UN*X, *nix, Unix-like, and so on. Hey, GNU is not Unix but that's exactly what it is. The "x" in Linux is a UNIX "x". The instigation to do Linux was in order to be able to use the university SunOS UNIX, only at home. It is Unix! COBOL is an acronym: Common Business-Oriented Language and like EMACS (acronym/abbreviation of "Editor MACroS") they have turned into names by now - simple as that, I suppose. FORTH isn't an acronym so one might as well make it a name with no regrets. All of those I would use as capitalized names, except for perhaps in some historical contexts - and to be sure, I never speak of Cobol and so Forth. -- underground experts united http://user.it.uu.se/~embe8573 ^ permalink raw reply [flat|nested] 32+ messages in thread
* Re: acronymania (was: Re: Real-life examples of lexical binding in Emacs Lisp) 2015-06-19 17:41 ` acronymania (was: Re: Real-life examples of lexical binding in Emacs Lisp) Emanuel Berg @ 2015-06-19 17:53 ` Rusi 0 siblings, 0 replies; 32+ messages in thread From: Rusi @ 2015-06-19 17:53 UTC (permalink / raw) To: help-gnu-emacs On Friday, June 19, 2015 at 11:04:53 PM UTC+5:30, Emanuel Berg wrote: > Udyant Wig writes: > > >> I use "LISP" in the context of the history and > >> origin of the technology but I don't have a defined > >> endpoint at what time history gives way to your > >> everyday "Lisp". > > > > It seems to have been a byproduct of the general > > attitude that also made "UNIX" "Unix", "COBOL" > > "Cobol", "FORTH" "Forth", "EMACS" "Emacs", etc. > > UNIX, despite being uppercased, isn't an acronym but > a pun/poke on Multics - which by the was *is* an > acronym: > > Multiplexed Information and Computing Service > > Only "Multi" should be put within quotation marks as > that part never worked out, which is where the > fun begins. > > With UNIX/Unix the distinction is clearer (?) than > with LISP/Lisp as UNIX is the trademark that is > awarded/sold to (at that point) official > implementations - and Unix is everything else. > > I consider GNU/Linux to be Unix tho some people insist > it is UN*X, *nix, Unix-like, and so on. Hey, GNU is > not Unix but that's exactly what it is. The "x" in > Linux is a UNIX "x". The instigation to do Linux was > in order to be able to use the university SunOS UNIX, > only at home. It is Unix! > > COBOL is an acronym: Common Business-Oriented Language > and like EMACS (acronym/abbreviation of > "Editor MACroS") they have turned into names by now - > simple as that, I suppose. > > FORTH isn't an acronym so one might as well make it > a name with no regrets. All of those I would use as > capitalized names, except for perhaps in some > historical contexts - and to be sure, I never speak of > Cobol and so Forth. Curiously, I wrote a blog-post recently on a functional programming timeline http://blog.languager.org/2015/04/cs-history-1.html in which I mentioned tangentially about the culture of lowercase starting with Unix. Someone felt strongly enough about the inaccuracies in this that he wrote me some longer-than-my-post emails about this. Since this has interesting historical titbits itself (and is too long for blogger's comments) its here: http://blog.languager.org/2015/06/richard-okeefes-responses-to-fp-timeline.html ^ permalink raw reply [flat|nested] 32+ messages in thread
* Re: Real-life examples of lexical binding in Emacs Lisp [not found] ` <mailman.5136.1434522217.904.help-gnu-emacs@gnu.org> 2015-06-17 10:49 ` Pascal J. Bourguignon @ 2015-06-17 20:33 ` Emanuel Berg 2015-06-17 22:07 ` Robert Thorpe 1 sibling, 1 reply; 32+ messages in thread From: Emanuel Berg @ 2015-06-17 20:33 UTC (permalink / raw) To: help-gnu-emacs Andreas Röhler <andreas.roehler@easy-emacs.de> writes: > Seems neither "lexical" nor "dynamic" express the > real thing. I take it "lexical" refers to you can make it out by looking at the code. "Dynamic" refers to it depends on the code and the program state in execution. I agree those terms are confusing. To me, it sounds like they refer to call-by-value vs. call-by-reference, which isn't so. I'd call it "normal scope" vs. "stacked scope", perhaps. > Nonetheless, that's the way Emacs acted all the > time, while called "dynamically" scoped. Well yeah, no one said it can't be done that way. I experience it as unnatural and consider it unpractical, but I'm not saying it cannot be done that way. The supreme techno-pope will beat his cardinals to the punch using anything, however typically he is using the *best* thing (that's why he is number one) and then the cardinals better do the same if they can less they are at an ever worse disadvantage. No one is telling you you can't use it or that it is inherently bad and always so. However tho a non-conformist myself I dare say here my intuition coincides with how most programmers will see it - be it by genes or upbringing. -- underground experts united http://user.it.uu.se/~embe8573 ^ permalink raw reply [flat|nested] 32+ messages in thread
* Re: Real-life examples of lexical binding in Emacs Lisp 2015-06-17 20:33 ` Real-life examples of lexical binding in Emacs Lisp Emanuel Berg @ 2015-06-17 22:07 ` Robert Thorpe 2015-06-17 22:17 ` Pascal J. Bourguignon 0 siblings, 1 reply; 32+ messages in thread From: Robert Thorpe @ 2015-06-17 22:07 UTC (permalink / raw) To: Emanuel Berg; +Cc: help-gnu-emacs Emanuel Berg <embe8573@student.uu.se> writes: > I take it "lexical" refers to you can make it out by > looking at the code. Yes. > "Dynamic" refers to it depends on the code and the > program state in execution. Yes. > I agree those terms are confusing. To me, it sounds > like they refer to call-by-value vs. > call-by-reference, which isn't so. > > I'd call it "normal scope" vs. > "stacked scope", perhaps. Both cases are usually implemented using stacks. Thinking about this helps understanding. In the lexical scope case we can think of one huge stack. Each entry in the stack can contain many elements. When execution enters a "let" form a new entry is created on the stack and the variables declared there are stored in that entry. They "shadow" other variables with the same name - they take precedence over them. When execution exits the let form that stack entry is deleted. This is usually how lexical scope is implement too. For dynamic scope we can think of each variable name as being associated with it's own stack. When execution reaches a let form a new value is pushed onto the stack for the relevant name. When the let form exits it's deleted from the top of the stack. Code always uses the top-of-stack value, so earlier let forms are shadowed by later ones. This is one way of implementing dynamic scope too, it's "shallow binding". I think it's how Elisp implements it. Dynamic scope was an accident of how Lisp was first written. See: http://www-formal.stanford.edu/jmc/history/lisp/node4.html The question of "extent" rather than "scope" brings up more problems. So does "deep" vs "shallow" binding with dynamic scope. BR, Robert Thorpe ^ permalink raw reply [flat|nested] 32+ messages in thread
* Re: Real-life examples of lexical binding in Emacs Lisp 2015-06-17 22:07 ` Robert Thorpe @ 2015-06-17 22:17 ` Pascal J. Bourguignon 0 siblings, 0 replies; 32+ messages in thread From: Pascal J. Bourguignon @ 2015-06-17 22:17 UTC (permalink / raw) To: help-gnu-emacs Robert Thorpe <rt@robertthorpeconsulting.com> writes: > Emanuel Berg <embe8573@student.uu.se> writes: >> I take it "lexical" refers to you can make it out by >> looking at the code. > > Yes. > >> "Dynamic" refers to it depends on the code and the >> program state in execution. > > Yes. > >> I agree those terms are confusing. To me, it sounds >> like they refer to call-by-value vs. >> call-by-reference, which isn't so. >> >> I'd call it "normal scope" vs. >> "stacked scope", perhaps. > > Both cases are usually implemented using stacks. Thinking about this > helps understanding. > > In the lexical scope case we can think of one huge stack. Each entry in > the stack can contain many elements. When execution enters a "let" form > a new entry is created on the stack and the variables declared there are > stored in that entry. They "shadow" other variables with the same name > - they take precedence over them. When execution exits the let form > that stack entry is deleted. This is usually how lexical scope is > implement too. However, contrarily to dynamic binding, lexical binding requires the use of the heap to implement non-delimited closures. This is why it was less obvious. -- __Pascal Bourguignon__ http://www.informatimago.com/ “The factory of the future will have only two employees, a man and a dog. The man will be there to feed the dog. The dog will be there to keep the man from touching the equipment.” -- Carl Bass CEO Autodesk ^ permalink raw reply [flat|nested] 32+ messages in thread
* Re: Real-life examples of lexical binding in Emacs Lisp 2015-06-16 23:48 ` Jim Diamond 2015-06-17 0:06 ` Emanuel Berg @ 2015-06-17 0:43 ` Pascal J. Bourguignon 2015-06-17 16:02 ` Phillip Lord [not found] ` <mailman.5167.1434556959.904.help-gnu-emacs@gnu.org> 3 siblings, 0 replies; 32+ messages in thread From: Pascal J. Bourguignon @ 2015-06-17 0:43 UTC (permalink / raw) To: help-gnu-emacs Jim Diamond <Jim.Diamond@deletethis.AcadiaU.ca> writes: > On 2015-06-14 at 08:31 ADT, Pascal J. Bourguignon <pjb@informatimago.com> wrote: >> Marcin Borkowski <mbork@mbork.pl> writes: >> >>> Exactly. What I'm curious is how lexical scoping might make some tasks >>> *connected to editing* easier/more natural. > > <snip> > >> Writing programs is easier and more natural with lexical scoping, IN >> GENERAL! > > <snip> > > Really? Are there well-agreed-upon studies showing those things? > Or are they your opinion? Yes, there are well-agreed-upon studies showing this. This is the reason ALL programming languages created since 1970, use lexical binding exclusively. > It strikes me that lexical scoping is easier to implement for compiled > languages (that is an "off the cuff" comment from someone (me) with > basic knowledge of compiler construction). But if lexical scoping is > "more natural", is that because more people were "brought up" with > lexically-scoped languages than dynamically-scoped languages? No, this is for theorical reasons, and in practice, because lexical scoping allows to understand the semantics of programs by just looking at the source, without executing it, and therefore make it easier on the programmers, and ease debugging and maintainance. > A few versions of emacs ago something I was using went from dynamic > scoping to lexical scoping. Working around that change was not > trivial, casting suspicion on the universality of "easier". The not trivial comes from the fact that it was wanted to perform the transition without rewriting all the existing elisp code, not only in the GNU emacs distribution, but also all the unpublished elisp code on the disks of all the users. Therefore, in emacs: 1- dynamic binding is still the default, 2- lexical binding is optional (you have to mark a file specially to get it). There may also be some technicalities with respect to the buffer-local variables which is an emacs specific complexity; I've not looked into it yet. Also, I would say that in emacs, given the number of hooks there are, lexical binding should demonstrate definite and overwhelming advantages over dynamic binding, since there is no closure with dynamic binding. For example, compare: (setq lexical-binding nil) (let ((message (read-from-minibuffer "Message: "))) (push (lambda () (insert message)) text-mode-hook)) [enter some text, type RET, then switch to *scratch* and:] M-x text-mode RET (pop text-mode-hook) with: (setq lexical-binding t) (let ((message (read-from-minibuffer "Message: "))) (push (lambda () (insert message)) text-mode-hook)) [enter some text, type RET, then switch to *scratch* and:] M-x text-mode RET (pop text-mode-hook) -- __Pascal Bourguignon__ http://www.informatimago.com/ “The factory of the future will have only two employees, a man and a dog. The man will be there to feed the dog. The dog will be there to keep the man from touching the equipment.” -- Carl Bass CEO Autodesk ^ permalink raw reply [flat|nested] 32+ messages in thread
* Re: Real-life examples of lexical binding in Emacs Lisp 2015-06-16 23:48 ` Jim Diamond 2015-06-17 0:06 ` Emanuel Berg 2015-06-17 0:43 ` Pascal J. Bourguignon @ 2015-06-17 16:02 ` Phillip Lord [not found] ` <mailman.5167.1434556959.904.help-gnu-emacs@gnu.org> 3 siblings, 0 replies; 32+ messages in thread From: Phillip Lord @ 2015-06-17 16:02 UTC (permalink / raw) To: Jim Diamond; +Cc: help-gnu-emacs Jim Diamond <Jim.Diamond@deletethis.AcadiaU.ca> writes: > The first language I "learned" was lexically scoped. But the first > language I used a lot was dynamically scoped. It seemed quite > reasonable and natural to me at the time. > > A few versions of emacs ago something I was using went from dynamic > scoping to lexical scoping. Working around that change was not > trivial, casting suspicion on the universality of "easier". You should write these problems up, with your solutions. Potentially useful to someone else, iff they have the same problems. Phil ^ permalink raw reply [flat|nested] 32+ messages in thread
[parent not found: <mailman.5167.1434556959.904.help-gnu-emacs@gnu.org>]
* Re: Real-life examples of lexical binding in Emacs Lisp [not found] ` <mailman.5167.1434556959.904.help-gnu-emacs@gnu.org> @ 2015-06-23 23:49 ` Jim Diamond 0 siblings, 0 replies; 32+ messages in thread From: Jim Diamond @ 2015-06-23 23:49 UTC (permalink / raw) To: help-gnu-emacs On 2015-06-17 at 13:02 ADT, Phillip Lord <phillip.lord@newcastle.ac.uk> wrote: > Jim Diamond <Jim.Diamond@deletethis.AcadiaU.ca> writes: >> The first language I "learned" was lexically scoped. But the first >> language I used a lot was dynamically scoped. It seemed quite >> reasonable and natural to me at the time. >> >> A few versions of emacs ago something I was using went from dynamic >> scoping to lexical scoping. Working around that change was not >> trivial, casting suspicion on the universality of "easier". > > > You should write these problems up, with your solutions. Potentially > useful to someone else, iff they have the same problems. Phil, It is quite a while ago now, and took me a while to dig up the details. Reviewing the solution, I see that it required a patch to a file which went from dynamic scoping to lexical scoping. Stefan Monnier was a huge help in getting this sorted out. Anyone interested in the particular issue and the particular solution can read the messages in the thread found at http://lists.gnu.org/archive/html/help-gnu-emacs/2012-06/msg00040.html It is not all that long. Cheers. Jim ^ permalink raw reply [flat|nested] 32+ messages in thread
[parent not found: <mailman.3950.1432974543.904.help-gnu-emacs@gnu.org>]
* Re: Real-life examples of lexical binding in Emacs Lisp [not found] ` <mailman.3950.1432974543.904.help-gnu-emacs@gnu.org> @ 2015-05-30 12:59 ` Pascal J. Bourguignon 2015-06-14 10:55 ` Marcin Borkowski [not found] ` <mailman.4977.1434279342.904.help-gnu-emacs@gnu.org> 0 siblings, 2 replies; 32+ messages in thread From: Pascal J. Bourguignon @ 2015-05-30 12:59 UTC (permalink / raw) To: help-gnu-emacs Tassilo Horn <tsdh@gnu.org> writes: > The emacs paper has a section explaining why emacs used dynamic binding > from the start: http://www.gnu.org/software/emacs/emacs-paper.html#SEC17 > > However, to me the two example use-cases only motivate why you want to > be able to use dynamic scoping for special variables (defvar), not > really for local variables (let) or function parameters, although the > first Edit Picture example explicitly speaks of binding command > arguments but I don't understand it. Indeed, in general, you want lexical binding for local variables. However, I would argue that for global variables, lexical binding would be useful too, even by default. In Common Lisp, we can implement global lexical variables, using eg. symbol macros, but in emacs lisp, we're missing operators for the global lexical case: dynamic lexical global defvar - local let(1) let(2) (1) when lexical-binding is nil or the variable has been defvar'ed. (2) when lexical-binding is t and the variable has not been defvar'ed. > But there are good use-cases for dynamic variables also in "normal" > programs. One example is to be able to bind some *error-handler* > dynamically in order to customize how to cope with errors that happen > far below the call stack. Definitely. https://groups.google.com/forum/#!original/comp.lang.lisp/oC5gDvn42pM/IudCXzCtxowJ -- __Pascal Bourguignon__ http://www.informatimago.com/ “The factory of the future will have only two employees, a man and a dog. The man will be there to feed the dog. The dog will be there to keep the man from touching the equipment.” -- Carl Bass CEO Autodesk ^ permalink raw reply [flat|nested] 32+ messages in thread
* Re: Real-life examples of lexical binding in Emacs Lisp 2015-05-30 12:59 ` Pascal J. Bourguignon @ 2015-06-14 10:55 ` Marcin Borkowski [not found] ` <mailman.4977.1434279342.904.help-gnu-emacs@gnu.org> 1 sibling, 0 replies; 32+ messages in thread From: Marcin Borkowski @ 2015-06-14 10:55 UTC (permalink / raw) To: help-gnu-emacs On 2015-05-30, at 14:59, Pascal J. Bourguignon <pjb@informatimago.com> wrote: > Tassilo Horn <tsdh@gnu.org> writes: > >> The emacs paper has a section explaining why emacs used dynamic binding >> from the start: http://www.gnu.org/software/emacs/emacs-paper.html#SEC17 >> >> However, to me the two example use-cases only motivate why you want to >> be able to use dynamic scoping for special variables (defvar), not >> really for local variables (let) or function parameters, although the >> first Edit Picture example explicitly speaks of binding command >> arguments but I don't understand it. > > Indeed, in general, you want lexical binding for local variables. > > However, I would argue that for global variables, lexical binding would > be useful too, even by default. > > In Common Lisp, we can implement global lexical variables, using > eg. symbol macros, but in emacs lisp, we're missing operators for the > global lexical case: > > dynamic lexical > global defvar - > local let(1) let(2) > > (1) when lexical-binding is nil or the variable has been defvar'ed. > (2) when lexical-binding is t and the variable has not been defvar'ed. > > >> But there are good use-cases for dynamic variables also in "normal" >> programs. One example is to be able to bind some *error-handler* >> dynamically in order to customize how to cope with errors that happen >> far below the call stack. > > Definitely. > > https://groups.google.com/forum/#!original/comp.lang.lisp/oC5gDvn42pM/IudCXzCtxowJ I'm sorry to say that I didn't understand that post. (Though I admit that I didn't try /very/ hard. I'll try harder again later.) Thanks anyway, -- Marcin Borkowski http://octd.wmi.amu.edu.pl/en/Marcin_Borkowski Faculty of Mathematics and Computer Science Adam Mickiewicz University ^ permalink raw reply [flat|nested] 32+ messages in thread
[parent not found: <mailman.4977.1434279342.904.help-gnu-emacs@gnu.org>]
* Re: Real-life examples of lexical binding in Emacs Lisp [not found] ` <mailman.4977.1434279342.904.help-gnu-emacs@gnu.org> @ 2015-06-14 20:04 ` Stefan Monnier 2015-06-14 21:44 ` Pascal J. Bourguignon 0 siblings, 1 reply; 32+ messages in thread From: Stefan Monnier @ 2015-06-14 20:04 UTC (permalink / raw) To: help-gnu-emacs >> However, I would argue that for global variables, lexical binding would >> be useful too, even by default. I'm not sure what that means. But you can set a global value to a variable without declaring it as dynamically scoped: (setq my-lex-var 3) Inside Emacs we also have a few global vars (e.g. `pi' and `argv') which we would want to declare with something like defvar for various reasons (providing a docstring, recording where is the declaration, etc...) yet we don't want them to be dynamically scoped. For `pi' we just used `setq', and for `argv' we used defvar followed by an ugly hack called internal-make-var-non-special. Stefan ^ permalink raw reply [flat|nested] 32+ messages in thread
* Re: Real-life examples of lexical binding in Emacs Lisp 2015-06-14 20:04 ` Stefan Monnier @ 2015-06-14 21:44 ` Pascal J. Bourguignon 2015-06-14 21:49 ` Pascal J. Bourguignon 0 siblings, 1 reply; 32+ messages in thread From: Pascal J. Bourguignon @ 2015-06-14 21:44 UTC (permalink / raw) To: help-gnu-emacs Stefan Monnier <monnier@iro.umontreal.ca> writes: >>> However, I would argue that for global variables, lexical binding would >>> be useful too, even by default. > > I'm not sure what that means. But you can set a global value to > a variable without declaring it as dynamically scoped: > > (setq my-lex-var 3) Wrong. Having a file lex.el: ------------------------------------------------------------------------ ;; -*- mode:emacs-lisp; lexical-binding:nil -*- (setq lexical? 33) (defun f () lexical?) (defun g () (let ((lexical? 42)) (f))) (print (g)) ------------------------------------------------------------------------ Then M-x load-file RET lex.el RET writes 42 in *Message* which shows that lexical? IS a dynamic variable! If it was lexical, we would get 33, because the lexical scope of the closure f is the global scope, where lexical? as been bound to 33, not the local dynamic scope of the function g when the variable lexical? is bound to 42. > Inside Emacs we also have a few global vars (e.g. `pi' and `argv') which > we would want to declare with something like defvar for various reasons > (providing a docstring, recording where is the declaration, etc...) yet > we don't want them to be dynamically scoped. > > For `pi' we just used `setq', and for `argv' we used defvar followed by > an ugly hack called internal-make-var-non-special. > > > Stefan -- __Pascal Bourguignon__ http://www.informatimago.com/ “The factory of the future will have only two employees, a man and a dog. The man will be there to feed the dog. The dog will be there to keep the man from touching the equipment.” -- Carl Bass CEO Autodesk ^ permalink raw reply [flat|nested] 32+ messages in thread
* Re: Real-life examples of lexical binding in Emacs Lisp 2015-06-14 21:44 ` Pascal J. Bourguignon @ 2015-06-14 21:49 ` Pascal J. Bourguignon 0 siblings, 0 replies; 32+ messages in thread From: Pascal J. Bourguignon @ 2015-06-14 21:49 UTC (permalink / raw) To: help-gnu-emacs "Pascal J. Bourguignon" <pjb@informatimago.com> writes: > Stefan Monnier <monnier@iro.umontreal.ca> writes: > >>>> However, I would argue that for global variables, lexical binding would >>>> be useful too, even by default. >> >> I'm not sure what that means. But you can set a global value to >> a variable without declaring it as dynamically scoped: >> >> (setq my-lex-var 3) > > Wrong. Not. > Having a file lex.el: > ------------------------------------------------------------------------ > ;; -*- mode:emacs-lisp; lexical-binding:nil -*- > > (setq lexical? 33) > (defun f () > lexical?) > (defun g () > (let ((lexical? 42)) > (f))) > > (print (g)) > ------------------------------------------------------------------------ > > Then M-x load-file RET lex.el RET writes 42 in *Message* which shows > that lexical? IS a dynamic variable! If it was lexical, we would get > 33, because the lexical scope of the closure f is the global scope, > where lexical? as been bound to 33, not the local dynamic scope of the > function g when the variable lexical? is bound to 42. Oops, sorry, I intended to run two tests. With lexical-binding:t indeed, setq defines the global variable and leaves it lexical. Reloading the file with lexical-binding:t even suppresses the dynamic aspect of a previously defined (with defvar) dynamic variable. -- __Pascal Bourguignon__ http://www.informatimago.com/ “The factory of the future will have only two employees, a man and a dog. The man will be there to feed the dog. The dog will be there to keep the man from touching the equipment.” -- Carl Bass CEO Autodesk ^ permalink raw reply [flat|nested] 32+ messages in thread
end of thread, other threads:[~2015-06-23 23:49 UTC | newest] Thread overview: 32+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2015-05-29 8:28 Real-life examples of lexical binding in Emacs Lisp Marcin Borkowski 2015-05-30 8:28 ` Tassilo Horn 2015-06-14 10:52 ` Marcin Borkowski [not found] ` <mailman.4976.1434279182.904.help-gnu-emacs@gnu.org> 2015-06-14 11:31 ` Pascal J. Bourguignon 2015-06-16 23:48 ` Jim Diamond 2015-06-17 0:06 ` Emanuel Berg 2015-06-17 6:23 ` Andreas Röhler [not found] ` <mailman.5136.1434522217.904.help-gnu-emacs@gnu.org> 2015-06-17 10:49 ` Pascal J. Bourguignon 2015-06-17 10:53 ` Pascal J. Bourguignon 2015-06-17 14:42 ` Stefan Monnier 2015-06-17 16:19 ` Andreas Röhler 2015-06-17 19:30 ` Tassilo Horn [not found] ` <mailman.5171.1434557990.904.help-gnu-emacs@gnu.org> 2015-06-17 17:12 ` Stefan Monnier 2015-06-17 20:22 ` Emanuel Berg 2015-06-17 22:13 ` Pascal J. Bourguignon 2015-06-17 23:46 ` Emanuel Berg 2015-06-18 14:57 ` Udyant Wig 2015-06-18 15:47 ` Emanuel Berg 2015-06-19 13:49 ` Udyant Wig 2015-06-19 17:41 ` acronymania (was: Re: Real-life examples of lexical binding in Emacs Lisp) Emanuel Berg 2015-06-19 17:53 ` Rusi 2015-06-17 20:33 ` Real-life examples of lexical binding in Emacs Lisp Emanuel Berg 2015-06-17 22:07 ` Robert Thorpe 2015-06-17 22:17 ` Pascal J. Bourguignon 2015-06-17 0:43 ` Pascal J. Bourguignon 2015-06-17 16:02 ` Phillip Lord [not found] ` <mailman.5167.1434556959.904.help-gnu-emacs@gnu.org> 2015-06-23 23:49 ` Jim Diamond [not found] ` <mailman.3950.1432974543.904.help-gnu-emacs@gnu.org> 2015-05-30 12:59 ` Pascal J. Bourguignon 2015-06-14 10:55 ` Marcin Borkowski [not found] ` <mailman.4977.1434279342.904.help-gnu-emacs@gnu.org> 2015-06-14 20:04 ` Stefan Monnier 2015-06-14 21:44 ` Pascal J. Bourguignon 2015-06-14 21:49 ` Pascal J. Bourguignon
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.