Elementwise -//- first release -//- Element-wise (vectorized) function, method and operator support for iterables in python.

Nathan Rice nathan.alexander.rice at gmail.com
Wed Dec 21 10:07:31 EST 2011


On Tue, Dec 20, 2011 at 8:37 PM, Joshua Landau
<joshua.landau.ws at gmail.com> wrote:
> On 21 December 2011 00:24, Nathan Rice <nathan.alexander.rice at gmail.com>
> wrote:
>> efoo_res = ((efoo2.capitalize() + " little indian").split("
>> ").apply(reversed) * 2).apply("_".join) # note that you could do
>> reversed(...) instead, I just like to read left to right
>> efoo_res.parent.parent.parent # same as ((efoo2.capitalize() + "
>> little indian").split(" ") in case you need to debug something and
>> want to look at intermediate values
>
> How is any of this better than the elementwise operators ("~")? People
> should be able to expect len(x) to always return a number or raise an error.
> I know it's not part of the spec, but a lot breaks without these guarantees.
> When "str(x)" isn't a string, all the formatting code breaks*. And when the
> other suggestion ("~str(x)" or "str~(x)" or something similar) has all the
> benifits and none of the drawbacks, why should I use this?

len() will always return a number or raise an error, just like the
type functions (bool/int/etc) return that type or raise an error.  The
interpreter guarantees that for you.

This has a couple of advantages over element-wise operators:

1. Because everything is handled in terms of generator chains, all
operations on an ElementwiseProxy are evaluated lazily.  With
element-wise operator overloading you would need to perform each
operation immediately.

2. As a result of #1, you can "undo" operations you perform on an
ElementwiseProxy with the parent property.

3. This still works if the person who created the class you're working
with doesn't add support for element-wise operators.  Sure, you could
monkey patch their code, but that can lead to other problems down the
line.

4. There isn't an obvious/intuitive character for element-wise
versions of operators, and fewer symbols is better than more IMHO
(see: Perl).  Also, if you use the ElementwiseProxyMixin, you can
sprinkle element-wise stuff in neatly just by using "variable.each"
where you would use "~" in your examples.

> Upon this implementation I take back my comment on the whole typing thing.
> Your title just really confused me.
>
> * You can't just make functions non-elementwise unless called through
> ".apply" either:
> def str(x): return x.__str__()

str is one of the special cases (along with repr, unicode, int, float,
long, bool, etc).  These can't ever be elementwise in CPython (I don't
know that this holds in other interpreters).

The idea is that you use ElementwiseProxy(x) or preferably x.each,
work with your data in an element-wise capacity as needed, then list()
or iter() back out.  I think it should be a deliberate change of
context.  Interleaving the proxy (say via x.each) in mostly scalar
expressions works, but wasn't the use case I designed it for, and in
those circumstances it doesn't really offer anything above the map
function.

Nathan



More information about the Python-list mailing list