Skip to content

Commit 24835a3

Browse files
committed
Extract imap from itertools.java.
1 parent 4322a1c commit 24835a3

2 files changed

Lines changed: 112 additions & 55 deletions

File tree

Lines changed: 111 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,111 @@
1+
/* Copyright (c) Jython Developers */
2+
package org.python.modules.itertools;
3+
4+
import org.python.core.ArgParser;
5+
import org.python.core.Py;
6+
import org.python.core.PyIterator;
7+
import org.python.core.PyObject;
8+
import org.python.core.PyString;
9+
import org.python.core.PyTuple;
10+
import org.python.core.PyType;
11+
import org.python.expose.ExposedClassMethod;
12+
import org.python.expose.ExposedGet;
13+
import org.python.expose.ExposedNew;
14+
import org.python.expose.ExposedMethod;
15+
import org.python.expose.ExposedType;
16+
17+
import java.util.ArrayList;
18+
19+
@ExposedType(name = "itertools.imap", base = PyObject.class)
20+
public class imap extends PyObject {
21+
22+
public static final PyType TYPE = PyType.fromClass(imap.class);
23+
private PyIterator iter;
24+
25+
@ExposedGet
26+
public static PyString __doc__ = new PyString(
27+
"'map(func, *iterables) --> imap object\n\nMake an iterator that computes the "
28+
+ "function using arguments from\neach of the iterables.\tLike map() except that it returns\n"
29+
+ "an iterator instead of a list and that it stops when the shortest\niterable is exhausted "
30+
+ "instead of filling in None for shorter\niterables.");
31+
32+
public imap() {
33+
super();
34+
}
35+
36+
public imap(PyType subType) {
37+
super(subType);
38+
}
39+
40+
public imap(PyObject... args) {
41+
super();
42+
imap___init__(args);
43+
}
44+
45+
46+
/**
47+
* Works as <code>__builtin__.map()</code> but returns an iterator instead of a list. (Code in
48+
* this method is based on __builtin__.map()).
49+
*/
50+
@ExposedNew
51+
@ExposedMethod
52+
final void imap___init__(final PyObject[] args, String[] kwds) {
53+
if (kwds.length > 0) {
54+
throw Py.TypeError(String.format("imap does not take keyword arguments"));
55+
}
56+
imap___init__(args);
57+
}
58+
59+
private void imap___init__(final PyObject[] argstar) {
60+
if (argstar.length < 2) {
61+
throw Py.TypeError("imap requires at least two arguments");
62+
}
63+
final int n = argstar.length - 1;
64+
final PyObject func = argstar[0];
65+
66+
final PyObject[] iterables = new PyObject[n];
67+
for (int j = 0; j < n; j++) {
68+
iterables[j] = Py.iter(argstar[j + 1], "argument " + (j + 1)
69+
+ " to imap() must support iteration");
70+
}
71+
iter = new PyIterator() {
72+
PyObject[] args = new PyObject[n];
73+
74+
PyObject element = null;
75+
76+
public PyObject __iternext__() {
77+
78+
for (int i = 0; i < n; i++) {
79+
if ((element = iterables[i].__iternext__()) != null) {
80+
// collect the arguments for the func
81+
args[i] = element;
82+
} else {
83+
// break iteration
84+
return null;
85+
}
86+
}
87+
if (func == Py.None) {
88+
// if None is supplied as func we just return what's in
89+
// the iterable(s)
90+
if (n == 1) {
91+
return args[0];
92+
} else {
93+
return new PyTuple(args.clone());
94+
}
95+
} else {
96+
return func.__call__(args);
97+
}
98+
}
99+
};
100+
}
101+
102+
@ExposedMethod
103+
public PyObject __iter__() {
104+
return iter;
105+
}
106+
107+
@ExposedMethod
108+
public PyObject next() {
109+
return iter.next();
110+
}
111+
}

src/org/python/modules/itertools/itertools.java

Lines changed: 1 addition & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,7 @@ public static void classDictInit(PyObject dict) {
8383
dict.__setitem__("__name__", new PyString("itertools"));
8484
dict.__setitem__("__doc__", __doc__);
8585
dict.__setitem__("chain", chain.TYPE);
86+
dict.__setitem__("imap", imap.TYPE);
8687

8788
// Hide from Python
8889
dict.__setitem__("classDictInit", null);
@@ -227,61 +228,6 @@ public PyString __repr__() {
227228
};
228229
}
229230

230-
public static PyString __doc__imap = new PyString(
231-
"'map(func, *iterables) --> imap object\n\nMake an iterator that computes the "
232-
+ "function using arguments from\neach of the iterables.\tLike map() except that it returns\n"
233-
+ "an iterator instead of a list and that it stops when the shortest\niterable is exhausted "
234-
+ "instead of filling in None for shorter\niterables.");
235-
236-
/**
237-
* Works as <code>__builtin__.map()</code> but returns an iterator instead of a list. (Code in
238-
* this method is based on __builtin__.map()).
239-
*/
240-
public static PyIterator imap(PyObject[] argstar) {
241-
final int n = argstar.length - 1;
242-
if (n < 1) {
243-
throw Py.TypeError("imap requires at least two arguments");
244-
}
245-
246-
final PyObject callable = argstar[0];
247-
final PyObject[] iters = new PyObject[n];
248-
249-
for (int j = 0; j < n; j++) {
250-
iters[j] = Py.iter(argstar[j + 1], "argument " + (j + 1)
251-
+ " to imap() must support iteration");
252-
}
253-
254-
return new PyIterator() {
255-
PyObject[] args = new PyObject[n];
256-
257-
PyObject element = null;
258-
259-
public PyObject __iternext__() {
260-
261-
for (int i = 0; i < n; i++) {
262-
if ((element = iters[i].__iternext__()) != null) {
263-
// collect the arguments for the callable
264-
args[i] = element;
265-
} else {
266-
// break iteration
267-
return null;
268-
}
269-
}
270-
if (callable == Py.None) {
271-
// if None is supplied as callable we just return what's in
272-
// the iterable(s)
273-
if (n == 1) {
274-
return args[0];
275-
} else {
276-
return new PyTuple(args.clone());
277-
}
278-
} else {
279-
return callable.__call__(args);
280-
}
281-
}
282-
};
283-
}
284-
285231
public static PyString __doc__islice = new PyString(
286232
"islice(iterable, [start,] stop [, step]) --> islice object\n"
287233
+ "\nReturn an iterator whose next() method returns selected values from an\n"

0 commit comments

Comments
 (0)