[Python-ideas] Ruby-style Blocks in Python Idea

Guido van Rossum guido at python.org
Wed Mar 11 15:26:29 CET 2009


On Tue, Mar 10, 2009 at 10:05 PM, Stephen J. Turnbull
<stephen at xemacs.org> wrote:
> Guido van Rossum writes:
>
>  > I'm feeling really dense right now -- I still don't see the difference
>  > between the two. Are you saying that you would prefer an expression
>  > that creates a *named* function? That seems to be really bizarre --
>  > like claiming that you don't like expressions that return anonymous
>  > numbers.
>
> Here's a use-case from Emacs.  Various modes have callbacks so that
> users can customize them.  A typical case is that a text-mode hook
> will turn on auto-fill-mode, which is documented as an example to be
> done like this:
>
> (add-hook 'text-mode-hook (lambda () (auto-fill-mode 1)))
>
> where *-mode functions called with nil toggle the mode, positive
> numbers turn it on, and non-positive numbers turn it off.  The
> add-hook function is supposed to be idempotent: it won't add the same
> hook function if it is already in the hook.  The problem is if you
> change the lambda and execute that form, the changed lambda is now not
> identical to the lambda on the hook, so the old version won't be
> removed.  This
>
> (add-hook 'text-mode-hook (defun turn-on-auto-fill () (auto-fill-mode 1)))
>
> neatly avoids the problem by returning the name of the function, the
> symbol `turn-on-auto-fill', which is callable and so suitable for
> hanging on the hook.  If you change the definition and execute the
> above form, add-hook *mutates nothing* (the symbol is already
> present), but because the hook is indirect through the function's
> symbol and the defun *is* executed, the definition changes ... which
> is exactly what you want.[1]

Got it -- sort of like using assignment in an expression in C, to set
a variable and return the valule (but not quite, don't worry :-).

> AMK's use-case could be post-processed as something like

I assume you're talking about Andrew Koenig's use case -- ANK is
Andrew Kuchling, who AFAIK didn't participate in this thread. :-)

> (let ((i 0))
>  (mapcar (lambda ()
>            (let ((name (intern (format "foo-%d-callback" i))))
>              (define-function name (aref slots i))
>              (aset slots i name)
>              (setq i (1+ i))
>              name))
>          slots))

IIUC (my Lisp is very rusty) this just assigns unique names to the
functions right? You're saying this to satisfy the people who insist
that __name__ is always useful right? But it seems to be marginally
useful here since the names don't occur in the source. (?)

> where slots is the vector of anonymous functions.  Providing names in
> this way costs one indirection per callback invocation in Emacs Lisp,
> but the benefits in readability of tracebacks are large, especially
> for compiled code.
>
>  > I don't see the conceptual difference between a "def-expression" (if
>  > it were syntactically possible) and a lambda-expression. What is the
>  > difference in your view? Are you sure that difference exists? (It
>  > wouldn't be the first time that people ascribe powers to lambda that
>  > it doesn't have. :-)
>
> AIUI, a def-expression binds a callable to an object, while a lambda
> expression returns a callable.  An anonymous def is just lambda by a
> different name (and I think the code block proponents agree, based on
> their willingness to accept syntax using def instead of lambda).
>
> I don't see how the kind of thing exemplified above would be useful in
> Python, and from a parallel reply I just saw, I gather Jim agrees.
> The point is to show how a function-defining expression can be useful
> in some contexts.  This works in Emacs Lisp because in
>
> (setq foo (lambda ...))
>
> tools (including the Lisp interpreter) will not recognize foo as a
> function identifier although its value is a function, while
>
> (defun foo ...)
>
> marks foo as a function identifier.  But in Python (like Scheme)
> they're basically the same operation, with a little syntactic sugar.
> Anything that is based on the separation of variable namespace from
> function namespace is DOA, right?

Right, and so are separations between value and type namespaces (as
other languages use, e.g. C++ and Haskell).

> The renaming mapper is a different issue, I think; it depends on
> computing object names at runtime (ie, the Lisp `intern' operation),
> not on separate namespaces.  I'm not sure offhand how to do that in
> Python, or even it it's possible; I've never wanted it.

You can assign new values to to f.__name__.

> Footnotes:
> [1]  N.B.  Of course modern Emacsen define turn-on-auto-fill as a
> standard function.  But this is ugly (because of the single flat
> namespace of Emacs Lisp), and not all modes have their turn-on,
> turn-off variants.  auto-fill-mode was chosen because (a) the
> semantics are easy to imagine and (b) the use of lambda in a hook is
> explained by exactly this example in the Emacs Lisp Manual.

-- 
--Guido van Rossum (home page: http://www.python.org/~guido/)



More information about the Python-ideas mailing list