Lambda binding solved (LONG) (was: Python has a little lambda ... )

Steven D. Majewski (sdm7g@elvis.med.virginia.edu)
Fri, 25 Feb 1994 04:53:35 -0500

Here are changes to funcobject.c to make function.__members__ read/write
instead of ReadOnly ( These mods were originally done to insert documentation
strings into functions - I don't remember if I ever posted them on the list.
If I did, then here they are again in a slightly different version. )

*** /usr/local/src/Python/Python/Objects/funcobject.c Fri Feb 25 01:41:44 1994
--- /usr/local/src/Python/Python/Objects/funcobject.c.0 Fri Feb 25 00:56:06 1994
***************
*** 40,48 ****
INCREF(globals);
op->func_globals = globals;
op->func_name = ((codeobject*)(op->func_code))->co_name;
- #ifdef SDM7G
- op->func_doc = ((codeobject*)(op->func_code))->co_name;
- #endif
INCREF(op->func_name);
}
return (object *)op;
--- 40,45 ----
***************
*** 76,90 ****

static struct memberlist func_memberlist[] = {
{"func_code", T_OBJECT, OFF(func_code), READONLY},
- #ifdef SDM7G
- {"func_globals",T_OBJECT, OFF(func_globals), 0},
- #else
{"func_globals",T_OBJECT, OFF(func_globals), READONLY},
- #endif
{"func_name", T_OBJECT, OFF(func_name), READONLY},
- #ifdef SDM7G
- {"func_doc", T_OBJECT, OFF(func_doc), 0},
- #endif
{NULL} /* Sentinel */
};

--- 73,80 ----
***************
*** 96,112 ****
return getmember((char *)op, func_memberlist, name);
}

- #ifdef SDM7G
- static object *
- func_setattr(op, name, v)
- funcobject *op;
- char *name;
- object *v;
- {
- return setmember((char *)op, func_memberlist, name, v);
- }
- #endif
-
static void
func_dealloc(op)
funcobject *op;
--- 86,91 ----
***************
*** 160,170 ****
(destructor)func_dealloc, /*tp_dealloc*/
0, /*tp_print*/
(getattrfunc)func_getattr, /*tp_getattr*/
! #ifdef SDM7G
! (setattrfunc)func_setattr, /*tp_setattr*/
! #else
! 0, /*tp_setattr*/
! #endif
(cmpfunc)func_compare, /*tp_compare*/
(reprfunc)func_repr, /*tp_repr*/
0, /*tp_as_number*/
--- 139,145 ----
(destructor)func_dealloc, /*tp_dealloc*/
0, /*tp_print*/
(getattrfunc)func_getattr, /*tp_getattr*/
! 0, /*tp_setattr*/
(cmpfunc)func_compare, /*tp_compare*/
(reprfunc)func_repr, /*tp_repr*/
0, /*tp_as_number*/

#----------------
# Now we need two python functions:
# One to merge 2 or more dictionaries,
# and another to replace the functions global namespace
# with a merged dictionary.
#

# scope.py
def merge_dicts( *ds ):
# last name had precedence and overwrites first.
newd = {}
for d in ds:
for k in d.keys():
newd[k] = d[k]
return newd

# can't do this without the above mods.
# normally function.__members__ are READONLY attributes.

def bind( f, d ):
f.func_globals = merge_dicts( f.func_globals, d )
return f

python
Python 1.0.1 (Feb 19 1994)
Copyright 1991-1994 Stichting Mathematisch Centrum, Amsterdam
>>> from scope import *
>>> dir()
['__name__', 'bind', 'lf', 'merge_dicts']
>>>lf = lambda x : x + a
< anon. func. object. > # or something like that
>>> lf( -1 ) # fail, no binding for 'a' !
Traceback (innermost last):
File "<stdin>", line 1
File "./scope.py", line 15
lf = lambda x : x + a
NameError: a
>>> bind( lf, { 'a':10000 } )( -1 ) # bind a, now it works
9999

# but since I don't know how to clone a new function from bind
# it modifies the old one, so it's permanently changed.

>>> lf( -1 )
9999
>>> lf( 1 )
10001
>>>

# But that's OK if it's just a lambda expression anyway.
# ( Maybe a new lambda would work for cloning, but I wasn't
# ready to tackle another layer of indirection yet! )
#
# Now, the failed attempt at collect using map works
# (* Do you remember back that far in this thread? *)
# when we bind the input value into the globals.
#

from scope import bind

def collect2( seq, attr ):
return map( bind(lambda obj: getattr( obj, attr ), {'attr':attr}), seq )

----

All this demonstrates that Python's functions are really closures
( function + environment/bindings ). Ok - we nearly have first
class closures. If we do the same thing for frames, and find a
way to manipulate continuations, will we have Scheme yet? ;-)

- Steve Majewski (804-982-0831) <sdm7g@Virginia.EDU>
- UVA Department of Molecular Physiology and Biological Physics