* Re: questioning let [not found] <mailman.1779.1267007568.14305.help-gnu-emacs@gnu.org> @ 2010-02-24 11:36 ` David Kastrup 2010-02-24 17:29 ` Andreas Röhler [not found] ` <mailman.1812.1267032434.14305.help-gnu-emacs@gnu.org> 2010-02-24 11:59 ` Pascal J. Bourguignon 2010-02-24 21:36 ` Tim X 2 siblings, 2 replies; 9+ messages in thread From: David Kastrup @ 2010-02-24 11:36 UTC (permalink / raw) To: help-gnu-emacs Andreas Roehler <andreas.roehler@online.de> writes: > Hi, > > behaviour of the example code below puzzles me. Would > expect setting of arg by external function, but inside > `let', recognised. But remains `1'. > > (defun arg-setting () > (interactive) > (let ((arg 1)) > (message "%s" arg) > (arg-extern arg) > (message "%s" arg))) > > (defun arg-extern (arg) > (setq arg (1- arg))) > > Any help? The argument binding in arg-extern is the innermost one and consequently the only affected one. If you make the function argument-less, it will likely work as expected by you, affecting the binding in arg-setting. -- David Kastrup ^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: questioning let 2010-02-24 11:36 ` questioning let David Kastrup @ 2010-02-24 17:29 ` Andreas Röhler [not found] ` <mailman.1812.1267032434.14305.help-gnu-emacs@gnu.org> 1 sibling, 0 replies; 9+ messages in thread From: Andreas Röhler @ 2010-02-24 17:29 UTC (permalink / raw) To: help-gnu-emacs David Kastrup wrote: > Andreas Roehler <andreas.roehler@online.de> writes: > >> Hi, >> >> behaviour of the example code below puzzles me. Would >> expect setting of arg by external function, but inside >> `let', recognised. But remains `1'. >> >> (defun arg-setting () >> (interactive) >> (let ((arg 1)) >> (message "%s" arg) >> (arg-extern arg) >> (message "%s" arg))) >> >> (defun arg-extern (arg) >> (setq arg (1- arg))) >> >> Any help? > > The argument binding in arg-extern is the innermost one and consequently > the only affected one. If you make the function argument-less, it will > likely work as expected by you, affecting the binding in arg-setting. > That works, thanks a lot! However, stored in some eil.el, get a compiler warning than: In arg-extern: eil.el:9:9:Warning: reference to free variable `arg' eil.el:9:17:Warning: assignment to free variable `arg' Would think a useless warning, as the compiler should know being inside a let (?) Andreas ^ permalink raw reply [flat|nested] 9+ messages in thread
[parent not found: <mailman.1812.1267032434.14305.help-gnu-emacs@gnu.org>]
* Re: questioning let [not found] ` <mailman.1812.1267032434.14305.help-gnu-emacs@gnu.org> @ 2010-02-24 18:10 ` David Kastrup 2010-02-24 21:53 ` Tim X 2010-02-24 23:41 ` Pascal J. Bourguignon 2 siblings, 0 replies; 9+ messages in thread From: David Kastrup @ 2010-02-24 18:10 UTC (permalink / raw) To: help-gnu-emacs Andreas Röhler <andreas.roehler@easy-emacs.de> writes: > David Kastrup wrote: >> Andreas Roehler <andreas.roehler@online.de> writes: >> >>> behaviour of the example code below puzzles me. Would >>> expect setting of arg by external function, but inside >>> `let', recognised. But remains `1'. >>> >>> (defun arg-setting () >>> (interactive) >>> (let ((arg 1)) >>> (message "%s" arg) >>> (arg-extern arg) >>> (message "%s" arg))) >>> >>> (defun arg-extern (arg) >>> (setq arg (1- arg))) >>> >>> Any help? >> >> The argument binding in arg-extern is the innermost one and consequently >> the only affected one. If you make the function argument-less, it will >> likely work as expected by you, affecting the binding in arg-setting. > > That works, thanks a lot! > However, stored in some eil.el, get a compiler warning than: > > > In arg-extern: > eil.el:9:9:Warning: reference to free variable `arg' > eil.el:9:17:Warning: assignment to free variable `arg' > > Would think a useless warning, as the compiler should know being inside a let (?) The warning is completely accurate since arg-extern can be called from outside arg-setting, in which case it will assign to a global variable called "arg". Whether or not some let-binding might be effective at the point of calling arg-extern is unknown to the compiler. In a Lisp variant with lexical binding (like Common Lisp or Scheme), arg-extern has no way to fiddle with the let-binding of arg-setting: it is completely inaccessible by name outside of arg-setting itself. -- David Kastrup ^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: questioning let [not found] ` <mailman.1812.1267032434.14305.help-gnu-emacs@gnu.org> 2010-02-24 18:10 ` David Kastrup @ 2010-02-24 21:53 ` Tim X 2010-02-24 23:41 ` Pascal J. Bourguignon 2 siblings, 0 replies; 9+ messages in thread From: Tim X @ 2010-02-24 21:53 UTC (permalink / raw) To: help-gnu-emacs Andreas Röhler <andreas.roehler@easy-emacs.de> writes: > David Kastrup wrote: >> Andreas Roehler <andreas.roehler@online.de> writes: >> >>> Hi, >>> >>> behaviour of the example code below puzzles me. Would >>> expect setting of arg by external function, but inside >>> `let', recognised. But remains `1'. >>> >>> (defun arg-setting () >>> (interactive) >>> (let ((arg 1)) >>> (message "%s" arg) >>> (arg-extern arg) >>> (message "%s" arg))) >>> >>> (defun arg-extern (arg) >>> (setq arg (1- arg))) >>> >>> Any help? >> >> The argument binding in arg-extern is the innermost one and consequently >> the only affected one. If you make the function argument-less, it will >> likely work as expected by you, affecting the binding in arg-setting. >> > > > That works, thanks a lot! > However, stored in some eil.el, get a compiler warning than: > > > In arg-extern: > eil.el:9:9:Warning: reference to free variable `arg' > eil.el:9:17:Warning: assignment to free variable `arg' > > Would think a useless warning, as the compiler should know being inside a let (?) > The compiler cannot know that this function will always be called in such a way. All it knows is that at its time of definition, it is setting an argument it doesn't know anything about. > The point to note is that in a defun argument list, that argument list is essentially an implicit let. The 'arg' referenced inside your original arg-extern is not the same as the arg being referenced in the first function. this is why I suggest you change the argument name in the arg-extern function as this will make that distinction obvious. To get the value set in arg-extern returned to its caller, you would do something like (setq arg (arg-extern arg)) Tim -- tcross (at) rapttech dot com dot au ^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: questioning let [not found] ` <mailman.1812.1267032434.14305.help-gnu-emacs@gnu.org> 2010-02-24 18:10 ` David Kastrup 2010-02-24 21:53 ` Tim X @ 2010-02-24 23:41 ` Pascal J. Bourguignon 2 siblings, 0 replies; 9+ messages in thread From: Pascal J. Bourguignon @ 2010-02-24 23:41 UTC (permalink / raw) To: help-gnu-emacs Andreas Röhler <andreas.roehler@easy-emacs.de> writes: > David Kastrup wrote: >> Andreas Roehler <andreas.roehler@online.de> writes: >> >>> Hi, >>> >>> behaviour of the example code below puzzles me. Would >>> expect setting of arg by external function, but inside >>> `let', recognised. But remains `1'. >>> >>> (defun arg-setting () >>> (interactive) >>> (let ((arg 1)) >>> (message "%s" arg) >>> (arg-extern arg) >>> (message "%s" arg))) >>> >>> (defun arg-extern (arg) >>> (setq arg (1- arg))) >>> >>> Any help? >> >> The argument binding in arg-extern is the innermost one and consequently >> the only affected one. If you make the function argument-less, it will >> likely work as expected by you, affecting the binding in arg-setting. >> > > > That works, thanks a lot! > However, stored in some eil.el, get a compiler warning than: > > > In arg-extern: > eil.el:9:9:Warning: reference to free variable `arg' > eil.el:9:17:Warning: assignment to free variable `arg' > > Would think a useless warning, as the compiler should know being inside a let (?) Yes, as I said, this is something that you shoudl avoid, and the compiler is of the same opinion. -- __Pascal Bourguignon__ ^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: questioning let [not found] <mailman.1779.1267007568.14305.help-gnu-emacs@gnu.org> 2010-02-24 11:36 ` questioning let David Kastrup @ 2010-02-24 11:59 ` Pascal J. Bourguignon 2010-02-24 17:44 ` Andreas Röhler 2010-02-24 21:36 ` Tim X 2 siblings, 1 reply; 9+ messages in thread From: Pascal J. Bourguignon @ 2010-02-24 11:59 UTC (permalink / raw) To: help-gnu-emacs Andreas Roehler <andreas.roehler@online.de> writes: > Hi, > > behaviour of the example code below puzzles me. Would > expect setting of arg by external function, but inside > `let', recognised. But remains `1'. > > (defun arg-setting () > (interactive) > (let ((arg 1)) > (message "%s" arg) > (arg-extern arg) > (message "%s" arg))) > > (defun arg-extern (arg) > (setq arg (1- arg))) > > Any help? let is equivalent to lambda: (let ((a 1) (b 2)) (list a b)) <=> ((lambda (a b) (list a b)) 1 2) defun is binding a lambda to a function cell: (defun f (a b) (list a b)) <=> (setf (symbol-function 'f) (lambda (a b) (list a b))) Therefore you can see that calling a function defined by defun is a let in disguise. If you transformed your code following these equivalences, you would notice that you have actually TWO variables named arg, one as parameter of the function arg-extern, and one as variable in the let in arg-setting. The setq in arg-extern will modify only the variable parameter of arg-extern. Because they have the same name, this variable hides the one defined in the let of arg-setting. There's no way to access it from within arg-extern. If they had a different name, you could modify a variable from an outer dynamic scope from an inner dynamic scope, because in emacs all the variables are dynamic. But it is considered very bad form to do so: this is a big side effect, and what's more, one that depends on the call chain. You should avoid side effects, to increase the readability and debugability of your code. Therefore you should avoid setq and setf. Try to write pure function, never try to modify a variable. One way to write your code would be: (defun do-what-you-need-to-do-with (arg) ) (defun arg-binding () (interactive) (let ((arg 1)) (message "before arg = %s" arg) (let ((arg (arg-extern arg))) (message "after arg = %s" arg) (do-what-you-need-to-do-with arg)) (message "original arg = %s" arg))) (defun arg-extern (arg) (message "arg-extern before arg = %s" arg) (message "arg-extern returns = %s" (1- arg)) (1- arg)) before arg = 1 arg-extern before arg = 1 arg-extern returns = 0 after arg = 0 original arg = 1 If you need a global variable (perhaps because you need to keep some data across command invocations), the I would advise to distringuish it from the other by giving it a name surrounded by stars: *var*. Then, it will have a different name, and won't be shadowed (inadvertantly) by inner lets, defuns or lambdas. (defvar *var* 42) (defun arg-extern (arg) (message "arg-extern before arg = %s" arg) (setf *var* (1- arg)) (message "arg-extern returns = %s" *var*) *var*) (arg-binding) *var* --> 0 -- __Pascal Bourguignon__ ^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: questioning let 2010-02-24 11:59 ` Pascal J. Bourguignon @ 2010-02-24 17:44 ` Andreas Röhler 0 siblings, 0 replies; 9+ messages in thread From: Andreas Röhler @ 2010-02-24 17:44 UTC (permalink / raw) To: help-gnu-emacs Pascal J. Bourguignon wrote: > Andreas Roehler <andreas.roehler@online.de> writes: > >> Hi, >> >> behaviour of the example code below puzzles me. Would >> expect setting of arg by external function, but inside >> `let', recognised. But remains `1'. >> >> (defun arg-setting () >> (interactive) >> (let ((arg 1)) >> (message "%s" arg) >> (arg-extern arg) >> (message "%s" arg))) >> >> (defun arg-extern (arg) >> (setq arg (1- arg))) >> >> Any help? > > > let is equivalent to lambda: > > (let ((a 1) (b 2)) (list a b)) <=> ((lambda (a b) (list a b)) 1 2) > > defun is binding a lambda to a function cell: > > (defun f (a b) (list a b)) > <=> (setf (symbol-function 'f) (lambda (a b) (list a b))) > > Therefore you can see that calling a function defined by defun is a let > in disguise. > > > If you transformed your code following these equivalences, you would > notice that you have actually TWO variables named arg, one as parameter > of the function arg-extern, and one as variable in the let in > arg-setting. > > The setq in arg-extern will modify only the variable parameter of > arg-extern. Because they have the same name, this variable hides the > one defined in the let of arg-setting. There's no way to access it from > within arg-extern. > > > If they had a different name, you could modify a variable from an outer > dynamic scope from an inner dynamic scope, because in emacs all the > variables are dynamic. But it is considered very bad form to do so: > this is a big side effect, and what's more, one that depends on the call > chain. You should avoid side effects, to increase the readability and > debugability of your code. Therefore you should avoid setq and setf. > Try to write pure function, never try to modify a variable. > > One way to write your code would be: > > (defun do-what-you-need-to-do-with (arg) > ) > > (defun arg-binding () > (interactive) > (let ((arg 1)) > (message "before arg = %s" arg) > (let ((arg (arg-extern arg))) > (message "after arg = %s" arg) > (do-what-you-need-to-do-with arg)) > (message "original arg = %s" arg))) > > (defun arg-extern (arg) > (message "arg-extern before arg = %s" arg) > (message "arg-extern returns = %s" (1- arg)) > (1- arg)) > > before arg = 1 > arg-extern before arg = 1 > arg-extern returns = 0 > after arg = 0 > original arg = 1 > > > If you need a global variable (perhaps because you need to keep some > data across command invocations), the I would advise to distringuish it > from the other by giving it a name surrounded by stars: *var*. Then, it > will have a different name, and won't be shadowed (inadvertantly) by > inner lets, defuns or lambdas. > > (defvar *var* 42) > > (defun arg-extern (arg) > (message "arg-extern before arg = %s" arg) > (setf *var* (1- arg)) > (message "arg-extern returns = %s" *var*) > *var*) > > (arg-binding) > *var* --> 0 > > Hi Pascal, thanks a lot for these helpful instructions. Next days it should go here: http://repo.or.cz/w/elbb.git Andreas BTW every Emacs hacker is invited recording it's stuff there It's about playing with git too... ^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: questioning let [not found] <mailman.1779.1267007568.14305.help-gnu-emacs@gnu.org> 2010-02-24 11:36 ` questioning let David Kastrup 2010-02-24 11:59 ` Pascal J. Bourguignon @ 2010-02-24 21:36 ` Tim X 2 siblings, 0 replies; 9+ messages in thread From: Tim X @ 2010-02-24 21:36 UTC (permalink / raw) To: help-gnu-emacs Andreas Roehler <andreas.roehler@online.de> writes: > Hi, > > behaviour of the example code below puzzles me. Would > expect setting of arg by external function, but inside > `let', recognised. But remains `1'. > > (defun arg-setting () > (interactive) > (let ((arg 1)) > (message "%s" arg) > (arg-extern arg) > (message "%s" arg))) > > (defun arg-extern (arg) > (setq arg (1- arg))) > > Any help? > > Thanks > > I think if you put a (message ....) statement inside arg-extern and pring it out, you will see what is happening. Maybe even change the name of the parameter of arg-extern as this is probably leading to your confusion and will clarify things. Tim > -- tcross (at) rapttech dot com dot au ^ permalink raw reply [flat|nested] 9+ messages in thread
* questioning let @ 2010-02-24 10:34 Andreas Roehler 0 siblings, 0 replies; 9+ messages in thread From: Andreas Roehler @ 2010-02-24 10:34 UTC (permalink / raw) To: help-gnu-emacs Hi, behaviour of the example code below puzzles me. Would expect setting of arg by external function, but inside `let', recognised. But remains `1'. (defun arg-setting () (interactive) (let ((arg 1)) (message "%s" arg) (arg-extern arg) (message "%s" arg))) (defun arg-extern (arg) (setq arg (1- arg))) Any help? Thanks Andreas -- https://code.launchpad.net/~a-roehler/python-mode https://code.launchpad.net/s-x-emacs-werkstatt/ ^ permalink raw reply [flat|nested] 9+ messages in thread
end of thread, other threads:[~2010-02-24 23:41 UTC | newest] Thread overview: 9+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- [not found] <mailman.1779.1267007568.14305.help-gnu-emacs@gnu.org> 2010-02-24 11:36 ` questioning let David Kastrup 2010-02-24 17:29 ` Andreas Röhler [not found] ` <mailman.1812.1267032434.14305.help-gnu-emacs@gnu.org> 2010-02-24 18:10 ` David Kastrup 2010-02-24 21:53 ` Tim X 2010-02-24 23:41 ` Pascal J. Bourguignon 2010-02-24 11:59 ` Pascal J. Bourguignon 2010-02-24 17:44 ` Andreas Röhler 2010-02-24 21:36 ` Tim X 2010-02-24 10:34 Andreas Roehler
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.