[Patches] Proposal To Modifying Map Function in 1.6
Zaur Shibzoukhov
sz@zmail.ru
Fri, 14 Apr 2000 18:35:52 +0400
Proposal To Modifying Map Function in 1.6
-----------------------------------------
map(func, List_1, List_2, ..., List_n) use the following rule now:
if len(List_i) < max(len(List_1),...,len(List_n)) then
List_i[Ni]=None, List_i[Ni+1]=None, ...
Ni=len(List_i)
I propose to change this rule to another:
if len(List_i) < max(len(List_1),...,len(List_n)) then
List_i[j]=List_i[j (mod Ni)], List_i[j]=List_i[j+1 (mod Ni)],
... (*)
Ni=len(List_i)
Why?
Main reason: I can't use map without lambda expression in the following
common case:
map(func, List, arg ) (1)
or
map(func, arg, List) (2)
where
func -- function with two arguments, arg -- not sequense.
Now I must do
map(lambda x,y=arg: func(x,y), List) (1')
or
map(lambda y,x=arg: func(x,y), List) (2')
With rule (*) I can write:
map(func, List, [arg])
After this change I also can repeat lists of smaller length in map's
arguments.
I think that it can improve functionality of map.
For example:
Ls=[list_1, ..., list_N]
map(append, Ls, [a,b]) ->
[list_1+[a],list_2+[b],list_3+[a],,list_4+[b], ...]
or
Ls = [func_1, ..., func_N]
map(apply, Ls, [args])
instead of
map(lambda f,args=args: apply(f, args), Ls)
and others ...
This modification allow to prevent using lambda expression
in map calls in some cases.
Here is an easy "patch" to map (for source of Python 1.5.2)
static PyObject *
builtin_map(self, args)
PyObject *self;
PyObject *args;
{
typedef struct {
PyObject *seq;
PySequenceMethods *sqf;
int len;
} sequence;
PyObject *func, *result;
sequence *seqs = NULL, *sqp;
int n, len;
register int i, j;
n = PyTuple_Size(args);
if (n < 2) {
PyErr_SetString(PyExc_TypeError,
"map() requires at least two args");
return NULL;
}
func = PyTuple_GetItem(args, 0);
n--;
if (func == Py_None && n == 1) {
/* map(None, S) is the same as list(S). */
return PySequence_List(PyTuple_GetItem(args, 1));
}
if ((seqs = PyMem_NEW(sequence, n)) == NULL) {
PyErr_NoMemory();
goto Fail_2;
}
for (len = 0, i = 0, sqp = seqs; i < n; ++i, ++sqp) {
int curlen;
PySequenceMethods *sqf;
if ((sqp->seq = PyTuple_GetItem(args, i + 1)) == NULL)
goto Fail_2;
sqp->sqf = sqf = sqp->seq->ob_type->tp_as_sequence;
if (sqf == NULL ||
sqf->sq_length == NULL ||
sqf->sq_item == NULL)
{
static char errmsg[] =
"argument %d to map() must be a sequence
object";
char errbuf[sizeof(errmsg) + 25];
sprintf(errbuf, errmsg, i+2);
PyErr_SetString(PyExc_TypeError, errbuf);
goto Fail_2;
}
if ((curlen = sqp->len =
(*sqp->sqf->sq_length)(sqp->seq)) < 0)
goto Fail_2;
if (curlen > len)
len = curlen;
}
if ((result = (PyObject *) PyList_New(len)) == NULL)
goto Fail_2;
for (i = 0; ; ++i) {
PyObject *alist, *item=NULL, *value;
int any = 0;
if (func == Py_None && n == 1)
alist = NULL;
else {
if ((alist = PyTuple_New(n)) == NULL)
goto Fail_1;
}
for (j = 0, sqp = seqs; j < n; ++j, ++sqp) {
if (sqp->len < 0) {
- Py_INCREF(Py_None);
- item = Py_None;
+ item = (*sqp->sqf->sq_item)(sqp->seq, i
% - sqp->len);
}
else {
item = (*sqp->sqf->sq_item)(sqp->seq,
i);
if (item == NULL) {
if (PyErr_ExceptionMatches(
PyExc_IndexError))
{
PyErr_Clear();
- Py_INCREF(Py_None);
- item = Py_None;
+ item =
(*sqp->sqf->sq_item)(sqp->seq, i % sqp->len);
- sqp->len = -1;
+ sqp->len = - sqp->len;
}
else {
goto Fail_0;
}
}
else
any = 1;
}
if (!alist)
break;
if (PyTuple_SetItem(alist, j, item) < 0) {
Py_DECREF(item);
goto Fail_0;
}
continue;
Fail_0:
Py_XDECREF(alist);
goto Fail_1;
}
if (!alist)
alist = item;
if (!any) {
Py_DECREF(alist);
break;
}
if (func == Py_None)
value = alist;
else {
value = PyEval_CallObject(func, alist);
Py_DECREF(alist);
if (value == NULL)
goto Fail_1;
}
if (i >= len) {
int status = PyList_Append(result, value);
Py_DECREF(value);
if (status < 0)
goto Fail_1;
}
else {
if (PyList_SetItem(result, i, value) < 0)
goto Fail_1;
}
}
if (i < len && PyList_SetSlice(result, i, len, NULL) < 0)
goto Fail_1;
PyMem_DEL(seqs);
return result;
Fail_1:
Py_DECREF(result);
Fail_2:
if (seqs) PyMem_DEL(seqs);
return NULL;
}
Zaur Shibzoukhov
sz@zmail.ru
-----------------------------------------------
Get Your e-mail at http://zmail.ru