unofficial mirror of help-gnu-emacs@gnu.org
 help / color / mirror / Atom feed
* 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

* 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
       [not found] <mailman.1779.1267007568.14305.help-gnu-emacs@gnu.org>
  2010-02-24 11:36 ` 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:36 ` 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

* 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.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.1779.1267007568.14305.help-gnu-emacs@gnu.org>
  2010-02-24 11:36 ` 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

* 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

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 --
2010-02-24 10:34 questioning let Andreas Roehler
     [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 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

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).