[Python-ideas] Vectorization [was Re: Add list.join() please]

David Mertz mertz at gnosis.cx
Sun Feb 3 17:58:26 EST 2019


>
> >>> len(v)  # Number of elements in the Vector `v`
>

Agreed, this should definitely be the behavior.  So how do we get a vector
of lengths of each element?


> >>> # Compute the length of each element of the Vector `v`
> >>> v.apply(len)
> >>> v @ len
>

Also possible is:

    v.len()

We couldn't do that for every possible function, but this one is special
inasmuch as we expect the items each to have a .__len__() but don't want to
spell the dunders. Likewise for just a handful of other methods/functions.

The key different though is that *I* would want to a way to use both
methods already attached to the objects/items. in a vector and also a
generic user-provided function that operates on the items. I guess you
disagree about "method pass-through" but it reads more elegantly to me:

>>> # Replace all "a" by "b"
> >>> v.apply(lambda s: s.replace("a", "b"))
> >>> v @ (lambda s: s.replace("a", "b"))
>

Compare these with:

    v.replace("a", "b")

Since we already know v is a Vector, we kinda expect methods to be
vectorized.  This feels like the "least surprise" and also the least extra
code.  Moreover, spelling chained methods with many .appy() calls (even if
spelled '@') feels very cumbersome:

(A) v.apply(lambda s: s.replace("a", "b")).apply(str.upper).apply(lambda s:
s.count("B"))

(B) v @ lambda s: s.replace("a", "b") @ str.upper  @ lambda s: s.count("B")

(C) v.replace("a","b").upper().count("B")

Between these, (C) feels a heck of a lot more intuitive and readable to me.

Here we put an emphasis on the methods already attached to objects.  But
this isn't terrible:

    def double(x):
        return x*2
    v.apply(double).replace("a","b").upper().count("B")

In @ notation it would be:

    v @ double @ lambda s: s.replace("a", "b") @ str.upper  @ lambda s:
s.count("B")

The 'double' is slightly easier, but the method calls are much worse.

MOREOVER, the model of "everything is apply/@" falls down terribly once we
have duck typing.

This is a completely silly example, but it's one that apply/@ simply cannot
address because it assumes it is the SAME function/method applied to each
object:

>>> class CaseInsensitiveStr(str):
...     def replace(self, old, new):
...         return str.upper(self).replace(old.upper(), new.upper())
...
>>> l = ['Monday', CaseInsensitiveStr('Tuesday'), 'Wednesday']
>>> v = Vector(l)
>>> v.replace('day', 'time')
<Vector of ['Montime', 'TUESTIME', 'Wednestime']>




-- 
Keeping medicines from the bloodstreams of the sick; food
from the bellies of the hungry; books from the hands of the
uneducated; technology from the underdeveloped; and putting
advocates of freedom in prisons.  Intellectual property is
to the 21st century what the slave trade was to the 16th.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.python.org/pipermail/python-ideas/attachments/20190203/3bafa4e4/attachment-0001.html>


More information about the Python-ideas mailing list