@@ -5,189 +5,198 @@ Last-Modified: $Date$
5
5
Author: gvwilson@ddj.com (Greg Wilson)
6
6
Status: Deferred
7
7
Type: Standards Track
8
+ Content-Type: text/x-rst
8
9
Created: 15-Jul-2000
9
10
Python-Version: 2.1
10
11
Post-History:
11
12
12
13
13
14
Introduction
15
+ ============
14
16
15
- This PEP describes a proposal to define "@" (pronounced "across")
16
- as a new outer product operator in Python 2.2. When applied to
17
- sequences (or other iterable objects), this operator will combine
18
- their iterators, so that:
17
+ This PEP describes a proposal to define ``@`` (pronounced "across")
18
+ as a new outer product operator in Python 2.2. When applied to
19
+ sequences (or other iterable objects), this operator will combine
20
+ their iterators, so that: :
19
21
20
- for (i, j) in S @ T:
21
- pass
22
+ for (i, j) in S @ T:
23
+ pass
22
24
23
- will be equivalent to:
25
+ will be equivalent to: :
24
26
25
- for i in S:
26
- for j in T:
27
- pass
27
+ for i in S:
28
+ for j in T:
29
+ pass
28
30
29
- Classes will be able to overload this operator using the special
30
- methods " __across__", " __racross__" , and " __iacross__" . In
31
- particular, the new Numeric module (PEP 209) will overload this
32
- operator for multi-dimensional arrays to implement matrix
33
- multiplication.
31
+ Classes will be able to overload this operator using the special
32
+ methods `` __across__``, `` __racross__`` , and `` __iacross__`` . In
33
+ particular, the new Numeric module (PEP 209) will overload this
34
+ operator for multi-dimensional arrays to implement matrix
35
+ multiplication.
34
36
35
37
36
38
Background
37
-
38
- Number-crunching is now just a small part of computing, but many
39
- programmers --- including many Python users --- still need to
40
- express complex mathematical operations in code. Most numerical
41
- languages, such as APL, Fortran-90, MATLAB, IDL, and Mathematica,
42
- therefore provide two forms of the common arithmetic operators.
43
- One form works element-by-element, e.g. multiplies corresponding
44
- elements of its matrix arguments. The other implements the
45
- "mathematical" definition of that operation, e.g. performs
46
- row-column matrix multiplication.
47
-
48
- Zhu and Lielens have proposed doubling up Python's operators in
49
- this way [1]. Their proposal would create six new binary infix
50
- operators, and six new in-place operators.
51
-
52
- The original version of this proposal was much more conservative.
53
- The author consulted the developers of GNU Octave [2], an open
54
- source clone of MATLAB. Its developers agreed that providing an
55
- infix operator for matrix multiplication was important: numerical
56
- programmers really do care whether they have to write "mmul(A,B)"
57
- instead of "A op B".
58
-
59
- On the other hand, when asked how important it was to have infix
60
- operators for matrix solution and other operations, Prof. James
61
- Rawlings replied [3]:
62
-
63
- I DON'T think it's a must have, and I do a lot of matrix
64
- inversion. I cannot remember if its A\b or b\A so I always
65
- write inv(A)*b instead. I recommend dropping \.
66
-
67
- Based on this discussion, and feedback from students at the US
68
- national laboratories and elsewhere, we recommended adding only
69
- one new operator, for matrix multiplication, to Python.
39
+ ==========
40
+
41
+ Number-crunching is now just a small part of computing, but many
42
+ programmers --- including many Python users --- still need to
43
+ express complex mathematical operations in code. Most numerical
44
+ languages, such as APL, Fortran-90, MATLAB, IDL, and Mathematica,
45
+ therefore provide two forms of the common arithmetic operators.
46
+ One form works element-by-element, e.g. multiplies corresponding
47
+ elements of its matrix arguments. The other implements the
48
+ "mathematical" definition of that operation, e.g. performs
49
+ row-column matrix multiplication.
50
+
51
+ Zhu and Lielens have proposed doubling up Python's operators in
52
+ this way [1]_. Their proposal would create six new binary infix
53
+ operators, and six new in-place operators.
54
+
55
+ The original version of this proposal was much more conservative.
56
+ The author consulted the developers of GNU Octave [2]_, an open
57
+ source clone of MATLAB. Its developers agreed that providing an
58
+ infix operator for matrix multiplication was important: numerical
59
+ programmers really do care whether they have to write ``mmul(A,B)``
60
+ instead of ``A op B``.
61
+
62
+ On the other hand, when asked how important it was to have infix
63
+ operators for matrix solution and other operations, Prof. James
64
+ Rawlings replied [3]_:
65
+
66
+ I DON'T think it's a must have, and I do a lot of matrix
67
+ inversion. I cannot remember if its A\b or b\A so I always
68
+ write inv(A)*b instead. I recommend dropping \.
69
+
70
+ Based on this discussion, and feedback from students at the US
71
+ national laboratories and elsewhere, we recommended adding only
72
+ one new operator, for matrix multiplication, to Python.
70
73
71
74
72
75
Iterators
76
+ =========
73
77
74
- The planned addition of iterators to Python 2.2 opens up a broader
75
- scope for this proposal. As part of the discussion of PEP 201,
76
- Lockstep Iteration[4], the author of this proposal conducted an
77
- informal usability experiment[5]. The results showed that users
78
- are psychologically receptive to "cross-product" loop syntax. For
79
- example, most users expected:
78
+ The planned addition of iterators to Python 2.2 opens up a broader
79
+ scope for this proposal. As part of the discussion of PEP 201,
80
+ Lockstep Iteration [4]_ , the author of this proposal conducted an
81
+ informal usability experiment [5]_ . The results showed that users
82
+ are psychologically receptive to "cross-product" loop syntax. For
83
+ example, most users expected: :
80
84
81
- S = [10, 20, 30]
82
- T = [1, 2, 3]
83
- for x in S; y in T:
84
- print x+y,
85
+ S = [10, 20, 30]
86
+ T = [1, 2, 3]
87
+ for x in S; y in T:
88
+ print x+y,
85
89
86
- to print " 11 12 13 21 22 23 31 32 33" . We believe that users will
87
- have the same reaction to:
90
+ to print `` 11 12 13 21 22 23 31 32 33`` . We believe that users will
91
+ have the same reaction to: :
88
92
89
- for (x, y) in S @ T:
90
- print x+y
93
+ for (x, y) in S @ T:
94
+ print x+y
91
95
92
- i.e. that they will naturally interpret this as a tidy way to
93
- write loop nests.
96
+ i.e. that they will naturally interpret this as a tidy way to
97
+ write loop nests.
94
98
95
- This is where iterators come in. Actually constructing the
96
- cross-product of two (or more) sequences before executing the loop
97
- would be very expensive. On the other hand, "@" could be defined
98
- to get its arguments' iterators, and then create an outer iterator
99
- which returns tuples of the values returned by the inner
100
- iterators.
99
+ This is where iterators come in. Actually constructing the
100
+ cross-product of two (or more) sequences before executing the loop
101
+ would be very expensive. On the other hand, ``@`` could be defined
102
+ to get its arguments' iterators, and then create an outer iterator
103
+ which returns tuples of the values returned by the inner
104
+ iterators.
101
105
102
106
103
107
Discussion
108
+ ==========
104
109
105
- 1. Adding a named function "across" would have less impact on
106
- Python than a new infix operator. However, this would not make
107
- Python more appealing to numerical programmers, who really do
108
- care whether they can write matrix multiplication using an
109
- operator, or whether they have to write it as a function call.
110
+ 1. Adding a named function "across" would have less impact on
111
+ Python than a new infix operator. However, this would not make
112
+ Python more appealing to numerical programmers, who really do
113
+ care whether they can write matrix multiplication using an
114
+ operator, or whether they have to write it as a function call.
110
115
111
- 2. "@" would have be chainable in the same way as comparison
112
- operators, i.e.:
116
+ 2. ``@`` would have be chainable in the same way as comparison
117
+ operators, i.e.: :
113
118
114
- (1, 2) @ (3, 4) @ (5, 6)
119
+ (1, 2) @ (3, 4) @ (5, 6)
115
120
116
- would have to return (1, 3, 5) ... (2, 4, 6), and *not*
117
- ((1, 3), 5) ... ((2, 4), 6). This should not require special
118
- support from the parser, as the outer iterator created by the
119
- first "@" could easily be taught how to combine itself with
120
- ordinary iterators.
121
+ would have to return `` (1, 3, 5) ... (2, 4, 6)`` , and *not*
122
+ `` ((1, 3), 5) ... ((2, 4), 6)``` . This should not require special
123
+ support from the parser, as the outer iterator created by the
124
+ first ``@`` could easily be taught how to combine itself with
125
+ ordinary iterators.
121
126
122
- 3. There would have to be some way to distinguish restartable
123
- iterators from ones that couldn't be restarted. For example,
124
- if S is an input stream (e.g. a file), and L is a list, then " S
125
- @ L" is straightforward, but " L @ S" is not, since iteration
126
- through the stream cannot be repeated. This could be treated
127
- as an error, or by having the outer iterator detect
128
- non-restartable inner iterators and cache their values.
127
+ 3. There would have to be some way to distinguish restartable
128
+ iterators from ones that couldn't be restarted. For example,
129
+ if ``S`` is an input stream (e.g. a file), and ``L`` is a list, then `` S
130
+ @ L`` is straightforward, but `` L @ S`` is not, since iteration
131
+ through the stream cannot be repeated. This could be treated
132
+ as an error, or by having the outer iterator detect
133
+ non-restartable inner iterators and cache their values.
129
134
130
- 4. Whiteboard testing of this proposal in front of three novice
131
- Python users (all of them experienced programmers) indicates
132
- that users will expect:
135
+ 4. Whiteboard testing of this proposal in front of three novice
136
+ Python users (all of them experienced programmers) indicates
137
+ that users will expect: :
133
138
134
- "ab" @ "cd"
139
+ "ab" @ "cd"
135
140
136
- to return four strings, not four tuples of pairs of
137
- characters. Opinion was divided on what:
141
+ to return four strings, not four tuples of pairs of
142
+ characters. Opinion was divided on what: :
138
143
139
- ("a", "b") @ "cd"
144
+ ("a", "b") @ "cd"
140
145
141
- ought to return...
146
+ ought to return...
142
147
143
148
144
149
Alternatives
150
+ ============
145
151
146
- 1. Do nothing --- keep Python simple.
152
+ 1. Do nothing --- keep Python simple.
147
153
148
- This is always the default choice.
154
+ This is always the default choice.
149
155
150
- 2. Add a named function instead of an operator.
156
+ 2. Add a named function instead of an operator.
151
157
152
- Python is not primarily a numerical language; it may not be worth
153
- complexifying it for this special case. However, support for real
154
- matrix multiplication *is* frequently requested, and the proposed
155
- semantics for "@" for built-in sequence types would simplify
156
- expression of a very common idiom (nested loops).
158
+ Python is not primarily a numerical language; it may not be worth
159
+ complexifying it for this special case. However, support for real
160
+ matrix multiplication *is* frequently requested, and the proposed
161
+ semantics for ``@`` for built-in sequence types would simplify
162
+ expression of a very common idiom (nested loops).
157
163
158
- 3. Introduce prefixed forms of all existing operators, such as
159
- "~*" and "~+" , as proposed in PEP 225 [1].
164
+ 3. Introduce prefixed forms of all existing operators, such as
165
+ ``~*`` and ``~+`` , as proposed in PEP 225 [1]_ .
160
166
161
- Our objections to this are that there isn't enough demand to
162
- justify the additional complexity (see Rawlings' comments [3]),
163
- and that the proposed syntax fails the "low toner" readability
164
- test.
167
+ Our objections to this are that there isn't enough demand to
168
+ justify the additional complexity (see Rawlings' comments [3]_ ),
169
+ and that the proposed syntax fails the "low toner" readability
170
+ test.
165
171
166
172
167
173
Acknowledgments
174
+ ===============
168
175
169
- I am grateful to Huaiyu Zhu for initiating this discussion, and to
170
- James Rawlings and students in various Python courses for their
171
- discussions of what numerical programmers really care about.
176
+ I am grateful to Huaiyu Zhu for initiating this discussion, and to
177
+ James Rawlings and students in various Python courses for their
178
+ discussions of what numerical programmers really care about.
172
179
173
180
174
181
References
182
+ ==========
183
+
184
+ .. [1] PEP 225, Elementwise/Objectwise Operators, Zhu, Lielens
185
+ http://www.python.org/dev/peps/pep-0225/
175
186
176
- [1] PEP 225, Elementwise/Objectwise Operators, Zhu, Lielens
177
- http://www.python.org/dev/peps/pep-0225/
187
+ .. [2] http://bevo.che.wisc.edu/octave/
178
188
179
- [2 ] http://bevo.che.wisc.edu/octave/
189
+ .. [3 ] http://www.egroups.com/message/python-numeric/4
180
190
181
- [3] http://www.egroups.com/message/python-numeric/4
191
+ .. [4] PEP 201, Lockstep Iteration, Warsaw
192
+ http://www.python.org/dev/peps/pep-0201/
182
193
183
- [4] PEP 201, Lockstep Iteration, Warsaw
184
- http://www.python.org/dev/peps/pep-0201/
194
+ .. [5] http://mail.python.org/pipermail/python-dev/2000-July/006427.html
185
195
186
- [5] http://mail.python.org/pipermail/python-dev/2000-July/006427.html
187
196
188
197
189
-
190
- Local Variables:
191
- mode: indented-text
192
- indent-tabs-mode: nil
193
- End:
198
+ ..
199
+ Local Variables:
200
+ mode: indented-text
201
+ indent-tabs-mode: nil
202
+ End:
0 commit comments