<div dir="ltr"><div dir="ltr"><div class="gmail_quote"><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div dir="ltr"><div>>>> len(v)  # Number of elements in the Vector `v`<br></div></div></blockquote><div><br></div><div>Agreed, this should definitely be the behavior.  So how do we get a vector of lengths of each element?</div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div dir="ltr"><div></div><div>>>> # Compute the length of each element of the Vector `v`<br></div><div>>>> v.apply(len)<br></div><div>>>> v @ len<br></div></div></blockquote><div><br></div><div>Also possible is:</div><div><br></div><div>    v.len()</div><div><br></div><div>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.</div><div><br></div><div>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:</div><div><br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div dir="ltr"><div>>>> # Replace all "a" by "b"<br></div><div>>>> v.apply(lambda s: s.replace("a", "b"))</div><div>>>> v @ (lambda s: s.replace("a", "b"))</div></div></blockquote><div><br></div><div>Compare these with:</div><div><br></div><div>    v.replace("a", "b")</div><div><br></div><div>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:</div><div><br></div><div>(A) v.apply(lambda s: s.replace("a", "b")).apply(str.upper).apply(lambda s: s.count("B"))</div><div><br></div><div>(B) v @ lambda s: s.replace("a", "b") @ str.upper  @ lambda s: s.count("B")</div><div class="gmail_quote"><br></div>(C) v.replace("a","b").upper().count("B")</div><div class="gmail_quote"><br></div><div class="gmail_quote">Between these, (C) feels a heck of a lot more intuitive and readable to me.</div><div class="gmail_quote"><br></div><div class="gmail_quote">Here we put an emphasis on the methods already attached to objects.  But this isn't terrible:</div><div class="gmail_quote"><br></div><div class="gmail_quote">    def double(x): </div><div class="gmail_quote">        return x*2</div><div class="gmail_quote">    v.apply(double).replace("a","b").upper().count("B")  </div><div class="gmail_quote"><br></div><div class="gmail_quote">In @ notation it would be:</div><div class="gmail_quote"><br></div><div class="gmail_quote">    v @ double @ lambda s: s.replace("a", "b") @ str.upper  @ lambda s: s.count("B")</div><br class="gmail-Apple-interchange-newline"><div class="gmail_quote"><div>The 'double' is slightly easier, but the method calls are much worse.</div><div><br></div><div>MOREOVER, the model of "everything is apply/@" falls down terribly once we have duck typing.</div><div><br></div><div>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:</div><div><br></div></div></div><blockquote style="margin:0 0 0 40px;border:none;padding:0px"><div><div class="gmail_quote"><div><div><font face="monospace, monospace">>>> class CaseInsensitiveStr(str):</font></div></div></div></div><div><div class="gmail_quote"><div><div><font face="monospace, monospace">...     def replace(self, old, new):</font></div></div></div></div><div><div class="gmail_quote"><div><div><font face="monospace, monospace">...         return str.upper(self).replace(old.upper(), new.upper())</font></div></div></div></div><div><div class="gmail_quote"><div><div><font face="monospace, monospace">...</font></div></div></div></div><div><div class="gmail_quote"><div><div><font face="monospace, monospace">>>> l = ['Monday', CaseInsensitiveStr('Tuesday'), 'Wednesday']</font></div></div></div></div><div><div class="gmail_quote"><div><div><font face="monospace, monospace">>>> v = Vector(l)</font></div></div></div></div><div><div class="gmail_quote"><div><div><font face="monospace, monospace">>>> v.replace('day', 'time')</font></div></div></div></div><div><div class="gmail_quote"><div><div><font face="monospace, monospace"><Vector of ['Montime', 'TUESTIME', 'Wednestime']></font></div></div></div></div></blockquote><div dir="ltr"><div class="gmail_quote"><div><br></div><div><br></div><div><br></div></div>-- <br><div dir="ltr" class="gmail_signature">Keeping medicines from the bloodstreams of the sick; food <br>from the bellies of the hungry; books from the hands of the <br>uneducated; technology from the underdeveloped; and putting <br>advocates of freedom in prisons.  Intellectual property is<br>to the 21st century what the slave trade was to the 16th.<br></div></div></div>