A critic of Guido's blog on Python's lambda

Duane Rettig duane at franz.com
Sat May 13 03:55:12 EDT 2006


Alexander Schmolck <a.schmolck at gmail.com> writes:

> I think that in most contexts lexical transparency is desirable so that
> deviations from lexical transparency ought to be well motivated. I also
> believe that a construct that is usually used to establish a lexically
> transparent binding shouldn't be equally used for dynamic bindings so that it
> isn't syntactically obvious what's going on. I've already provided some
> reasons why CL's design wrt. binding special and lexical variables seems bad
> to me. I don't think these reasons were terribly forceful but as I'm not aware
> of any strong motivation why the current behaviour would be useful I'm
> currently considering it a minor wart.
>
> To make things more concrete: What would be the downside of, instead of doing
> something like:
>
> (let ((*x* ...)) [(declare (special *x*))] ...) ; where [X] denotes maybe X

Let's start with this.  You seem to be saying that the above construct is inferior
to the alternatives you are about to suggest.  Why?  And since you are adding
an optional form, let's break it down into its separate situations:

1. (let ((*x* ...)) (declare (special *x*)) ...)

Here there is no question about the specialness of *x*; it is textually
obvious what the binding is - that it is not a lexical binding but a special
binding.

2. (let ((*x* ...)) ...)

[where there is no special declaration for *x* within the form]

Here, the issue is that it is not obvious that *x* is special (in this case,
it would have to already be a dynamic variable (what we internally call
"globally special"), because a special declaration within a lexical context
does not affect inner bindings.  Perhaps this form is the one you are really
having trouble with.

> doing any of the below:
>
> a) using a different construct e.g. (fluid-let ((*x* ...)) ...) for binding
>    special variables

Unless you also _remove_ the #2 case above, this seems no diferent than writing
a macro for the #1 case, above.

> b) having to use *...* (or some other syntax) for special variables

In fact, the spec does suggest precisely this (see
http://www.franz.com/support/documentation/8.0/ansicl/dictentr/defparam.htm,
in the Notes section), and to the extent that programmers obey the suggestion,
the textual prompting is present in the name.

> c) using (let ((q (special *x*) (,a ,b , at c)) (values 1 2 '(3 4 5 6)))
>               (list q ((lambda () (incf *x*))) a b c)) ; => (1 3 3 4 (5 6))
>
> (It's getting late, but hopefully this makes some vague sense)

Well, sort of; this seems simply like a sometimes-fluid-let, whose syntax could
easily be established by a macro (with destructurings whose form is (special X)
could be specially [sic] treated.

Now if in the above example you would have trouble with (a) and/or (c)
based on the absence of a "lexical" declaration (i.e. one that would undo
the effect of a globally special declaration), thus guaranteeing that a
fluid-let or a "sometimes-fluid-let" would work, you should know that while
I was working on the Environments Access module I theorized and demonstrated
that such a declaration could be easily done within a conforming Common Lisp.
I leave you with that demonstration here (though it really is only for
demonstration purposes only; I don't necessarily propose that CL should add
a lexical declaration to the language):

[This only works on Allegro CL 8.0]:

CL-USER(1): (defvar pie pi)
PIE
CL-USER(2): (compile (defun circ (rad) (* pie rad rad)))
CIRC
NIL
NIL
CL-USER(3): (circ 10)
314.1592653589793d0
CL-USER(4): (compile (defun foo (x) (let ((pie 22/7)) (circ x))))
FOO
NIL
NIL
CL-USER(5): (foo 10)
2200/7
CL-USER(6): (float *)
314.2857
CL-USER(7): (sys:define-declaration sys::lexical (&rest vars)
  nil
  :variable
  (lambda (declaration env)
    (declare (ignore env))
    (let* ((spec '(lexical t))
	   (res (mapcar #'(lambda (x) (cons x spec))
			(cdr declaration))))
      (values :variable res))))
SYSTEM::LEXICAL
CL-USER(8): (compile (defun foo (x) (let ((pie 22/7)) (declare (sys::lexical pie)) (circ x))))
; While compiling FOO:
Warning: Variable PIE is never used.
FOO
T
NIL
CL-USER(9): (foo 10)
314.1592653589793d0
CL-USER(10): 

-- 
Duane Rettig    duane at franz.com    Franz Inc.  http://www.franz.com/
555 12th St., Suite 1450               http://www.555citycenter.com/
Oakland, Ca. 94607        Phone: (510) 452-2000; Fax: (510) 452-0182   



More information about the Python-list mailing list