The fate of reduce() in Python 3000

Link

Guido van Rossum comments on the elimination of map(), filter(), reduce() and lambda from Python 3000:

About 12 years ago, Python aquired lambda, reduce(), filter() and map(), courtesy of (I believe) a Lisp hacker who missed them and submitted working patches. But, despite of the PR value, I think these features should be cut from Python 3000.

He believes map and filter are unnecessary because there are list comprehensions. But what about reduce ? It seems Guido doesn't believe in folds:

So now reduce(). This is actually the one I've always hated most, because, apart from a few examples involving + or *, almost every time I see a reduce() call with a non-trivial function argument, I need to grab pen and paper to diagram what's actually being fed into that function before I understand what the reduce() is supposed to do. So in my mind, the applicability of reduce() is pretty much limited to associative operators, and in all other cases it's better to write out the accumulation loop explicitly.

And then, with these functions gone, there is no use for lambdas, he argues.

I find it positive, in general, when designers eliminate features from a programming languages, if they are rarely used, but maybe he is being too harsh on reduce(); it may be my predilection for functional programming getting on the way, though.

via PLNews

Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.

Learning through meta-programming

When I find myself worring about what Common Lisp's REDUCE actually does, I write myself a formal function:

(defun formal-function (x y)
  (list 'f x y))
This allows me to try it out at the REPL
CL-USER> (reduce #'formal-function
                 '(x y z))
(F (F X Y) Z)
That helps but Common Lisp's reduce has keyword arguments, :from-end and :initial-value. What do they do? What does :from-end default to if the programmer omits it? One could sit at the REPL and try them out, or you could type in a form that does it for you.
CL-USER> (dolist (direction '(nil (:from-end t) (:from-end nil)))
           (dolist (initial-value '(nil (:initial-value 0)))
             (let ((form (append `(reduce #'formal-function '(1 2 3))
                                 direction
                                 initial-value)))
               (format t "~&~S~%=> ~S~%if F = cons => ~S~2%"
                       form
                       (eval form)
                       (eval `(flet ((f (x y)(cons x y)))
                               ,(eval form)))))))
(REDUCE #'FORMAL-FUNCTION '(1 2 3))
=> (F (F 1 2) 3)
if F = cons => ((1 . 2) . 3)

(REDUCE #'FORMAL-FUNCTION '(1 2 3) :INITIAL-VALUE 0)
=> (F (F (F 0 1) 2) 3)
if F = cons => (((0 . 1) . 2) . 3)

(REDUCE #'FORMAL-FUNCTION '(1 2 3) :FROM-END T)
=> (F 1 (F 2 3))
if F = cons => (1 2 . 3)

(REDUCE #'FORMAL-FUNCTION '(1 2 3) :FROM-END T :INITIAL-VALUE 0)
=> (F 1 (F 2 (F 3 0)))
if F = cons => (1 2 3 . 0)

(REDUCE #'FORMAL-FUNCTION '(1 2 3) :FROM-END NIL)
=> (F (F 1 2) 3)
if F = cons => ((1 . 2) . 3)

(REDUCE #'FORMAL-FUNCTION '(1 2 3) :FROM-END NIL :INITIAL-VALUE 0)
=> (F (F (F 0 1) 2) 3)
if F = cons => (((0 . 1) . 2) . 3)

NIL
If you conceive the code your are trying to write as a variant on copying a list you can quickly see that you need to take
CL-USER> (reduce #'cons '(a b c) :from-end t :initial-value nil)
(A B C)
as your starting point.

I think that this brings up three issues for the programming language designer to consider

First, confining your languages reduce to a limited set of approved, easy functions stops the apprentice programmer from using a formal function to see what it does.

Second, program writing programs are directly useful in understanding reduce. I use reduce with a formal function to get (f (f 2 3)) and if I am uncertain of the implications of what I am seeing I can evaluate (f (f 2 3)) with f bound to a function of interest to me.

The concern about reduce is that it is hard to understand. The context for that debate is assumptions about the resources that the apprentice programmer has available to him to help him study the language. A language designer might omit meta-programming from his language. A educator might schedule meta-programming as the final, esoteric initiation, too late to assist in understanding other language constructs, or omit it from his curriculum entirely.

My concern is that the difficulties of reduce might be an artifact of that context. If apprentice programmers were taught meta-programming, not for immediate use, but as a learning aid, then other language constructs might be easier to learn in this context. Meta-programming provides the opportunity to test out variations on hard language constructs, a fresh perspective on language syntax, and a source of exercises which are about the language being studied rather than a toy problem in a domain that might be unfamiliar to the student.

Is there a domino effect here? Python lacks meta-programming, so it is not available as an aid to studying the language. This makes it harder to learn Python, which forces hard constructs to be dropped as being too difficult to learn