Velocity Reviews > Would Anonymous Functions Help in Learning Programming/Python?

# Would Anonymous Functions Help in Learning Programming/Python?

Paul Rubin
Guest
Posts: n/a

 09-22-2007
Bryan Olson <(E-Mail Removed)> writes:
> http://www.velocityreviews.com/forums/(E-Mail Removed) wrote:
> > There are already anonymous functions in Python.
> > lambda x, y, z: x + y + z
> > is the same as:
> > def _(x, y, z): return x + y + z

>
> They are the same only in special cases:
> The special identifier "_" is used in the interactive
> interpreter to store the result of the last evaluation...

I'm not sure what Chris was really getting at, since among other
things lambda:... is an expression while def... is a statement.
But Python certainly has anonymous functions without lambda:

def compose(f,g):
def h(*a, **k):
return f(g(*a, **k))
return h

x = compose(math.sin, math.cos)(1.0)

computes sin(cos(1.0)) where a function equivalent to
lambda x: sin(cos(x))
is constructed and used without being bound to a symbol.

Bryan Olson
Guest
Posts: n/a

 09-22-2007
Cristian wrote:
> [...] Specifically, he's having trouble
> thinking of functions as first order data (don't worry, I haven't
> confused him with such terminology yet).

[...]
> And, after we finally
> get a hold of first order functions, we appreciate its incorporation
> into languages. It would be a shame if my friend just learns the
> motions and never incorporates first order functions into his
> programs.

The terminology I've heard for this is that functions are
"first-class values". There's a minor name-collision on
"class", but people have heard "first-class" in other
contexts, and it means the same thing here: no second-class
status for such values.

"First order" has other usages, some contradicting what you
mean. First-order functions are exactly those that cannot
take functions as arguments. It would be a shame if your
friend never incorporates *higher order* functions.
[http://en.wikipedia.org/wiki/Higher-order_function]

[...]
> my_function = function(foo, bar): pass
> an_instance_method = function(self, foo): pass
> a_method_declaration = method(self, foo): pass

I just argued for adopting mainstream terminology, but here
I like yours better. The keyword "lambda" sucks. All the
other keywords, having been so carefully chosen to relate
to their conversational usage, have mis-trained to look
at this spelling-out of the name of an arbitrary symbol.

Alonzo Church's calculus used the *symbol*. He just needed
it to be distinct. Could as well have been the '\$-calculus'.

Function-as-value is not a trivial concept. I remember
wrestling with it, and I've seen many others do the same.
The 'lambda' keyword is so awful as to pass for deep
mystery long after students have grasped first-class
functions.

"function" would be a much better keyword. Or follow ML and
abbreviate to "fn", or choose another term that clues one
in to the meaning. I'd have caught on much quicker given a

lambda x, y: x + y

as: "the function of two variables, call them x and y, that
returns x + y."

--Bryan

Bryan Olson
Guest
Posts: n/a

 09-22-2007
Paul Rubin wrote:
> Bryan Olson <(E-Mail Removed)> writes:
>> (E-Mail Removed) wrote:
>>> There are already anonymous functions in Python.
>>> lambda x, y, z: x + y + z
>>> is the same as:
>>> def _(x, y, z): return x + y + z

>> They are the same only in special cases:
>> The special identifier "_" is used in the interactive
>> interpreter to store the result of the last evaluation...

>
> I'm not sure what Chris was really getting at,

I was big-time unsure. At first, I thought Chris's latter
form to be equivalent to a pass statement. I've long used
the Python convention of assigning throw-away values to '_',
and I was under the mistaken impression Python defined _

When I looked it up, I was surprised to find that my
understanding of the _ variable was wrong, and shocked that
there really is an interesting context where Chris's claim
has a strong case.

> since among other
> things lambda:... is an expression while def... is a statement.

True fact, but note that one form of statement is an expression.

> But Python certainly has anonymous functions without lambda:
>
> def compose(f,g):
> def h(*a, **k):
> return f(g(*a, **k))
> return h
>
> x = compose(math.sin, math.cos)(1.0)
> computes sin(cos(1.0)) where a function equivalent to
> lambda x: sin(cos(x))
> is constructed and used without being bound to a symbol.

How anonymous is that function when we can see that its name is 'h'?

import math

f = compose(math.sin, math.cos)
print f.__name__

Am I making a bogus argument? Kind of. Most authors of "anonymous"
works do in fact have real names. The term really means that they
entered the context at issue dissociated from their given name.
Nevertheless, def is never a real anonymous function constructor.

If our concern is Python's suitability for studying principles of
programming, I think I'm on stronger ground. Python is great for
getting things done. It is easy to learn in the sense of learning
to to use if for practical tasks. Python's actual semantics are not
as neat and clean as some other languages.

--
--Bryan

Paul Rubin
Guest
Posts: n/a

 09-22-2007
Bryan Olson <(E-Mail Removed)> writes:
> How anonymous is that function when we can see that its name is 'h'?

h is out of scope after compose returns, so the function is anonymous
in the sense that there is no symbol bound to the function, through
which you can refer to it.

> import math
>
> f = compose(math.sin, math.cos)
> print f.__name__

I prefer to think of __name__ as just some debugging info stuck inside
the closure, though actually Python is introspective enough to be able
to let you locate and call a function whose __name__ is "h". Of
course there might be more than one:

f = compose(math.sin, math.cos)
g = compose(math.sqrt, math.tan)
print f.__name__, g.__name__

> Nevertheless, def is never a real anonymous function constructor.

Well, def constructs a function with a name, but the function can stay
around after the name goes away, after which I'd say the function is
nameless. One could otherwise say that (lambda x: x+x) is not
anonymous either, since id(lambda ...) is a unique label stuck to it
like a __name__.

> If our concern is Python's suitability for studying principles of
> programming, I think I'm on stronger ground. Python is great for
> getting things done. It is easy to learn in the sense of learning
> to to use if for practical tasks. Python's actual semantics are not
> as neat and clean as some other languages.

Fair enough.

Erik Max Francis
Guest
Posts: n/a

 09-22-2007
Kay Schluehr wrote:

> I checked out Io once and I disliked it. I expected Io's prototype OO
> being just a more flexible variant of class based OO but Io couples a
> prototype very closely to its offspring. When A produces B and A.f is
> modified after production of B also B.f is modified. A controls the
> state of B during the whole lifetime of B. I think parents shall not
> do this, not in real life and also not in programming language
> semantics.

It sounds like you're talking about some language other than Io, or
didn't delve deeply enough into it, since Io makes no such requirements.

The attribute and method (not made distinct in Io; they're called
"slots") is much the same as with Python; the current instance is
checked for the object, then its parents, then _its_ parents, and so on.

--
Erik Max Francis && (E-Mail Removed) && http://www.alcyone.com/max/
San Jose, CA, USA && 37 20 N 121 53 W && AIM, Y!M erikmaxfrancis
No man quite believes in any other man.
-- H.L. Mencken

Steven D'Aprano
Guest
Posts: n/a

 09-23-2007
On Sat, 22 Sep 2007 14:09:13 -0700, Paul Rubin wrote:

>> Nevertheless, def is never a real anonymous function constructor.

>
> Well, def constructs a function with a name, but the function can stay
> around after the name goes away, after which I'd say the function is
> nameless. One could otherwise say that (lambda x: x+x) is not anonymous
> either, since id(lambda ...) is a unique label stuck to it like a
> __name__.

If you want to be tediously pedantic, lambda doesn't construct anonymous
functions either: you can bind them to a name, and whether you do or not,
they have a name.

>>> f = lambda: 3
>>> f.__name__

'<lambda>'

It's just that all functions created by lambda share the same name.

If you really want an anonymous function...

>>> def foo():

.... return 3
....
>>> foo.__name__ = ''
>>> foo

<function at 0x97a26bc>

I know, I know, I'm being tediously pedantic... and that's not what the
anonymity of lambda refers to. What it actually means is that the lambda
doesn't create a name in a namespace. In that regard, calling a factory
function is also anonymous, because the function isn't added to the
calling code's namespace.

Or, to put it another way...

def factory():
def foo():
return 3
return foo

Within factory(), foo() is not an anonymous function, because 'foo' is in
the local namespace. But the result of factory() is anonymous in the same
sense that lambda is: although the function object has a attribute
__name__ set to 'foo', calling factory() doesn't modify the caller's
namespace (unless you assign the result to a name).

--
Steven.

Kay Schluehr
Guest
Posts: n/a

 09-23-2007
On 22 Sep., 23:17, Erik Max Francis <(E-Mail Removed)> wrote:

> The attribute and method (not made distinct in Io; they're called
> "slots") is much the same as with Python; the current instance is
> checked for the object, then its parents, then _its_ parents, and so on.

Repeating the same point as Marc doesn't mean that I have to repeat my

Guest
Posts: n/a

 09-23-2007

Scott David Daniels wrote:
>>
>> Scott David Daniels wrote:
>>> Cristian wrote:
>>>> On Sep 21, 3:44 pm, Ron Adam <(E-Mail Removed)> wrote:
>>>>
>>>>> I think key may be to discuss names and name binding with your friend.
>>> Here's an idea:
>>>
>>> import math
>>>
>>> def sin_integral(start, finish, dx): ...
>>> def cos_integral(start, finish, dx): ...
>>> generalize and separate the integration technique from the
>>> function it integrates.

>> It's based on the apple basic program example in How to Enjoy Calculus.
>> Ron
>>
>> import math
>> def integrate(fn, x1, x2, n=100):...
>> def fn(x): ...
>> print "Area of fn:", integrate(fn, 0, 2)
>> print "Area of cos fn:", integrate(math.cos, 1, 2)

>
> The point was a pedagogic suggestion, i.e.

I understood your point. I just found it interesting since I've been
trying to extend my math (for use with python) skills in this area.

>"Try taking your
> friend along this path." I wasn't trying to do a particularly
> good job integrating, simply trying to show how you could
> motivate first-class functions by showing a "useful" and
> "fun" (at least to an engineer) function that cries out
> for higher order functions. In my experience engineers
> often want a "reason its useful" before engaging with an
> idea. I'll bet that after a few such experiences he'll see
> how passing around functions and (later) making functions from
> from functions is a great tool to have in his toolbox. Once
> he sees that, there will be no problem.

Yes, I agree. Another useful thing I've found is to store functions in a
dictionary and call them (dispatching) based on some data value.

Ron

Scott David Daniels
Guest
Posts: n/a

 09-23-2007
> Scott David Daniels wrote:
>>> def integrate(fn, x1, x2, n=100):...

>> The point was a pedagogic suggestion, ...

> I understood your point. I just found it interesting since I've been
> trying to extend my math (for use with python) skills in this area.

Ah, sorry. I had realized I wasn't explicit in my first message.
Yes, a perfectly fine integration.

You can then (and this is a major jump to get used to):
import functools

Sine = functools.partial(integrate, math.cos, 0.0, n=100)

Similarly, you can define a derivative that will behave fairly well,
all without examining the definition of the function being operated
upon.

-Scott

Guest
Posts: n/a

 09-23-2007

Scott David Daniels wrote:
>> Scott David Daniels wrote:
>>>> def integrate(fn, x1, x2, n=100):...
>>> The point was a pedagogic suggestion, ...

>> I understood your point. I just found it interesting since I've been
>> trying to extend my math (for use with python) skills in this area.

>
> Ah, sorry. I had realized I wasn't explicit in my first message.

Yes, I wasn't trying to correct you. I'm sorry if it came across that way.

> Yes, a perfectly fine integration.

There's still something about it that bothers me. I think it may be the
n=100 rather than delta='.0001', or some other way to specify the minimal
error. (Yes, it's a bit off topic.)

> You can then (and this is a major jump to get used to):
> import functools
>
> Sine = functools.partial(integrate, math.cos, 0.0, n=100)

I haven't played around with .partial yet. I wonder if it could be used in
dispatching situations where the function signatures differ?

> Similarly, you can define a derivative that will behave fairly well,
> all without examining the definition of the function being operated
> upon.

I'll get around to doing that at some point.

I also have a class that solves equations that takes a function in a
similar way. It uses the same method used by HP calculators to solve TVM
equations.

Cheers,
Ron