Ruby and Python
Alex Martelli
aleaxit at yahoo.com
Mon Nov 20 04:23:56 EST 2000
"graham" <graham73 at telocity.com> wrote in message
news:B63D9C65.17342%graham73 at telocity.com...
> Alex Martelli
> > [on functions]
> > They're treated exactly like every other object, and thus
> > are first-class.
>
> It's fine if you want to go on believing that Python has first class
> functions, but the fact that you have to manually form closures for
> functions means that they are not first class in the accepted (and
> admittedly informal) definition of "first class". Ocaml, Haskell, etc
Here's an "accepted definition of first-class", from a typical
(and, incidentally, quite usable) Scheme course:
http://www.cs.odu.edu/~zeil/cs355/Handouts/schemedoc/schemedoc/node13.html
"""
In Scheme, as in most dialects of Lisp, functions are first-class. This
means that they are values, just like any other data type--they may be
passed as arguments to functions and returned as values of functions.
"""
*Are values like any other data type -- may be passed as arguments and
returned as values*. THIS is the typical "accepted, admittedly informal"
definition.
Similarly, take a typical introduction to functional programming, at
http://cs.wwc.edu/~aabyan/221_2/PLBOOK/Functions.html:
"LISP ... in 1958 ... provided for recursion, first-class functions ...
dynamic rather than static scope rules". Gist of the quote: LISP in
the 1958 version is said to provide first-class functions, although
it lacks any static scoping but provides dynamic scoping instead.
Not all authors agree on this (that early LISP provided first-class
functions), but it does appear to be the most-widespread opinion
about this issue.
Taking Charles Elkan's lectures at
http://www-cse.ucsd.edu/graduate/Comps/vogt/proglang/elkan.lectures:
"""
In a nutshell, at "definition time", when an abstraction is evaluated
to give a "function value":
- under static scoping the function value is a closure
which saves the current environment
- under dynamic scoping, only the abstraction expression is saved.
"""
we see that Python is far closer to what Elkan defines as 'static
scoping' -- it just doesn't (currently) define "the current
environment" to include any NESTING (lexical or otherwise).
Of course, Elkan's explicit definition of "first-class" is:
"""
FIRST-CLASS VALUES
Defn: A value is first-class if it can be used in all contexts
where other values can be used, in particular:
- as a literal value
- as part of a larger value
- as a function argument
- as a function result
"""
Are you disputing that THIS is what a value "being first-class"
means? And/or are you disputing that function-objects in Python
meet this definition? Besides the arguments/results parts, they
can surely be used 'as part of a larger value' (a tuple, or list,
or dictionary, ...), and as literals too, e.g.:
atuple = (1, "2", 3.0, lambda x: 4+x, 5+0j, 6L, [7], (8,), {9:10})
This 'larger value' (a 9-elements tuple) uses as its "parts"
various literals of different 'first-class' Python types --
each with its own, different syntax -- the fourth one being
a function.
"All contexts" in Elkan's definition needs to be taken _in
context_, of course, -- e.g.,
atuple[i] + 7
is OK for i in (0,2,4,5), but not otherwise -- that doesn't
mean strings, functions, lists, tuples, and dictionaries
aren't first-class, just that "addition of 7" is not defined
for these particular types, while it is for integers, floats,
complex and longs. Just trying to forestall some cavils...:-).
> all have first class functions in the accepted meaning.
>
> I am not criticising Python on this issue. All I am saying is that
> to go around saying Python has first class functions is misleading,
No, it's just applying the common-or-garden definition. A function
is first-class, but it's (currently) not a (nested) lexical closure.
It's not in issue of criticism of praise, but one of precision in
the use of words.
Is the following idiom familiar at all...?
(defun make-adder (n)
(lexical-let ((n n))
(function (lambda (m) (+ n m)))))
The result of make-adder isn't any less 'first-class' because an
explicit lexical-let was needed to make it into a lexical-closure,
in a Lisp dialect that otherwise binds dynamically. This is not
a _defense_ of dynamical binding (nor of Python's current, limited
form of statical binding) -- just a *terminological clarification*.
Humpty-Dumpty-ish use of words is not correct or acceptable on
a public technical forum, in my opinion.
> particulary when comparing Python with other languagees, as the
> original author did with Ruby. If you want to say that "Python has
> first class functions, except that you have to manually form closures",
> that's fine, but that's not the same as "having first class functions".
You don't *have* to 'form closures' at all -- you form them if
and when you feel a need for them. This issue has no bearing
on 'first-classness' of functions, and it would therefore be
totally inappropriate to tag it in an "exception clause" to
an assertion about said first-classness -- as if it was somehow
a LIMITATION of the first-classness aspect, when it just isn't.
It would be like saying something like, e.g., 'Python has first
class unlimited-precision integers (bignums), except that you
have to syntactically denote them with a trailing L'. The lack
of, e.g., Smalltalk-ish implicit conversion between fixnums and
bignums may be a plus or a minus, but it has nothing to do with
the *first-classness* of such numbers, and it wold be misleading
to imply or assert it does.
Alex
More information about the Python-list
mailing list