From mboxrd@z Thu Jan 1 00:00:00 1970 Path: news.gmane.org!not-for-mail From: pjb@informatimago.com (Pascal J. Bourguignon) Newsgroups: gmane.emacs.help Subject: Re: questioning let Date: Wed, 24 Feb 2010 12:59:22 +0100 Organization: Informatimago Message-ID: <873a0qyhd1.fsf@galatea.lan.informatimago.com> References: NNTP-Posting-Host: lo.gmane.org Mime-Version: 1.0 Content-Type: text/plain; charset=us-ascii X-Trace: dough.gmane.org 1267015281 845 80.91.229.12 (24 Feb 2010 12:41:21 GMT) X-Complaints-To: usenet@dough.gmane.org NNTP-Posting-Date: Wed, 24 Feb 2010 12:41:21 +0000 (UTC) To: help-gnu-emacs@gnu.org Original-X-From: help-gnu-emacs-bounces+geh-help-gnu-emacs=m.gmane.org@gnu.org Wed Feb 24 13:41:16 2010 Return-path: Envelope-to: geh-help-gnu-emacs@m.gmane.org Original-Received: from lists.gnu.org ([199.232.76.165]) by lo.gmane.org with esmtp (Exim 4.69) (envelope-from ) id 1NkGYD-0000yk-Bj for geh-help-gnu-emacs@m.gmane.org; Wed, 24 Feb 2010 13:41:13 +0100 Original-Received: from localhost ([127.0.0.1]:53533 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1NkGYC-0005qa-4j for geh-help-gnu-emacs@m.gmane.org; Wed, 24 Feb 2010 07:41:12 -0500 Original-Path: news.stanford.edu!usenet.stanford.edu!news.tele.dk!news.tele.dk!small.news.tele.dk!fu-berlin.de!uni-berlin.de!individual.net!not-for-mail Original-Newsgroups: gnu.emacs.help Original-Lines: 99 Original-X-Trace: individual.net d/ztVEzpkvV+jCdFrTEC8AuAJA8SEyqlEuLIcqWZcpDRdxm2SF Cancel-Lock: sha1:NjI3YjljNDc0MGE1NDUyYWJkZGVlMmEyODkyNjZmMjA3MzJkN2FiOQ== sha1:yuuLEmkAqTyeIbYuMppeyrbgog4= Face: iVBORw0KGgoAAAANSUhEUgAAADAAAAAwAQMAAABtzGvEAAAABlBMVEUAAAD///+l2Z/dAAAA oElEQVR4nK3OsRHCMAwF0O8YQufUNIQRGIAja9CxSA55AxZgFO4coMgYrEDDQZWPIlNAjwq9 033pbOBPtbXuB6PKNBn5gZkhGa86Z4x2wE67O+06WxGD/HCOGR0deY3f9Ijwwt7rNGNf6Oac l/GuZTF1wFGKiYYHKSFAkjIo1b6sCYS1sVmFhhhahKQssRjRT90ITWUk6vvK3RsPGs+M1RuR mV+hO/VvFAAAAABJRU5ErkJggg== X-Accept-Language: fr, es, en X-Disabled: X-No-Archive: no User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/23.1 (darwin) Original-Xref: news.stanford.edu gnu.emacs.help:177062 X-BeenThere: help-gnu-emacs@gnu.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: Users list for the GNU Emacs text editor List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Original-Sender: help-gnu-emacs-bounces+geh-help-gnu-emacs=m.gmane.org@gnu.org Errors-To: help-gnu-emacs-bounces+geh-help-gnu-emacs=m.gmane.org@gnu.org Xref: news.gmane.org gmane.emacs.help:72098 Archived-At: Andreas Roehler 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__